diff --git a/breakpad/breakpad.sln b/breakpad/breakpad.sln deleted file mode 100644 index 06dc919b1..000000000 --- a/breakpad/breakpad.sln +++ /dev/null @@ -1,73 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "breakpad_common", "client\windows\common.vcxproj", "{EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_generation_client", "client\windows\crash_generation\crash_generation_client.vcxproj", "{EC847717-119A-2391-0477-212E1140082C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_generation_server", "client\windows\crash_generation\crash_generation_server.vcxproj", "{7893E300-3ED0-7F4C-158F-67EA63934C57}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exception_handler", "client\windows\handler\exception_handler.vcxproj", "{B7399F39-300F-450E-F471-9490F959D2A7}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Purify|Win32 = Purify|Win32 - Purify|x64 = Purify|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Debug|Win32.ActiveCfg = Debug|Win32 - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Debug|Win32.Build.0 = Debug|Win32 - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Debug|x64.ActiveCfg = Debug|x64 - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Debug|x64.Build.0 = Debug|x64 - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Purify|Win32.ActiveCfg = Purify|Win32 - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Purify|Win32.Build.0 = Purify|Win32 - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Purify|x64.ActiveCfg = Purify|x64 - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Purify|x64.Build.0 = Purify|x64 - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Release|Win32.ActiveCfg = Release|Win32 - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Release|Win32.Build.0 = Release|Win32 - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Release|x64.ActiveCfg = Release|x64 - {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Release|x64.Build.0 = Release|x64 - {EC847717-119A-2391-0477-212E1140082C}.Debug|Win32.ActiveCfg = Debug|Win32 - {EC847717-119A-2391-0477-212E1140082C}.Debug|Win32.Build.0 = Debug|Win32 - {EC847717-119A-2391-0477-212E1140082C}.Debug|x64.ActiveCfg = Debug|x64 - {EC847717-119A-2391-0477-212E1140082C}.Debug|x64.Build.0 = Debug|x64 - {EC847717-119A-2391-0477-212E1140082C}.Purify|Win32.ActiveCfg = Purify|Win32 - {EC847717-119A-2391-0477-212E1140082C}.Purify|Win32.Build.0 = Purify|Win32 - {EC847717-119A-2391-0477-212E1140082C}.Purify|x64.ActiveCfg = Purify|x64 - {EC847717-119A-2391-0477-212E1140082C}.Purify|x64.Build.0 = Purify|x64 - {EC847717-119A-2391-0477-212E1140082C}.Release|Win32.ActiveCfg = Release|Win32 - {EC847717-119A-2391-0477-212E1140082C}.Release|Win32.Build.0 = Release|Win32 - {EC847717-119A-2391-0477-212E1140082C}.Release|x64.ActiveCfg = Release|x64 - {EC847717-119A-2391-0477-212E1140082C}.Release|x64.Build.0 = Release|x64 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Debug|Win32.ActiveCfg = Debug|Win32 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Debug|Win32.Build.0 = Debug|Win32 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Debug|x64.ActiveCfg = Debug|x64 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Debug|x64.Build.0 = Debug|x64 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Purify|Win32.ActiveCfg = Purify|Win32 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Purify|Win32.Build.0 = Purify|Win32 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Purify|x64.ActiveCfg = Purify|x64 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Purify|x64.Build.0 = Purify|x64 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Release|Win32.ActiveCfg = Release|Win32 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Release|Win32.Build.0 = Release|Win32 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Release|x64.ActiveCfg = Release|x64 - {7893E300-3ED0-7F4C-158F-67EA63934C57}.Release|x64.Build.0 = Release|x64 - {B7399F39-300F-450E-F471-9490F959D2A7}.Debug|Win32.ActiveCfg = Debug|Win32 - {B7399F39-300F-450E-F471-9490F959D2A7}.Debug|Win32.Build.0 = Debug|Win32 - {B7399F39-300F-450E-F471-9490F959D2A7}.Debug|x64.ActiveCfg = Debug|x64 - {B7399F39-300F-450E-F471-9490F959D2A7}.Debug|x64.Build.0 = Debug|x64 - {B7399F39-300F-450E-F471-9490F959D2A7}.Purify|Win32.ActiveCfg = Purify|Win32 - {B7399F39-300F-450E-F471-9490F959D2A7}.Purify|Win32.Build.0 = Purify|Win32 - {B7399F39-300F-450E-F471-9490F959D2A7}.Purify|x64.ActiveCfg = Purify|x64 - {B7399F39-300F-450E-F471-9490F959D2A7}.Purify|x64.Build.0 = Purify|x64 - {B7399F39-300F-450E-F471-9490F959D2A7}.Release|Win32.ActiveCfg = Release|Win32 - {B7399F39-300F-450E-F471-9490F959D2A7}.Release|Win32.Build.0 = Release|Win32 - {B7399F39-300F-450E-F471-9490F959D2A7}.Release|x64.ActiveCfg = Release|x64 - {B7399F39-300F-450E-F471-9490F959D2A7}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/breakpad/client/minidump_file_writer-inl.h b/breakpad/client/minidump_file_writer-inl.h deleted file mode 100644 index 0e12e00b6..000000000 --- a/breakpad/client/minidump_file_writer-inl.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// minidump_file_writer-inl.h: Minidump file writer implementation. -// -// See minidump_file_writer.h for documentation. - -#ifndef CLIENT_MINIDUMP_FILE_WRITER_INL_H__ -#define CLIENT_MINIDUMP_FILE_WRITER_INL_H__ - -#include - -#include "client/minidump_file_writer.h" -#include "google_breakpad/common/minidump_size.h" - -namespace google_breakpad { - -template -inline bool TypedMDRVA::Allocate() { - allocation_state_ = SINGLE_OBJECT; - return UntypedMDRVA::Allocate(minidump_size::size()); -} - -template -inline bool TypedMDRVA::Allocate(size_t additional) { - allocation_state_ = SINGLE_OBJECT; - return UntypedMDRVA::Allocate(minidump_size::size() + additional); -} - -template -inline bool TypedMDRVA::AllocateArray(size_t count) { - assert(count); - allocation_state_ = ARRAY; - return UntypedMDRVA::Allocate(minidump_size::size() * count); -} - -template -inline bool TypedMDRVA::AllocateObjectAndArray(size_t count, - size_t length) { - assert(count && length); - allocation_state_ = SINGLE_OBJECT_WITH_ARRAY; - return UntypedMDRVA::Allocate(minidump_size::size() + count * length); -} - -template -inline bool TypedMDRVA::CopyIndex(unsigned int index, MDType *item) { - assert(allocation_state_ == ARRAY); - return writer_->Copy( - static_cast(position_ + index * minidump_size::size()), - item, minidump_size::size()); -} - -template -inline bool TypedMDRVA::CopyIndexAfterObject(unsigned int index, - const void *src, - size_t length) { - assert(allocation_state_ == SINGLE_OBJECT_WITH_ARRAY); - return writer_->Copy( - static_cast(position_ + minidump_size::size() - + index * length), - src, length); -} - -template -inline bool TypedMDRVA::Flush() { - return writer_->Copy(position_, &data_, minidump_size::size()); -} - -} // namespace google_breakpad - -#endif // CLIENT_MINIDUMP_FILE_WRITER_INL_H__ diff --git a/breakpad/client/minidump_file_writer.cc b/breakpad/client/minidump_file_writer.cc deleted file mode 100644 index 1e18d24ba..000000000 --- a/breakpad/client/minidump_file_writer.cc +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// minidump_file_writer.cc: Minidump file writer implementation. -// -// See minidump_file_writer.h for documentation. - -#include -#include -#include -#include -#include - -#include "client/minidump_file_writer-inl.h" -#include "common/linux/linux_libc_support.h" -#include "common/string_conversion.h" -#if __linux__ -#include "third_party/lss/linux_syscall_support.h" -#endif - -namespace google_breakpad { - -const MDRVA MinidumpFileWriter::kInvalidMDRVA = static_cast(-1); - -MinidumpFileWriter::MinidumpFileWriter() - : file_(-1), - close_file_when_destroyed_(true), - position_(0), - size_(0) { -} - -MinidumpFileWriter::~MinidumpFileWriter() { - if (close_file_when_destroyed_) - Close(); -} - -bool MinidumpFileWriter::Open(const char *path) { - assert(file_ == -1); -#if __linux__ - file_ = sys_open(path, O_WRONLY | O_CREAT | O_EXCL, 0600); -#else - file_ = open(path, O_WRONLY | O_CREAT | O_EXCL, 0600); -#endif - - return file_ != -1; -} - -void MinidumpFileWriter::SetFile(const int file) { - assert(file_ == -1); - file_ = file; - close_file_when_destroyed_ = false; -} - -bool MinidumpFileWriter::Close() { - bool result = true; - - if (file_ != -1) { - if (-1 == ftruncate(file_, position_)) { - return false; - } -#if __linux__ - result = (sys_close(file_) == 0); -#else - result = (close(file_) == 0); -#endif - file_ = -1; - } - - return result; -} - -bool MinidumpFileWriter::CopyStringToMDString(const wchar_t *str, - unsigned int length, - TypedMDRVA *mdstring) { - bool result = true; - if (sizeof(wchar_t) == sizeof(uint16_t)) { - // Shortcut if wchar_t is the same size as MDString's buffer - result = mdstring->Copy(str, mdstring->get()->length); - } else { - uint16_t out[2]; - int out_idx = 0; - - // Copy the string character by character - while (length && result) { - UTF32ToUTF16Char(*str, out); - if (!out[0]) - return false; - - // Process one character at a time - --length; - ++str; - - // Append the one or two UTF-16 characters. The first one will be non- - // zero, but the second one may be zero, depending on the conversion from - // UTF-32. - int out_count = out[1] ? 2 : 1; - size_t out_size = sizeof(uint16_t) * out_count; - result = mdstring->CopyIndexAfterObject(out_idx, out, out_size); - out_idx += out_count; - } - } - return result; -} - -bool MinidumpFileWriter::CopyStringToMDString(const char *str, - unsigned int length, - TypedMDRVA *mdstring) { - bool result = true; - uint16_t out[2]; - int out_idx = 0; - - // Copy the string character by character - while (length && result) { - int conversion_count = UTF8ToUTF16Char(str, length, out); - if (!conversion_count) - return false; - - // Move the pointer along based on the nubmer of converted characters - length -= conversion_count; - str += conversion_count; - - // Append the one or two UTF-16 characters - int out_count = out[1] ? 2 : 1; - size_t out_size = sizeof(uint16_t) * out_count; - result = mdstring->CopyIndexAfterObject(out_idx, out, out_size); - out_idx += out_count; - } - return result; -} - -template -bool MinidumpFileWriter::WriteStringCore(const CharType *str, - unsigned int length, - MDLocationDescriptor *location) { - assert(str); - assert(location); - // Calculate the mdstring length by either limiting to |length| as passed in - // or by finding the location of the NULL character. - unsigned int mdstring_length = 0; - if (!length) - length = INT_MAX; - for (; mdstring_length < length && str[mdstring_length]; ++mdstring_length) - ; - - // Allocate the string buffer - TypedMDRVA mdstring(this); - if (!mdstring.AllocateObjectAndArray(mdstring_length + 1, sizeof(uint16_t))) - return false; - - // Set length excluding the NULL and copy the string - mdstring.get()->length = - static_cast(mdstring_length * sizeof(uint16_t)); - bool result = CopyStringToMDString(str, mdstring_length, &mdstring); - - // NULL terminate - if (result) { - uint16_t ch = 0; - result = mdstring.CopyIndexAfterObject(mdstring_length, &ch, sizeof(ch)); - - if (result) - *location = mdstring.location(); - } - - return result; -} - -bool MinidumpFileWriter::WriteString(const wchar_t *str, unsigned int length, - MDLocationDescriptor *location) { - return WriteStringCore(str, length, location); -} - -bool MinidumpFileWriter::WriteString(const char *str, unsigned int length, - MDLocationDescriptor *location) { - return WriteStringCore(str, length, location); -} - -bool MinidumpFileWriter::WriteMemory(const void *src, size_t size, - MDMemoryDescriptor *output) { - assert(src); - assert(output); - UntypedMDRVA mem(this); - - if (!mem.Allocate(size)) - return false; - if (!mem.Copy(src, mem.size())) - return false; - - output->start_of_memory_range = reinterpret_cast(src); - output->memory = mem.location(); - - return true; -} - -MDRVA MinidumpFileWriter::Allocate(size_t size) { - assert(size); - assert(file_ != -1); - size_t aligned_size = (size + 7) & ~7; // 64-bit alignment - - if (position_ + aligned_size > size_) { - size_t growth = aligned_size; - size_t minimal_growth = getpagesize(); - - // Ensure that the file grows by at least the size of a memory page - if (growth < minimal_growth) - growth = minimal_growth; - - size_t new_size = size_ + growth; - if (ftruncate(file_, new_size) != 0) - return kInvalidMDRVA; - - size_ = new_size; - } - - MDRVA current_position = position_; - position_ += static_cast(aligned_size); - - return current_position; -} - -bool MinidumpFileWriter::Copy(MDRVA position, const void *src, ssize_t size) { - assert(src); - assert(size); - assert(file_ != -1); - - // Ensure that the data will fit in the allocated space - if (static_cast(size + position) > size_) - return false; - - // Seek and write the data -#if __linux__ - if (sys_lseek(file_, position, SEEK_SET) == static_cast(position)) { - if (sys_write(file_, src, size) == size) { -#else - if (lseek(file_, position, SEEK_SET) == static_cast(position)) { - if (write(file_, src, size) == size) { -#endif - return true; - } - } - - return false; -} - -bool UntypedMDRVA::Allocate(size_t size) { - assert(size_ == 0); - size_ = size; - position_ = writer_->Allocate(size_); - return position_ != MinidumpFileWriter::kInvalidMDRVA; -} - -bool UntypedMDRVA::Copy(MDRVA pos, const void *src, size_t size) { - assert(src); - assert(size); - assert(pos + size <= position_ + size_); - return writer_->Copy(pos, src, size); -} - -} // namespace google_breakpad diff --git a/breakpad/client/minidump_file_writer.h b/breakpad/client/minidump_file_writer.h deleted file mode 100644 index 538e85453..000000000 --- a/breakpad/client/minidump_file_writer.h +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// minidump_file_writer.h: Implements file-based minidump generation. It's -// intended to be used with the Google Breakpad open source crash handling -// project. - -#ifndef CLIENT_MINIDUMP_FILE_WRITER_H__ -#define CLIENT_MINIDUMP_FILE_WRITER_H__ - -#include - -#include "google_breakpad/common/minidump_format.h" - -namespace google_breakpad { - -class UntypedMDRVA; -template class TypedMDRVA; - -// The user of this class can Open() a file and add minidump streams, data, and -// strings using the definitions in minidump_format.h. Since this class is -// expected to be used in a situation where the current process may be -// damaged, it will not allocate heap memory. -// Sample usage: -// MinidumpFileWriter writer; -// writer.Open("/tmp/minidump.dmp"); -// TypedMDRVA header(&writer_); -// header.Allocate(); -// header->get()->signature = MD_HEADER_SIGNATURE; -// : -// writer.Close(); -// -// An alternative is to use SetFile and provide a file descriptor: -// MinidumpFileWriter writer; -// writer.SetFile(minidump_fd); -// TypedMDRVA header(&writer_); -// header.Allocate(); -// header->get()->signature = MD_HEADER_SIGNATURE; -// : -// writer.Close(); - -class MinidumpFileWriter { -public: - // Invalid MDRVA (Minidump Relative Virtual Address) - // returned on failed allocation - static const MDRVA kInvalidMDRVA; - - MinidumpFileWriter(); - ~MinidumpFileWriter(); - - // Open |path| as the destination of the minidump data. Any existing file - // will be overwritten. - // Return true on success, or false on failure. - bool Open(const char *path); - - // Sets the file descriptor |file| as the destination of the minidump data. - // Can be used as an alternative to Open() when a file descriptor is - // available. - // Note that |fd| is not closed when the instance of MinidumpFileWriter is - // destroyed. - void SetFile(const int file); - - // Close the current file (that was either created when Open was called, or - // specified with SetFile). - // Return true on success, or false on failure. - bool Close(); - - // Copy the contents of |str| to a MDString and write it to the file. - // |str| is expected to be either UTF-16 or UTF-32 depending on the size - // of wchar_t. - // Maximum |length| of characters to copy from |str|, or specify 0 to use the - // entire NULL terminated string. Copying will stop at the first NULL. - // |location| the allocated location - // Return true on success, or false on failure - bool WriteString(const wchar_t *str, unsigned int length, - MDLocationDescriptor *location); - - // Same as above, except with |str| as a UTF-8 string - bool WriteString(const char *str, unsigned int length, - MDLocationDescriptor *location); - - // Write |size| bytes starting at |src| into the current position. - // Return true on success and set |output| to position, or false on failure - bool WriteMemory(const void *src, size_t size, MDMemoryDescriptor *output); - - // Copies |size| bytes from |src| to |position| - // Return true on success, or false on failure - bool Copy(MDRVA position, const void *src, ssize_t size); - - // Return the current position for writing to the minidump - inline MDRVA position() const { return position_; } - - private: - friend class UntypedMDRVA; - - // Allocates an area of |size| bytes. - // Returns the position of the allocation, or kInvalidMDRVA if it was - // unable to allocate the bytes. - MDRVA Allocate(size_t size); - - // The file descriptor for the output file. - int file_; - - // Whether |file_| should be closed when the instance is destroyed. - bool close_file_when_destroyed_; - - // Current position in buffer - MDRVA position_; - - // Current allocated size - size_t size_; - - // Copy |length| characters from |str| to |mdstring|. These are distinct - // because the underlying MDString is a UTF-16 based string. The wchar_t - // variant may need to create a MDString that has more characters than the - // source |str|, whereas the UTF-8 variant may coalesce characters to form - // a single UTF-16 character. - bool CopyStringToMDString(const wchar_t *str, unsigned int length, - TypedMDRVA *mdstring); - bool CopyStringToMDString(const char *str, unsigned int length, - TypedMDRVA *mdstring); - - // The common templated code for writing a string - template - bool WriteStringCore(const CharType *str, unsigned int length, - MDLocationDescriptor *location); -}; - -// Represents an untyped allocated chunk -class UntypedMDRVA { - public: - explicit UntypedMDRVA(MinidumpFileWriter *writer) - : writer_(writer), - position_(writer->position()), - size_(0) {} - - // Allocates |size| bytes. Must not call more than once. - // Return true on success, or false on failure - bool Allocate(size_t size); - - // Returns the current position or kInvalidMDRVA if allocation failed - inline MDRVA position() const { return position_; } - - // Number of bytes allocated - inline size_t size() const { return size_; } - - // Return size and position - inline MDLocationDescriptor location() const { - MDLocationDescriptor location = { static_cast(size_), - position_ }; - return location; - } - - // Copy |size| bytes starting at |src| into the minidump at |position| - // Return true on success, or false on failure - bool Copy(MDRVA position, const void *src, size_t size); - - // Copy |size| bytes from |src| to the current position - inline bool Copy(const void *src, size_t size) { - return Copy(position_, src, size); - } - - protected: - // Writer we associate with - MinidumpFileWriter *writer_; - - // Position of the start of the data - MDRVA position_; - - // Allocated size - size_t size_; -}; - -// Represents a Minidump object chunk. Additional memory can be allocated at -// the end of the object as a: -// - single allocation -// - Array of MDType objects -// - A MDType object followed by an array -template -class TypedMDRVA : public UntypedMDRVA { - public: - // Constructs an unallocated MDRVA - explicit TypedMDRVA(MinidumpFileWriter *writer) - : UntypedMDRVA(writer), - data_(), - allocation_state_(UNALLOCATED) {} - - inline ~TypedMDRVA() { - // Ensure that the data_ object is written out - if (allocation_state_ != ARRAY) - Flush(); - } - - // Address of object data_ of MDType. This is not declared const as the - // typical usage will be to access the underlying |data_| object as to - // alter its contents. - MDType *get() { return &data_; } - - // Allocates minidump_size::size() bytes. - // Must not call more than once. - // Return true on success, or false on failure - bool Allocate(); - - // Allocates minidump_size::size() + |additional| bytes. - // Must not call more than once. - // Return true on success, or false on failure - bool Allocate(size_t additional); - - // Allocate an array of |count| elements of MDType. - // Must not call more than once. - // Return true on success, or false on failure - bool AllocateArray(size_t count); - - // Allocate an array of |count| elements of |size| after object of MDType - // Must not call more than once. - // Return true on success, or false on failure - bool AllocateObjectAndArray(size_t count, size_t size); - - // Copy |item| to |index| - // Must have been allocated using AllocateArray(). - // Return true on success, or false on failure - bool CopyIndex(unsigned int index, MDType *item); - - // Copy |size| bytes starting at |str| to |index| - // Must have been allocated using AllocateObjectAndArray(). - // Return true on success, or false on failure - bool CopyIndexAfterObject(unsigned int index, const void *src, size_t size); - - // Write data_ - bool Flush(); - - private: - enum AllocationState { - UNALLOCATED = 0, - SINGLE_OBJECT, - ARRAY, - SINGLE_OBJECT_WITH_ARRAY - }; - - MDType data_; - AllocationState allocation_state_; -}; - -} // namespace google_breakpad - -#endif // CLIENT_MINIDUMP_FILE_WRITER_H__ diff --git a/breakpad/client/minidump_file_writer_unittest.cc b/breakpad/client/minidump_file_writer_unittest.cc deleted file mode 100644 index 60c364e68..000000000 --- a/breakpad/client/minidump_file_writer_unittest.cc +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: waylonis@google.com (Dan Waylonis) - -/* - g++ -I../ ../common/convert_UTF.c \ - ../common/string_conversion.cc \ - minidump_file_writer.cc \ - minidump_file_writer_unittest.cc \ - -o minidump_file_writer_unittest - */ - -#include -#include - -#include "minidump_file_writer-inl.h" - -using google_breakpad::MinidumpFileWriter; - -#define ASSERT_TRUE(cond) \ -if (!(cond)) { \ - fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \ - return false; \ -} - -#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2)) -#define ASSERT_NE(e1, e2) ASSERT_TRUE((e1) != (e2)) - -struct StringStructure { - unsigned long integer_value; - MDLocationDescriptor first_string; - MDLocationDescriptor second_string; -}; - -struct ArrayStructure { - unsigned char char_value; - unsigned short short_value; - unsigned long long_value; -}; - -typedef struct { - unsigned long count; - ArrayStructure array[0]; -} ObjectAndArrayStructure; - -static bool WriteFile(const char *path) { - MinidumpFileWriter writer; - if (writer.Open(path)) { - // Test a single structure - google_breakpad::TypedMDRVA strings(&writer); - ASSERT_TRUE(strings.Allocate()); - strings.get()->integer_value = 0xBEEF; - const char *first = "First String"; - ASSERT_TRUE(writer.WriteString(first, 0, &strings.get()->first_string)); - const wchar_t *second = L"Second String"; - ASSERT_TRUE(writer.WriteString(second, 0, &strings.get()->second_string)); - - // Test an array structure - google_breakpad::TypedMDRVA array(&writer); - unsigned int count = 10; - ASSERT_TRUE(array.AllocateArray(count)); - for (unsigned char i = 0; i < count; ++i) { - ArrayStructure local; - local.char_value = i; - local.short_value = i + 1; - local.long_value = i + 2; - ASSERT_TRUE(array.CopyIndex(i, &local)); - } - - // Test an object followed by an array - google_breakpad::TypedMDRVA obj_array(&writer); - ASSERT_TRUE(obj_array.AllocateObjectAndArray(count, - sizeof(ArrayStructure))); - obj_array.get()->count = count; - for (unsigned char i = 0; i < count; ++i) { - ArrayStructure local; - local.char_value = i; - local.short_value = i + 1; - local.long_value = i + 2; - ASSERT_TRUE(obj_array.CopyIndexAfterObject(i, &local, sizeof(local))); - } - } - - return writer.Close(); -} - -static bool CompareFile(const char *path) { - unsigned long expected[] = { -#if defined(__BIG_ENDIAN__) - 0x0000beef, 0x0000001e, 0x00000018, 0x00000020, 0x00000038, 0x00000000, - 0x00000018, 0x00460069, 0x00720073, 0x00740020, 0x00530074, 0x00720069, - 0x006e0067, 0x00000000, 0x0000001a, 0x00530065, 0x0063006f, 0x006e0064, - 0x00200053, 0x00740072, 0x0069006e, 0x00670000, 0x00000001, 0x00000002, - 0x01000002, 0x00000003, 0x02000003, 0x00000004, 0x03000004, 0x00000005, - 0x04000005, 0x00000006, 0x05000006, 0x00000007, 0x06000007, 0x00000008, - 0x07000008, 0x00000009, 0x08000009, 0x0000000a, 0x0900000a, 0x0000000b, - 0x0000000a, 0x00000001, 0x00000002, 0x01000002, 0x00000003, 0x02000003, - 0x00000004, 0x03000004, 0x00000005, 0x04000005, 0x00000006, 0x05000006, - 0x00000007, 0x06000007, 0x00000008, 0x07000008, 0x00000009, 0x08000009, - 0x0000000a, 0x0900000a, 0x0000000b, 0x00000000 -#else - 0x0000beef, 0x0000001e, 0x00000018, 0x00000020, - 0x00000038, 0x00000000, 0x00000018, 0x00690046, - 0x00730072, 0x00200074, 0x00740053, 0x00690072, - 0x0067006e, 0x00000000, 0x0000001a, 0x00650053, - 0x006f0063, 0x0064006e, 0x00530020, 0x00720074, - 0x006e0069, 0x00000067, 0x00011e00, 0x00000002, - 0x00021e01, 0x00000003, 0x00031e02, 0x00000004, - 0x00041e03, 0x00000005, 0x00051e04, 0x00000006, - 0x00061e05, 0x00000007, 0x00071e06, 0x00000008, - 0x00081e07, 0x00000009, 0x00091e08, 0x0000000a, - 0x000a1e09, 0x0000000b, 0x0000000a, 0x00011c00, - 0x00000002, 0x00021c01, 0x00000003, 0x00031c02, - 0x00000004, 0x00041c03, 0x00000005, 0x00051c04, - 0x00000006, 0x00061c05, 0x00000007, 0x00071c06, - 0x00000008, 0x00081c07, 0x00000009, 0x00091c08, - 0x0000000a, 0x000a1c09, 0x0000000b, 0x00000000, -#endif - }; - size_t expected_byte_count = sizeof(expected); - int fd = open(path, O_RDONLY, 0600); - void *buffer = malloc(expected_byte_count); - ASSERT_NE(fd, -1); - ASSERT_TRUE(buffer); - ASSERT_EQ(read(fd, buffer, expected_byte_count), - static_cast(expected_byte_count)); - - char *b1, *b2; - b1 = reinterpret_cast(buffer); - b2 = reinterpret_cast(expected); - while (*b1 == *b2) { - b1++; - b2++; - } - - printf("%p\n", reinterpret_cast(b1 - (char*)buffer)); - - ASSERT_EQ(memcmp(buffer, expected, expected_byte_count), 0); - return true; -} - -static bool RunTests() { - const char *path = "/tmp/minidump_file_writer_unittest.dmp"; - ASSERT_TRUE(WriteFile(path)); - ASSERT_TRUE(CompareFile(path)); - unlink(path); - return true; -} - -extern "C" int main(int argc, const char *argv[]) { - return RunTests() ? 0 : 1; -} diff --git a/breakpad/client/windows/common.vcxproj.filters b/breakpad/client/windows/common.vcxproj.filters deleted file mode 100644 index d6285c77a..000000000 --- a/breakpad/client/windows/common.vcxproj.filters +++ /dev/null @@ -1,39 +0,0 @@ - - - - - {739DB09A-CC57-A953-A6CF-F64FA08E4FA7} - - - {739DB09A-CC57-A953-A6CF-F64FA08E4FA7} - - - {2F5FD094-EF52-77F7-7AA8-4327A01BF747} - - - {C1450D01-C033-76F3-3763-6DE88AF48A77} - - - - - - - - ..\..\common\windows - - - ..\..\common\windows - - - ..\..\common\windows - - - - - ..\..\common\windows - - - ..\..\common\windows - - - \ No newline at end of file diff --git a/breakpad/common/basictypes.h b/breakpad/common/basictypes.h deleted file mode 100644 index 84668b79d..000000000 --- a/breakpad/common/basictypes.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2011 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef COMMON_BASICTYPES_H_ -#define COMMON_BASICTYPES_H_ - -// A macro to disallow the copy constructor and operator= functions -// This should be used in the private: declarations for a class -#ifndef DISALLOW_COPY_AND_ASSIGN -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) -#endif // DISALLOW_COPY_AND_ASSIGN - -#endif // COMMON_BASICTYPES_H_ diff --git a/breakpad/common/byte_cursor.h b/breakpad/common/byte_cursor.h deleted file mode 100644 index accd54e0a..000000000 --- a/breakpad/common/byte_cursor.h +++ /dev/null @@ -1,265 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// byte_cursor.h: Classes for parsing values from a buffer of bytes. -// The ByteCursor class provides a convenient interface for reading -// fixed-size integers of arbitrary endianness, being thorough about -// checking for buffer overruns. - -#ifndef COMMON_BYTE_CURSOR_H_ -#define COMMON_BYTE_CURSOR_H_ - -#include -#include -#include -#include -#include - -#include "common/using_std_string.h" - -namespace google_breakpad { - -// A buffer holding a series of bytes. -struct ByteBuffer { - ByteBuffer() : start(0), end(0) { } - ByteBuffer(const uint8_t *set_start, size_t set_size) - : start(set_start), end(set_start + set_size) { } - ~ByteBuffer() { }; - - // Equality operators. Useful in unit tests, and when we're using - // ByteBuffers to refer to regions of a larger buffer. - bool operator==(const ByteBuffer &that) const { - return start == that.start && end == that.end; - } - bool operator!=(const ByteBuffer &that) const { - return start != that.start || end != that.end; - } - - // Not C++ style guide compliant, but this definitely belongs here. - size_t Size() const { - assert(start <= end); - return end - start; - } - - const uint8_t *start, *end; -}; - -// A cursor pointing into a ByteBuffer that can parse numbers of various -// widths and representations, strings, and data blocks, advancing through -// the buffer as it goes. All ByteCursor operations check that accesses -// haven't gone beyond the end of the enclosing ByteBuffer. -class ByteCursor { - public: - // Create a cursor reading bytes from the start of BUFFER. By default, the - // cursor reads multi-byte values in little-endian form. - ByteCursor(const ByteBuffer *buffer, bool big_endian = false) - : buffer_(buffer), here_(buffer->start), - big_endian_(big_endian), complete_(true) { } - - // Accessor and setter for this cursor's endianness flag. - bool big_endian() const { return big_endian_; } - void set_big_endian(bool big_endian) { big_endian_ = big_endian; } - - // Accessor and setter for this cursor's current position. The setter - // returns a reference to this cursor. - const uint8_t *here() const { return here_; } - ByteCursor &set_here(const uint8_t *here) { - assert(buffer_->start <= here && here <= buffer_->end); - here_ = here; - return *this; - } - - // Return the number of bytes available to read at the cursor. - size_t Available() const { return size_t(buffer_->end - here_); } - - // Return true if this cursor is at the end of its buffer. - bool AtEnd() const { return Available() == 0; } - - // When used as a boolean value this cursor converts to true if all - // prior reads have been completed, or false if we ran off the end - // of the buffer. - operator bool() const { return complete_; } - - // Read a SIZE-byte integer at this cursor, signed if IS_SIGNED is true, - // unsigned otherwise, using the cursor's established endianness, and set - // *RESULT to the number. If we read off the end of our buffer, clear - // this cursor's complete_ flag, and store a dummy value in *RESULT. - // Return a reference to this cursor. - template - ByteCursor &Read(size_t size, bool is_signed, T *result) { - if (CheckAvailable(size)) { - T v = 0; - if (big_endian_) { - for (size_t i = 0; i < size; i++) - v = (v << 8) + here_[i]; - } else { - // This loop condition looks weird, but size_t is unsigned, so - // decrementing i after it is zero yields the largest size_t value. - for (size_t i = size - 1; i < size; i--) - v = (v << 8) + here_[i]; - } - if (is_signed && size < sizeof(T)) { - size_t sign_bit = (T)1 << (size * 8 - 1); - v = (v ^ sign_bit) - sign_bit; - } - here_ += size; - *result = v; - } else { - *result = (T) 0xdeadbeef; - } - return *this; - } - - // Read an integer, using the cursor's established endianness and - // *RESULT's size and signedness, and set *RESULT to the number. If we - // read off the end of our buffer, clear this cursor's complete_ flag. - // Return a reference to this cursor. - template - ByteCursor &operator>>(T &result) { - bool T_is_signed = (T)-1 < 0; - return Read(sizeof(T), T_is_signed, &result); - } - - // Copy the SIZE bytes at the cursor to BUFFER, and advance this - // cursor to the end of them. If we read off the end of our buffer, - // clear this cursor's complete_ flag, and set *POINTER to NULL. - // Return a reference to this cursor. - ByteCursor &Read(uint8_t *buffer, size_t size) { - if (CheckAvailable(size)) { - memcpy(buffer, here_, size); - here_ += size; - } - return *this; - } - - // Set STR to a copy of the '\0'-terminated string at the cursor. If the - // byte buffer does not contain a terminating zero, clear this cursor's - // complete_ flag, and set STR to the empty string. Return a reference to - // this cursor. - ByteCursor &CString(string *str) { - const uint8_t *end - = static_cast(memchr(here_, '\0', Available())); - if (end) { - str->assign(reinterpret_cast(here_), end - here_); - here_ = end + 1; - } else { - str->clear(); - here_ = buffer_->end; - complete_ = false; - } - return *this; - } - - // Like CString(STR), but extract the string from a fixed-width buffer - // LIMIT bytes long, which may or may not contain a terminating '\0' - // byte. Specifically: - // - // - If there are not LIMIT bytes available at the cursor, clear the - // cursor's complete_ flag and set STR to the empty string. - // - // - Otherwise, if the LIMIT bytes at the cursor contain any '\0' - // characters, set *STR to a copy of the bytes before the first '\0', - // and advance the cursor by LIMIT bytes. - // - // - Otherwise, set *STR to a copy of those LIMIT bytes, and advance the - // cursor by LIMIT bytes. - ByteCursor &CString(string *str, size_t limit) { - if (CheckAvailable(limit)) { - const uint8_t *end - = static_cast(memchr(here_, '\0', limit)); - if (end) - str->assign(reinterpret_cast(here_), end - here_); - else - str->assign(reinterpret_cast(here_), limit); - here_ += limit; - } else { - str->clear(); - } - return *this; - } - - // Set *POINTER to point to the SIZE bytes at the cursor, and advance - // this cursor to the end of them. If SIZE is omitted, don't move the - // cursor. If we read off the end of our buffer, clear this cursor's - // complete_ flag, and set *POINTER to NULL. Return a reference to this - // cursor. - ByteCursor &PointTo(const uint8_t **pointer, size_t size = 0) { - if (CheckAvailable(size)) { - *pointer = here_; - here_ += size; - } else { - *pointer = NULL; - } - return *this; - } - - // Skip SIZE bytes at the cursor. If doing so would advance us off - // the end of our buffer, clear this cursor's complete_ flag, and - // set *POINTER to NULL. Return a reference to this cursor. - ByteCursor &Skip(size_t size) { - if (CheckAvailable(size)) - here_ += size; - return *this; - } - - private: - // If there are at least SIZE bytes available to read from the buffer, - // return true. Otherwise, set here_ to the end of the buffer, set - // complete_ to false, and return false. - bool CheckAvailable(size_t size) { - if (Available() >= size) { - return true; - } else { - here_ = buffer_->end; - complete_ = false; - return false; - } - } - - // The buffer we're reading bytes from. - const ByteBuffer *buffer_; - - // The next byte within buffer_ that we'll read. - const uint8_t *here_; - - // True if we should read numbers in big-endian form; false if we - // should read in little-endian form. - bool big_endian_; - - // True if we've been able to read all we've been asked to. - bool complete_; -}; - -} // namespace google_breakpad - -#endif // COMMON_BYTE_CURSOR_H_ diff --git a/breakpad/common/byte_cursor_unittest.cc b/breakpad/common/byte_cursor_unittest.cc deleted file mode 100644 index 06bfd89d7..000000000 --- a/breakpad/common/byte_cursor_unittest.cc +++ /dev/null @@ -1,776 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// byte_cursor_unittest.cc: Unit tests for google_breakpad::ByteBuffer -// and google_breakpad::ByteCursor. - -#include - -#include - -#include "breakpad_googletest_includes.h" -#include "common/byte_cursor.h" -#include "common/using_std_string.h" - -using google_breakpad::ByteBuffer; -using google_breakpad::ByteCursor; - -TEST(Buffer, SizeOfNothing) { - uint8_t data[1]; - ByteBuffer buffer(data, 0); - EXPECT_EQ(0U, buffer.Size()); -} - -TEST(Buffer, SizeOfSomething) { - uint8_t data[10]; - ByteBuffer buffer(data, sizeof(data)); - EXPECT_EQ(10U, buffer.Size()); -} - -TEST(Extent, AvailableEmpty) { - uint8_t data[1]; - ByteBuffer buffer(data, 0); - ByteCursor cursor(&buffer); - EXPECT_EQ(0U, cursor.Available()); -} - -TEST(Extent, AtEndEmpty) { - uint8_t data[1]; - ByteBuffer buffer(data, 0); - ByteCursor cursor(&buffer); - EXPECT_TRUE(cursor.AtEnd()); -} - -TEST(Extent, AsBoolEmpty) { - uint8_t data[1]; - ByteBuffer buffer(data, 0); - ByteCursor cursor(&buffer); - EXPECT_TRUE(cursor); -} - -TEST(Extent, AvailableSome) { - uint8_t data[10]; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - EXPECT_EQ(10U, cursor.Available()); -} - -TEST(Extent, AtEndSome) { - uint8_t data[10]; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - EXPECT_FALSE(cursor.AtEnd()); - EXPECT_TRUE(cursor.Skip(sizeof(data)).AtEnd()); -} - -TEST(Extent, AsBoolSome) { - uint8_t data[10]; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - EXPECT_TRUE(cursor); - EXPECT_TRUE(cursor.Skip(sizeof(data))); - EXPECT_FALSE(cursor.Skip(1)); -} - -TEST(Extent, Cursor) { - uint8_t data[] = { 0xf7, - 0x9f, 0xbe, - 0x67, 0xfb, 0xd3, 0x58, - 0x6f, 0x36, 0xde, 0xd1, - 0x2a, 0x2a, 0x2a }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - - uint8_t a; - uint16_t b; - uint32_t c; - uint32_t d; - uint8_t stars[3]; - - EXPECT_EQ(data + 0U, cursor.here()); - - EXPECT_TRUE(cursor >> a); - EXPECT_EQ(data + 1U, cursor.here()); - - EXPECT_TRUE(cursor >> b); - EXPECT_EQ(data + 3U, cursor.here()); - - EXPECT_TRUE(cursor >> c); - EXPECT_EQ(data + 7U, cursor.here()); - - EXPECT_TRUE(cursor.Skip(4)); - EXPECT_EQ(data + 11U, cursor.here()); - - EXPECT_TRUE(cursor.Read(stars, 3)); - EXPECT_EQ(data + 14U, cursor.here()); - - EXPECT_FALSE(cursor >> d); - EXPECT_EQ(data + 14U, cursor.here()); -} - -TEST(Extent, SetOffset) { - uint8_t data[] = { 0x5c, 0x79, 0x8c, 0xd5 }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - - uint8_t a, b, c, d, e; - EXPECT_TRUE(cursor >> a); - EXPECT_EQ(0x5cU, a); - EXPECT_EQ(data + 1U, cursor.here()); - EXPECT_TRUE(((cursor >> b).set_here(data + 3) >> c).set_here(data + 1) - >> d >> e); - EXPECT_EQ(0x79U, b); - EXPECT_EQ(0xd5U, c); - EXPECT_EQ(0x79U, d); - EXPECT_EQ(0x8cU, e); - EXPECT_EQ(data + 3U, cursor.here()); -} - -TEST(BigEndian, Signed1) { - uint8_t data[] = { 0x00, 0x7f, 0x80, 0xff }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - cursor.set_big_endian(true); - int a, b, c, d, e; - ASSERT_TRUE(cursor - .Read(1, true, &a) - .Read(1, true, &b) - .Read(1, true, &c) - .Read(1, true, &d)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x7f, b); - EXPECT_EQ(-0x80, c); - EXPECT_EQ(-1, d); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(1, true, &e)); -} - -TEST(BigEndian, Signed2) { - uint8_t data[] = { 0x00, 0x00, 0x00, 0x80, 0x7f, 0xff, - 0x80, 0x00, 0x80, 0x80, 0xff, 0xff, - 0x39, 0xf1, 0x8a, 0xbc, 0x5a, 0xec }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer, true); - int a, b, c, d, e, f, g, h, i, j; - ASSERT_TRUE(cursor - .Read(2, true, &a) - .Read(2, true, &b) - .Read(2, true, &c) - .Read(2, true, &d) - .Read(2, true, &e) - .Read(2, true, &f) - .Read(2, true, &g) - .Read(2, true, &h) - .Read(2, true, &i)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x80, b); - EXPECT_EQ(0x7fff, c); - EXPECT_EQ(-0x8000, d); - EXPECT_EQ(-0x7f80, e); - EXPECT_EQ(-1, f); - EXPECT_EQ(0x39f1, g); - EXPECT_EQ(-0x7544, h); - EXPECT_EQ(0x5aec, i); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(2, true, &j)); -} - -TEST(BigEndian, Signed4) { - uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, - 0x7f, 0xff, 0xff, 0xff, - 0x80, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, - 0xb6, 0xb1, 0xff, 0xef, - 0x19, 0x6a, 0xca, 0x46 }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - cursor.set_big_endian(true); - int64_t a, b, c, d, e, f, g; - ASSERT_TRUE(cursor - .Read(4, true, &a) - .Read(4, true, &b) - .Read(4, true, &c) - .Read(4, true, &d) - .Read(4, true, &e) - .Read(4, true, &f)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x7fffffff, b); - EXPECT_EQ(-0x80000000LL, c); - EXPECT_EQ(-1, d); - EXPECT_EQ((int32_t) 0xb6b1ffef, e); - EXPECT_EQ(0x196aca46, f); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(4, true, &g)); -} - -TEST(BigEndian, Signed8) { - uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x93, 0x20, 0xd5, 0xe9, 0xd2, 0xd5, 0x87, 0x9c, - 0x4e, 0x42, 0x49, 0xd2, 0x7f, 0x84, 0x14, 0xa4 }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer, true); - int64_t a, b, c, d, e, f, g; - ASSERT_TRUE(cursor - .Read(8, true, &a) - .Read(8, true, &b) - .Read(8, true, &c) - .Read(8, true, &d) - .Read(8, true, &e) - .Read(8, true, &f)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x7fffffffffffffffLL, b); - EXPECT_EQ(-0x7fffffffffffffffLL - 1, c); - EXPECT_EQ(-1, d); - EXPECT_EQ((int64_t) 0x9320d5e9d2d5879cULL, e); - EXPECT_EQ(0x4e4249d27f8414a4LL, f); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(8, true, &g)); -} - -TEST(BigEndian, Unsigned1) { - uint8_t data[] = { 0x00, 0x7f, 0x80, 0xff }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - cursor.set_big_endian(true); - int32_t a, b, c, d, e; - ASSERT_TRUE(cursor - .Read(1, false, &a) - .Read(1, false, &b) - .Read(1, false, &c) - .Read(1, false, &d)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x7f, b); - EXPECT_EQ(0x80, c); - EXPECT_EQ(0xff, d); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(1, false, &e)); -} - -TEST(BigEndian, Unsigned2) { - uint8_t data[] = { 0x00, 0x00, 0x00, 0x80, 0x7f, 0xff, - 0x80, 0x00, 0x80, 0x80, 0xff, 0xff, - 0x39, 0xf1, 0x8a, 0xbc, 0x5a, 0xec }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer, true); - int64_t a, b, c, d, e, f, g, h, i, j; - ASSERT_TRUE(cursor - .Read(2, false, &a) - .Read(2, false, &b) - .Read(2, false, &c) - .Read(2, false, &d) - .Read(2, false, &e) - .Read(2, false, &f) - .Read(2, false, &g) - .Read(2, false, &h) - .Read(2, false, &i)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x80, b); - EXPECT_EQ(0x7fff, c); - EXPECT_EQ(0x8000, d); - EXPECT_EQ(0x8080, e); - EXPECT_EQ(0xffff, f); - EXPECT_EQ(0x39f1, g); - EXPECT_EQ(0x8abc, h); - EXPECT_EQ(0x5aec, i); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(2, false, &j)); -} - -TEST(BigEndian, Unsigned4) { - uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, - 0x7f, 0xff, 0xff, 0xff, - 0x80, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, - 0xb6, 0xb1, 0xff, 0xef, - 0x19, 0x6a, 0xca, 0x46 }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - cursor.set_big_endian(true); - int64_t a, b, c, d, e, f, g; - ASSERT_TRUE(cursor - .Read(4, false, &a) - .Read(4, false, &b) - .Read(4, false, &c) - .Read(4, false, &d) - .Read(4, false, &e) - .Read(4, false, &f)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x7fffffff, b); - EXPECT_EQ(0x80000000, c); - EXPECT_EQ(0xffffffff, d); - EXPECT_EQ(0xb6b1ffef, e); - EXPECT_EQ(0x196aca46, f); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(4, false, &g)); -} - -TEST(BigEndian, Unsigned8) { - uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x93, 0x20, 0xd5, 0xe9, 0xd2, 0xd5, 0x87, 0x9c, - 0x4e, 0x42, 0x49, 0xd2, 0x7f, 0x84, 0x14, 0xa4 }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer, true); - uint64_t a, b, c, d, e, f, g; - ASSERT_TRUE(cursor - .Read(8, false, &a) - .Read(8, false, &b) - .Read(8, false, &c) - .Read(8, false, &d) - .Read(8, false, &e) - .Read(8, false, &f)); - EXPECT_EQ(0U, a); - EXPECT_EQ(0x7fffffffffffffffULL, b); - EXPECT_EQ(0x8000000000000000ULL, c); - EXPECT_EQ(0xffffffffffffffffULL, d); - EXPECT_EQ(0x9320d5e9d2d5879cULL, e); - EXPECT_EQ(0x4e4249d27f8414a4ULL, f); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(8, false, &g)); -} - -TEST(LittleEndian, Signed1) { - uint8_t data[] = { 0x00, 0x7f, 0x80, 0xff }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - int32_t a, b, c, d, e; - ASSERT_TRUE(cursor - .Read(1, true, &a) - .Read(1, true, &b) - .Read(1, true, &c) - .Read(1, true, &d)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x7f, b); - EXPECT_EQ(-0x80, c); - EXPECT_EQ(-1, d); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(1, true, &e)); -} - -TEST(LittleEndian, Signed2) { - uint8_t data[] = { 0x00, 0x00, 0x80, 0x00, 0xff, 0x7f, - 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, - 0xf1, 0x39, 0xbc, 0x8a, 0xec, 0x5a }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer, false); - int32_t a, b, c, d, e, f, g, h, i, j; - ASSERT_TRUE(cursor - .Read(2, true, &a) - .Read(2, true, &b) - .Read(2, true, &c) - .Read(2, true, &d) - .Read(2, true, &e) - .Read(2, true, &f) - .Read(2, true, &g) - .Read(2, true, &h) - .Read(2, true, &i)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x80, b); - EXPECT_EQ(0x7fff, c); - EXPECT_EQ(-0x8000, d); - EXPECT_EQ(-0x7f80, e); - EXPECT_EQ(-1, f); - EXPECT_EQ(0x39f1, g); - EXPECT_EQ(-0x7544, h); - EXPECT_EQ(0x5aec, i); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(2, true, &j)); -} - -TEST(LittleEndian, Signed4) { - uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0x7f, - 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xb1, 0xb6, - 0x46, 0xca, 0x6a, 0x19 }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - int64_t a, b, c, d, e, f, g; - ASSERT_TRUE(cursor - .Read(4, true, &a) - .Read(4, true, &b) - .Read(4, true, &c) - .Read(4, true, &d) - .Read(4, true, &e) - .Read(4, true, &f)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x7fffffff, b); - EXPECT_EQ(-0x80000000LL, c); - EXPECT_EQ(-1, d); - EXPECT_EQ((int32_t) 0xb6b1ffef, e); - EXPECT_EQ(0x196aca46, f); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(4, true, &g)); -} - -TEST(LittleEndian, Signed8) { - uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x9c, 0x87, 0xd5, 0xd2, 0xe9, 0xd5, 0x20, 0x93, - 0xa4, 0x14, 0x84, 0x7f, 0xd2, 0x49, 0x42, 0x4e }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer, false); - int64_t a, b, c, d, e, f, g; - ASSERT_TRUE(cursor - .Read(8, true, &a) - .Read(8, true, &b) - .Read(8, true, &c) - .Read(8, true, &d) - .Read(8, true, &e) - .Read(8, true, &f)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x7fffffffffffffffLL, b); - EXPECT_EQ(-0x7fffffffffffffffLL - 1, c); - EXPECT_EQ(-1, d); - EXPECT_EQ((int64_t) 0x9320d5e9d2d5879cULL, e); - EXPECT_EQ(0x4e4249d27f8414a4LL, f); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(8, true, &g)); -} - -TEST(LittleEndian, Unsigned1) { - uint8_t data[] = { 0x00, 0x7f, 0x80, 0xff }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - int32_t a, b, c, d, e; - ASSERT_TRUE(cursor - .Read(1, false, &a) - .Read(1, false, &b) - .Read(1, false, &c) - .Read(1, false, &d)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x7f, b); - EXPECT_EQ(0x80, c); - EXPECT_EQ(0xff, d); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(1, false, &e)); -} - -TEST(LittleEndian, Unsigned2) { - uint8_t data[] = { 0x00, 0x00, 0x80, 0x00, 0xff, 0x7f, - 0x00, 0x80, 0x80, 0x80, 0xff, 0xff, - 0xf1, 0x39, 0xbc, 0x8a, 0xec, 0x5a }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - int32_t a, b, c, d, e, f, g, h, i, j; - ASSERT_TRUE(cursor - .Read(2, false, &a) - .Read(2, false, &b) - .Read(2, false, &c) - .Read(2, false, &d) - .Read(2, false, &e) - .Read(2, false, &f) - .Read(2, false, &g) - .Read(2, false, &h) - .Read(2, false, &i)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x80, b); - EXPECT_EQ(0x7fff, c); - EXPECT_EQ(0x8000, d); - EXPECT_EQ(0x8080, e); - EXPECT_EQ(0xffff, f); - EXPECT_EQ(0x39f1, g); - EXPECT_EQ(0x8abc, h); - EXPECT_EQ(0x5aec, i); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(2, false, &j)); -} - -TEST(LittleEndian, Unsigned4) { - uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0x7f, - 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xb1, 0xb6, - 0x46, 0xca, 0x6a, 0x19 }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - int64_t a, b, c, d, e, f, g; - ASSERT_TRUE(cursor - .Read(4, false, &a) - .Read(4, false, &b) - .Read(4, false, &c) - .Read(4, false, &d) - .Read(4, false, &e) - .Read(4, false, &f)); - EXPECT_EQ(0, a); - EXPECT_EQ(0x7fffffff, b); - EXPECT_EQ(0x80000000, c); - EXPECT_EQ(0xffffffff, d); - EXPECT_EQ(0xb6b1ffef, e); - EXPECT_EQ(0x196aca46, f); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(4, false, &g)); -} - -TEST(LittleEndian, Unsigned8) { - uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x9c, 0x87, 0xd5, 0xd2, 0xe9, 0xd5, 0x20, 0x93, - 0xa4, 0x14, 0x84, 0x7f, 0xd2, 0x49, 0x42, 0x4e }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - uint64_t a, b, c, d, e, f, g; - ASSERT_TRUE(cursor - .Read(8, false, &a) - .Read(8, false, &b) - .Read(8, false, &c) - .Read(8, false, &d) - .Read(8, false, &e) - .Read(8, false, &f)); - EXPECT_EQ(0U, a); - EXPECT_EQ(0x7fffffffffffffffULL, b); - EXPECT_EQ(0x8000000000000000ULL, c); - EXPECT_EQ(0xffffffffffffffffULL, d); - EXPECT_EQ(0x9320d5e9d2d5879cULL, e); - EXPECT_EQ(0x4e4249d27f8414a4ULL, f); - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor.Read(8, false, &g)); -} - -TEST(Extractor, Signed1) { - uint8_t data[] = { 0xfd }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - int8_t a; - EXPECT_TRUE(cursor >> a); - EXPECT_EQ(-3, a); - EXPECT_FALSE(cursor >> a); -} - -TEST(Extractor, Signed2) { - uint8_t data[] = { 0x13, 0xcd }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - int16_t a; - EXPECT_TRUE(cursor >> a); - EXPECT_EQ(-13037, a); - EXPECT_FALSE(cursor >> a); -} - -TEST(Extractor, Signed4) { - uint8_t data[] = { 0xd2, 0xe4, 0x53, 0xe9 }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - int32_t a; - // For some reason, G++ 4.4.1 complains: - // warning: array subscript is above array bounds - // in ByteCursor::Read(size_t, bool, T *) as it inlines this call, but - // I'm not able to see how such a reference would occur. - EXPECT_TRUE(cursor >> a); - EXPECT_EQ(-380377902, a); - EXPECT_FALSE(cursor >> a); -} - -TEST(Extractor, Unsigned1) { - uint8_t data[] = { 0xfd }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - uint8_t a; - EXPECT_TRUE(cursor >> a); - EXPECT_EQ(0xfd, a); - EXPECT_FALSE(cursor >> a); -} - -TEST(Extractor, Unsigned2) { - uint8_t data[] = { 0x13, 0xcd }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - uint16_t a; - EXPECT_TRUE(cursor >> a); - EXPECT_EQ(0xcd13, a); - EXPECT_FALSE(cursor >> a); -} - -TEST(Extractor, Unsigned4) { - uint8_t data[] = { 0xd2, 0xe4, 0x53, 0xe9 }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - uint32_t a; - // For some reason, G++ 4.4.1 complains: - // warning: array subscript is above array bounds - // in ByteCursor::Read(size_t, bool, T *) as it inlines this call, but - // I'm not able to see how such a reference would occur. - EXPECT_TRUE(cursor >> a); - EXPECT_EQ(0xe953e4d2, a); - EXPECT_FALSE(cursor >> a); - EXPECT_FALSE(cursor >> a); -} - -TEST(Extractor, Mixed) { - uint8_t data[] = { 0x42, - 0x25, 0x0b, - 0x3d, 0x25, 0xed, 0x2a, - 0xec, 0x16, 0x9e, 0x14, 0x61, 0x5b, 0x2c, 0xcf, - 0xd8, - 0x22, 0xa5, - 0x3a, 0x02, 0x6a, 0xd7, - 0x93, 0x2a, 0x2d, 0x8d, 0xb4, 0x95, 0xe0, 0xc6 }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - cursor.set_big_endian(true); - - uint8_t a; - uint16_t b; - uint32_t c; - uint64_t d; - int8_t e; - int16_t f; - int32_t g; - int64_t h; - int z; - EXPECT_FALSE(cursor.AtEnd()); - EXPECT_TRUE(cursor >> a >> b >> c >> d >> e >> f >> g >> h); - EXPECT_EQ(0x42U, a); - EXPECT_EQ(0x250bU, b); - EXPECT_EQ(0x3d25ed2aU, c); - EXPECT_EQ(0xec169e14615b2ccfULL, d); - EXPECT_EQ(-40, e); - EXPECT_EQ(0x22a5, f); - EXPECT_EQ(0x3a026ad7, g); - EXPECT_EQ(-7842405714468937530LL, h); - - EXPECT_TRUE(cursor.AtEnd()); - EXPECT_FALSE(cursor >> z); -} - -TEST(Strings, Zero) { - uint8_t data[] = { 0xa6 }; - ByteBuffer buffer(data, 0); - ByteCursor cursor(&buffer); - - uint8_t received[1]; - received[0] = 0xc2; - EXPECT_TRUE(cursor.Read(received, 0)); - EXPECT_EQ(0xc2U, received[0]); -} - -TEST(Strings, Some) { - uint8_t data[] = { 0x5d, 0x31, 0x09, 0xa6, 0x2e, 0x2c, 0x83, 0xbb }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - - uint8_t received[7] = { 0xa7, 0xf7, 0x43, 0x0c, 0x27, 0xea, 0xed }; - EXPECT_TRUE(cursor.Skip(2).Read(received, 5)); - uint8_t expected[7] = { 0x09, 0xa6, 0x2e, 0x2c, 0x83, 0xea, 0xed }; - EXPECT_TRUE(memcmp(received, expected, 7) == 0); -} - -TEST(Strings, TooMuch) { - uint8_t data[] = { 0x5d, 0x31, 0x09, 0xa6, 0x2e, 0x2c, 0x83, 0xbb }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - - uint8_t received1[3]; - uint8_t received2[3]; - uint8_t received3[3]; - EXPECT_FALSE(cursor - .Read(received1, 3) - .Read(received2, 3) - .Read(received3, 3)); - uint8_t expected1[3] = { 0x5d, 0x31, 0x09 }; - uint8_t expected2[3] = { 0xa6, 0x2e, 0x2c }; - - EXPECT_TRUE(memcmp(received1, expected1, 3) == 0); - EXPECT_TRUE(memcmp(received2, expected2, 3) == 0); -} - -TEST(Strings, PointTo) { - uint8_t data[] = { 0x83, 0x80, 0xb4, 0x38, 0x00, 0x2c, 0x0a, 0x27 }; - ByteBuffer buffer(data, sizeof(data)); - ByteCursor cursor(&buffer); - - const uint8_t *received1; - const uint8_t *received2; - const uint8_t *received3; - const uint8_t *received4; - EXPECT_FALSE(cursor - .PointTo(&received1, 3) - .PointTo(&received2, 3) - .PointTo(&received3) - .PointTo(&received4, 3)); - EXPECT_EQ(data + 0, received1); - EXPECT_EQ(data + 3, received2); - EXPECT_EQ(data + 6, received3); - EXPECT_EQ(NULL, received4); -} - -TEST(Strings, CString) { - uint8_t data[] = "abc\0\0foo"; - ByteBuffer buffer(data, sizeof(data) - 1); // don't include terminating '\0' - ByteCursor cursor(&buffer); - - string a, b, c; - EXPECT_TRUE(cursor.CString(&a).CString(&b)); - EXPECT_EQ("abc", a); - EXPECT_EQ("", b); - EXPECT_FALSE(cursor.CString(&c)); - EXPECT_EQ("", c); - EXPECT_TRUE(cursor.AtEnd()); -} - -TEST(Strings, CStringLimit) { - uint8_t data[] = "abcdef\0\0foobar"; - ByteBuffer buffer(data, sizeof(data) - 1); // don't include terminating '\0' - ByteCursor cursor(&buffer); - - string a, b, c, d, e; - - EXPECT_TRUE(cursor.CString(&a, 3)); - EXPECT_EQ("abc", a); - - EXPECT_TRUE(cursor.CString(&b, 0)); - EXPECT_EQ("", b); - - EXPECT_TRUE(cursor.CString(&c, 6)); - EXPECT_EQ("def", c); - - EXPECT_TRUE(cursor.CString(&d, 4)); - EXPECT_EQ("ooba", d); - - EXPECT_FALSE(cursor.CString(&e, 4)); - EXPECT_EQ("", e); - - EXPECT_TRUE(cursor.AtEnd()); -} - -// uint8_t data[] = { 0xa6, 0x54, 0xdf, 0x67, 0x51, 0x43, 0xac, 0xf1 }; -// ByteBuffer buffer(data, sizeof(data)); diff --git a/breakpad/common/convert_UTF.c b/breakpad/common/convert_UTF.c deleted file mode 100644 index 80178d35e..000000000 --- a/breakpad/common/convert_UTF.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright 2001-2004 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - -/* --------------------------------------------------------------------- - -Conversions between UTF32, UTF-16, and UTF-8. Source code file. -Author: Mark E. Davis, 1994. -Rev History: Rick McGowan, fixes & updates May 2001. -Sept 2001: fixed const & error conditions per -mods suggested by S. Parent & A. Lillich. -June 2002: Tim Dodd added detection and handling of incomplete -source sequences, enhanced error detection, added casts -to eliminate compiler warnings. -July 2003: slight mods to back out aggressive FFFE detection. -Jan 2004: updated switches in from-UTF8 conversions. -Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. - -See the header file "ConvertUTF.h" for complete documentation. - ------------------------------------------------------------------------- */ - - -#include "convert_UTF.h" -#ifdef CVTUTF_DEBUG -#include -#endif - -static const int halfShift = 10; /* used for shifting by 10 bits */ - -static const UTF32 halfBase = 0x0010000UL; -static const UTF32 halfMask = 0x3FFUL; - -#define UNI_SUR_HIGH_START (UTF32)0xD800 -#define UNI_SUR_HIGH_END (UTF32)0xDBFF -#define UNI_SUR_LOW_START (UTF32)0xDC00 -#define UNI_SUR_LOW_END (UTF32)0xDFFF -#define false 0 -#define true 1 - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF32toUTF16 (const UTF32** sourceStart, const UTF32* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF32* source = *sourceStart; - UTF16* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - if (target >= targetEnd) { - result = targetExhausted; break; - } - ch = *source++; - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_LEGAL_UTF32) { - if (flags == strictConversion) { - result = sourceIllegal; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - --source; /* Back up source pointer! */ - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } -*sourceStart = source; -*targetStart = target; -return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF16toUTF32 (const UTF16** sourceStart, const UTF16* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF16* source = *sourceStart; - UTF32* target = *targetStart; - UTF32 ch, ch2; - while (source < sourceEnd) { - const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - if (target >= targetEnd) { - source = oldSource; /* Back up source pointer! */ - result = targetExhausted; break; - } - *target++ = ch; - } - *sourceStart = source; - *targetStart = target; -#ifdef CVTUTF_DEBUG - if (result == sourceIllegal) { - fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); - fflush(stderr); - } -#endif - return result; -} - -/* --------------------------------------------------------------------- */ - -/* - * Index into the table below with the first byte of a UTF-8 sequence to - * get the number of trailing bytes that are supposed to follow it. - * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is - * left as-is for anyone who may want to do such conversion, which was - * allowed in earlier algorithms. - */ -static const char trailingBytesForUTF8[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 -}; - -/* - * Magic values subtracted from a buffer value during UTF8 conversion. - * This table contains as many values as there might be trailing bytes - * in a UTF-8 sequence. - */ -static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, - 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; - -/* - * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed - * into the first byte, depending on how many bytes follow. There are - * as many entries in this table as there are UTF-8 sequence types. - * (I.e., one byte sequence, two byte... etc.). Remember that sequencs - * for *legal* UTF-8 will be 4 or fewer bytes total. - */ -static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - -/* --------------------------------------------------------------------- */ - -/* The interface converts a whole buffer to avoid function-call overhead. -* Constants have been gathered. Loops & conditionals have been removed as -* much as possible for efficiency, in favor of drop-through switches. -* (See "Note A" at the bottom of the file for equivalent code.) -* If your compiler supports it, the "isLegalUTF8" call can be turned -* into an inline function. -*/ - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF16toUTF8 (const UTF16** sourceStart, const UTF16* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF16* source = *sourceStart; - UTF8* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - UTF32 ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* Figure out how many bytes the result will require */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; - } else { bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - } - - target += bytesToWrite; - if (target > targetEnd) { - source = oldSource; /* Back up source pointer! */ - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } -*sourceStart = source; -*targetStart = target; -return result; -} - -/* --------------------------------------------------------------------- */ - -/* - * Utility routine to tell whether a sequence of bytes is legal UTF-8. - * This must be called with the length pre-determined by the first byte. - * If not calling this from ConvertUTF8to*, then the length can be set by: - * length = trailingBytesForUTF8[*source]+1; - * and the sequence is illegal right away if there aren't that many bytes - * available. - * If presented with a length > 4, this returns false. The Unicode - * definition of UTF-8 goes up to 4-byte sequences. - */ - -static Boolean isLegalUTF8(const UTF8 *source, int length) { - UTF8 a; - const UTF8 *srcptr = source+length; - switch (length) { - default: return false; - /* Everything else falls through when "true"... */ - case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 2: if ((a = (*--srcptr)) > 0xBF) return false; - - switch (*source) { - /* no fall-through in this inner switch */ - case 0xE0: if (a < 0xA0) return false; break; - case 0xED: if (a > 0x9F) return false; break; - case 0xF0: if (a < 0x90) return false; break; - case 0xF4: if (a > 0x8F) return false; break; - default: if (a < 0x80) return false; - } - - case 1: if (*source >= 0x80 && *source < 0xC2) return false; - } - if (*source > 0xF4) return false; - return true; -} - -/* --------------------------------------------------------------------- */ - -/* - * Exported function to return whether a UTF-8 sequence is legal or not. - * This is not used here; it's just exported. - */ -Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { - int length = trailingBytesForUTF8[*source]+1; - if (source+length > sourceEnd) { - return false; - } - return isLegalUTF8(source, length); -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF8toUTF16 (const UTF8** sourceStart, const UTF8* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF8* source = *sourceStart; - UTF16* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up source pointer! */ - result = targetExhausted; break; - } - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead+1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_UTF16) { - if (flags == strictConversion) { - result = sourceIllegal; - source -= (extraBytesToRead+1); /* return to the start */ - break; /* Bail out; shouldn't continue */ - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up source pointer! */ - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } -*sourceStart = source; -*targetStart = target; -return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF32toUTF8 (const UTF32** sourceStart, const UTF32* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF32* source = *sourceStart; - UTF8* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - ch = *source++; - if (flags == strictConversion ) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* - * Figure out how many bytes the result will require. Turn any - * illegally large UTF32 things (> Plane 17) into replacement chars. - */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; - } else { bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - result = sourceIllegal; - } - - target += bytesToWrite; - if (target > targetEnd) { - --source; /* Back up source pointer! */ - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } -*sourceStart = source; -*targetStart = target; -return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF8toUTF32 (const UTF8** sourceStart, const UTF8* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF8* source = *sourceStart; - UTF32* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; - case 4: ch += *source++; ch <<= 6; - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up the source pointer! */ - result = targetExhausted; break; - } - if (ch <= UNI_MAX_LEGAL_UTF32) { - /* - * UTF-16 surrogate values are illegal in UTF-32, and anything - * over Plane 17 (> 0x10FFFF) is illegal. - */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead+1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = ch; - } - } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ - result = sourceIllegal; - *target++ = UNI_REPLACEMENT_CHAR; - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- - -Note A. -The fall-through switches in UTF-8 reading code save a -temp variable, some decrements & conditionals. The switches -are equivalent to the following loop: -{ - int tmpBytesToRead = extraBytesToRead+1; - do { - ch += *source++; - --tmpBytesToRead; - if (tmpBytesToRead) ch <<= 6; - } while (tmpBytesToRead > 0); -} -In UTF-8 writing code, the switches on "bytesToWrite" are -similarly unrolled loops. - ---------------------------------------------------------------------- */ diff --git a/breakpad/common/convert_UTF.h b/breakpad/common/convert_UTF.h deleted file mode 100644 index b1556de81..000000000 --- a/breakpad/common/convert_UTF.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2001-2004 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - -/* --------------------------------------------------------------------- - -Conversions between UTF32, UTF-16, and UTF-8. Header file. - -Several funtions are included here, forming a complete set of -conversions between the three formats. UTF-7 is not included -here, but is handled in a separate source file. - -Each of these routines takes pointers to input buffers and output -buffers. The input buffers are const. - -Each routine converts the text between *sourceStart and sourceEnd, -putting the result into the buffer between *targetStart and -targetEnd. Note: the end pointers are *after* the last item: e.g. -*(sourceEnd - 1) is the last item. - -The return result indicates whether the conversion was successful, -and if not, whether the problem was in the source or target buffers. -(Only the first encountered problem is indicated.) - -After the conversion, *sourceStart and *targetStart are both -updated to point to the end of last text successfully converted in -the respective buffers. - -Input parameters: -sourceStart - pointer to a pointer to the source buffer. -The contents of this are modified on return so that -it points at the next thing to be converted. -targetStart - similarly, pointer to pointer to the target buffer. -sourceEnd, targetEnd - respectively pointers to the ends of the -two buffers, for overflow checking only. - -These conversion functions take a ConversionFlags argument. When this -flag is set to strict, both irregular sequences and isolated surrogates -will cause an error. When the flag is set to lenient, both irregular -sequences and isolated surrogates are converted. - -Whether the flag is strict or lenient, all illegal sequences will cause -an error return. This includes sequences such as: , , -or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code -must check for illegal sequences. - -When the flag is set to lenient, characters over 0x10FFFF are converted -to the replacement character; otherwise (when the flag is set to strict) -they constitute an error. - -Output parameters: -The value "sourceIllegal" is returned from some routines if the input -sequence is malformed. When "sourceIllegal" is returned, the source -value will point to the illegal value that caused the problem. E.g., -in UTF-8 when a sequence is malformed, it points to the start of the -malformed sequence. - -Author: Mark E. Davis, 1994. -Rev History: Rick McGowan, fixes & updates May 2001. -Fixes & updates, Sept 2001. - ------------------------------------------------------------------------- */ - -/* --------------------------------------------------------------------- -The following 4 definitions are compiler-specific. -The C standard does not guarantee that wchar_t has at least -16 bits, so wchar_t is no less portable than unsigned short! -All should be unsigned values to avoid sign extension during -bit mask & shift operations. ------------------------------------------------------------------------- */ - -typedef unsigned long UTF32; /* at least 32 bits */ -typedef unsigned short UTF16; /* at least 16 bits */ -typedef unsigned char UTF8; /* typically 8 bits */ -typedef unsigned char Boolean; /* 0 or 1 */ - -/* Some fundamental constants */ -#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD -#define UNI_MAX_BMP (UTF32)0x0000FFFF -#define UNI_MAX_UTF16 (UTF32)0x0010FFFF -#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF -#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF - -typedef enum { - conversionOK, /* conversion successful */ - sourceExhausted, /* partial character in source, but hit end */ - targetExhausted, /* insuff. room in target for conversion */ - sourceIllegal /* source sequence is illegal/malformed */ -} ConversionResult; - -typedef enum { - strictConversion = 0, - lenientConversion -} ConversionFlags; - -/* This is for C++ and does no harm in C */ -#ifdef __cplusplus -extern "C" { -#endif - -ConversionResult ConvertUTF8toUTF16 (const UTF8** sourceStart, const UTF8* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF16toUTF8 (const UTF16** sourceStart, const UTF16* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF8toUTF32 (const UTF8** sourceStart, const UTF8* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF32toUTF8 (const UTF32** sourceStart, const UTF32* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF16toUTF32 (const UTF16** sourceStart, const UTF16* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF32toUTF16 (const UTF32** sourceStart, const UTF32* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); - -Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); - -#ifdef __cplusplus -} -#endif - -/* --------------------------------------------------------------------- */ diff --git a/breakpad/common/dwarf_cfi_to_module.cc b/breakpad/common/dwarf_cfi_to_module.cc deleted file mode 100644 index 15904d759..000000000 --- a/breakpad/common/dwarf_cfi_to_module.cc +++ /dev/null @@ -1,258 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// Implementation of google_breakpad::DwarfCFIToModule. -// See dwarf_cfi_to_module.h for details. - -#include - -#include "common/dwarf_cfi_to_module.h" - -namespace google_breakpad { - -using std::ostringstream; - -vector DwarfCFIToModule::RegisterNames::MakeVector( - const char * const *strings, - size_t size) { - vector names(strings, strings + size); - return names; -} - -vector DwarfCFIToModule::RegisterNames::I386() { - static const char *const names[] = { - "$eax", "$ecx", "$edx", "$ebx", "$esp", "$ebp", "$esi", "$edi", - "$eip", "$eflags", "$unused1", - "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7", - "$unused2", "$unused3", - "$xmm0", "$xmm1", "$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7", - "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7", - "$fcw", "$fsw", "$mxcsr", - "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused4", "$unused5", - "$tr", "$ldtr" - }; - - return MakeVector(names, sizeof(names) / sizeof(names[0])); -} - -vector DwarfCFIToModule::RegisterNames::X86_64() { - static const char *const names[] = { - "$rax", "$rdx", "$rcx", "$rbx", "$rsi", "$rdi", "$rbp", "$rsp", - "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", - "$rip", - "$xmm0","$xmm1","$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7", - "$xmm8","$xmm9","$xmm10","$xmm11","$xmm12","$xmm13","$xmm14","$xmm15", - "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7", - "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7", - "$rflags", - "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused1", "$unused2", - "$fs.base", "$gs.base", "$unused3", "$unused4", - "$tr", "$ldtr", - "$mxcsr", "$fcw", "$fsw" - }; - - return MakeVector(names, sizeof(names) / sizeof(names[0])); -} - -// Per ARM IHI 0040A, section 3.1 -vector DwarfCFIToModule::RegisterNames::ARM() { - static const char *const names[] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", - "fps", "cpsr", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", - "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", - "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", - "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7" - }; - - return MakeVector(names, sizeof(names) / sizeof(names[0])); -} - -bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length, - uint8 version, const string &augmentation, - unsigned return_address) { - assert(!entry_); - - // If dwarf2reader::CallFrameInfo can handle this version and - // augmentation, then we should be okay with that, so there's no - // need to check them here. - - // Get ready to collect entries. - entry_ = new Module::StackFrameEntry; - entry_->address = address; - entry_->size = length; - entry_offset_ = offset; - return_address_ = return_address; - - // Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI - // may not establish any rule for .ra if the return address column - // is an ordinary register, and that register holds the return - // address on entry to the function. So establish an initial .ra - // rule citing the return address register. - if (return_address_ < register_names_.size()) - entry_->initial_rules[ra_name_] = register_names_[return_address_]; - - return true; -} - -string DwarfCFIToModule::RegisterName(int i) { - assert(entry_); - if (i < 0) { - assert(i == kCFARegister); - return cfa_name_; - } - unsigned reg = i; - if (reg == return_address_) - return ra_name_; - - // Ensure that a non-empty name exists for this register value. - if (reg < register_names_.size() && !register_names_[reg].empty()) - return register_names_[reg]; - - reporter_->UnnamedRegister(entry_offset_, reg); - char buf[30]; - sprintf(buf, "unnamed_register%u", reg); - return buf; -} - -void DwarfCFIToModule::Record(Module::Address address, int reg, - const string &rule) { - assert(entry_); - - // Place the name in our global set of strings, and then use the string - // from the set. Even though the assignment looks like a copy, all the - // major std::string implementations use reference counting internally, - // so the effect is to have all our data structures share copies of rules - // whenever possible. Since register names are drawn from a - // vector, register names are already shared. - string shared_rule = *common_strings_.insert(rule).first; - - // Is this one of this entry's initial rules? - if (address == entry_->address) - entry_->initial_rules[RegisterName(reg)] = shared_rule; - // File it under the appropriate address. - else - entry_->rule_changes[address][RegisterName(reg)] = shared_rule; -} - -bool DwarfCFIToModule::UndefinedRule(uint64 address, int reg) { - reporter_->UndefinedNotSupported(entry_offset_, RegisterName(reg)); - // Treat this as a non-fatal error. - return true; -} - -bool DwarfCFIToModule::SameValueRule(uint64 address, int reg) { - ostringstream s; - s << RegisterName(reg); - Record(address, reg, s.str()); - return true; -} - -bool DwarfCFIToModule::OffsetRule(uint64 address, int reg, - int base_register, long offset) { - ostringstream s; - s << RegisterName(base_register) << " " << offset << " + ^"; - Record(address, reg, s.str()); - return true; -} - -bool DwarfCFIToModule::ValOffsetRule(uint64 address, int reg, - int base_register, long offset) { - ostringstream s; - s << RegisterName(base_register) << " " << offset << " +"; - Record(address, reg, s.str()); - return true; -} - -bool DwarfCFIToModule::RegisterRule(uint64 address, int reg, - int base_register) { - ostringstream s; - s << RegisterName(base_register); - Record(address, reg, s.str()); - return true; -} - -bool DwarfCFIToModule::ExpressionRule(uint64 address, int reg, - const string &expression) { - reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg)); - // Treat this as a non-fatal error. - return true; -} - -bool DwarfCFIToModule::ValExpressionRule(uint64 address, int reg, - const string &expression) { - reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg)); - // Treat this as a non-fatal error. - return true; -} - -bool DwarfCFIToModule::End() { - module_->AddStackFrameEntry(entry_); - entry_ = NULL; - return true; -} - -void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) { - fprintf(stderr, "%s, section '%s': " - "the call frame entry at offset 0x%zx refers to register %d," - " whose name we don't know\n", - file_.c_str(), section_.c_str(), offset, reg); -} - -void DwarfCFIToModule::Reporter::UndefinedNotSupported(size_t offset, - const string ®) { - fprintf(stderr, "%s, section '%s': " - "the call frame entry at offset 0x%zx sets the rule for " - "register '%s' to 'undefined', but the Breakpad symbol file format" - " cannot express this\n", - file_.c_str(), section_.c_str(), offset, reg.c_str()); -} - -void DwarfCFIToModule::Reporter::ExpressionsNotSupported(size_t offset, - const string ®) { - fprintf(stderr, "%s, section '%s': " - "the call frame entry at offset 0x%zx uses a DWARF expression to" - " describe how to recover register '%s', " - " but this translator cannot yet translate DWARF expressions to" - " Breakpad postfix expressions\n", - file_.c_str(), section_.c_str(), offset, reg.c_str()); -} - -} // namespace google_breakpad diff --git a/breakpad/common/dwarf_cfi_to_module.h b/breakpad/common/dwarf_cfi_to_module.h deleted file mode 100644 index 7db552a68..000000000 --- a/breakpad/common/dwarf_cfi_to_module.h +++ /dev/null @@ -1,196 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// dwarf_cfi_to_module.h: Define the DwarfCFIToModule class, which -// accepts parsed DWARF call frame info and adds it to a -// google_breakpad::Module object, which can write that information to -// a Breakpad symbol file. - -#ifndef COMMON_LINUX_DWARF_CFI_TO_MODULE_H -#define COMMON_LINUX_DWARF_CFI_TO_MODULE_H - -#include -#include - -#include -#include -#include - -#include "common/module.h" -#include "common/dwarf/dwarf2reader.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -using dwarf2reader::CallFrameInfo; -using google_breakpad::Module; -using std::set; -using std::vector; - -// A class that accepts parsed call frame information from the DWARF -// CFI parser and populates a google_breakpad::Module object with the -// contents. -class DwarfCFIToModule: public CallFrameInfo::Handler { - public: - - // DwarfCFIToModule uses an instance of this class to report errors - // detected while converting DWARF CFI to Breakpad STACK CFI records. - class Reporter { - public: - // Create a reporter that writes messages to the standard error - // stream. FILE is the name of the file we're processing, and - // SECTION is the name of the section within that file that we're - // looking at (.debug_frame, .eh_frame, etc.). - Reporter(const string &file, const string §ion) - : file_(file), section_(section) { } - virtual ~Reporter() { } - - // The DWARF CFI entry at OFFSET cites register REG, but REG is not - // covered by the vector of register names passed to the - // DwarfCFIToModule constructor, nor does it match the return - // address column number for this entry. - virtual void UnnamedRegister(size_t offset, int reg); - - // The DWARF CFI entry at OFFSET says that REG is undefined, but the - // Breakpad symbol file format cannot express this. - virtual void UndefinedNotSupported(size_t offset, const string ®); - - // The DWARF CFI entry at OFFSET says that REG uses a DWARF - // expression to find its value, but DwarfCFIToModule is not - // capable of translating DWARF expressions to Breakpad postfix - // expressions. - virtual void ExpressionsNotSupported(size_t offset, const string ®); - - protected: - string file_, section_; - }; - - // Register name tables. If TABLE is a vector returned by one of these - // functions, then TABLE[R] is the name of the register numbered R in - // DWARF call frame information. - class RegisterNames { - public: - // Intel's "x86" or IA-32. - static vector I386(); - - // AMD x86_64, AMD64, Intel EM64T, or Intel 64 - static vector X86_64(); - - // ARM. - static vector ARM(); - - private: - // Given STRINGS, an array of C strings with SIZE elements, return an - // equivalent vector. - static vector MakeVector(const char * const *strings, size_t size); - }; - - // Create a handler for the dwarf2reader::CallFrameInfo parser that - // records the stack unwinding information it receives in MODULE. - // - // Use REGISTER_NAMES[I] as the name of register number I; *this - // keeps a reference to the vector, so the vector should remain - // alive for as long as the DwarfCFIToModule does. - // - // Use REPORTER for reporting problems encountered in the conversion - // process. - DwarfCFIToModule(Module *module, const vector ®ister_names, - Reporter *reporter) - : module_(module), register_names_(register_names), reporter_(reporter), - entry_(NULL), return_address_(-1), cfa_name_(".cfa"), ra_name_(".ra") { - } - virtual ~DwarfCFIToModule() { delete entry_; } - - virtual bool Entry(size_t offset, uint64 address, uint64 length, - uint8 version, const string &augmentation, - unsigned return_address); - virtual bool UndefinedRule(uint64 address, int reg); - virtual bool SameValueRule(uint64 address, int reg); - virtual bool OffsetRule(uint64 address, int reg, - int base_register, long offset); - virtual bool ValOffsetRule(uint64 address, int reg, - int base_register, long offset); - virtual bool RegisterRule(uint64 address, int reg, int base_register); - virtual bool ExpressionRule(uint64 address, int reg, - const string &expression); - virtual bool ValExpressionRule(uint64 address, int reg, - const string &expression); - virtual bool End(); - - private: - // Return the name to use for register REG. - string RegisterName(int i); - - // Record RULE for register REG at ADDRESS. - void Record(Module::Address address, int reg, const string &rule); - - // The module to which we should add entries. - Module *module_; - - // Map from register numbers to register names. - const vector ®ister_names_; - - // The reporter to use to report problems. - Reporter *reporter_; - - // The current entry we're constructing. - Module::StackFrameEntry *entry_; - - // The section offset of the current frame description entry, for - // use in error messages. - size_t entry_offset_; - - // The return address column for that entry. - unsigned return_address_; - - // The names of the return address and canonical frame address. Putting - // these here instead of using string literals allows us to share their - // texts in reference-counted std::string implementations (all the - // popular ones). Many, many rules cite these strings. - string cfa_name_, ra_name_; - - // A set of strings used by this CFI. Before storing a string in one of - // our data structures, insert it into this set, and then use the string - // from the set. - // - // Because std::string uses reference counting internally, simply using - // strings from this set, even if passed by value, assigned, or held - // directly in structures and containers (map, for example), - // causes those strings to share a single instance of each distinct piece - // of text. - set common_strings_; -}; - -} // namespace google_breakpad - -#endif // COMMON_LINUX_DWARF_CFI_TO_MODULE_H diff --git a/breakpad/common/dwarf_cfi_to_module_unittest.cc b/breakpad/common/dwarf_cfi_to_module_unittest.cc deleted file mode 100644 index 807d1b20c..000000000 --- a/breakpad/common/dwarf_cfi_to_module_unittest.cc +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// dwarf_cfi_to_module_unittest.cc: Tests for google_breakpad::DwarfCFIToModule. - -#include -#include - -#include "breakpad_googletest_includes.h" -#include "common/dwarf_cfi_to_module.h" -#include "common/using_std_string.h" - -using std::vector; - -using google_breakpad::Module; -using google_breakpad::DwarfCFIToModule; -using testing::ContainerEq; -using testing::Test; -using testing::_; - -struct MockCFIReporter: public DwarfCFIToModule::Reporter { - MockCFIReporter(const string &file, const string §ion) - : Reporter(file, section) { } - MOCK_METHOD2(UnnamedRegister, void(size_t offset, int reg)); - MOCK_METHOD2(UndefinedNotSupported, void(size_t offset, const string ®)); - MOCK_METHOD2(ExpressionsNotSupported, void(size_t offset, const string ®)); -}; - -struct DwarfCFIToModuleFixture { - DwarfCFIToModuleFixture() - : module("module name", "module os", "module arch", "module id"), - reporter("reporter file", "reporter section"), - handler(&module, register_names, &reporter) { - register_names.push_back("reg0"); - register_names.push_back("reg1"); - register_names.push_back("reg2"); - register_names.push_back("reg3"); - register_names.push_back("reg4"); - register_names.push_back("reg5"); - register_names.push_back("reg6"); - register_names.push_back("reg7"); - register_names.push_back("sp"); - register_names.push_back("pc"); - register_names.push_back(""); - - EXPECT_CALL(reporter, UnnamedRegister(_, _)).Times(0); - EXPECT_CALL(reporter, UndefinedNotSupported(_, _)).Times(0); - EXPECT_CALL(reporter, ExpressionsNotSupported(_, _)).Times(0); - } - - Module module; - vector register_names; - MockCFIReporter reporter; - DwarfCFIToModule handler; - vector entries; -}; - -class Entry: public DwarfCFIToModuleFixture, public Test { }; - -TEST_F(Entry, Accept) { - ASSERT_TRUE(handler.Entry(0x3b8961b8, 0xa21069698096fc98ULL, - 0xb440ce248169c8d6ULL, 3, "", 0xea93c106)); - ASSERT_TRUE(handler.End()); - module.GetStackFrameEntries(&entries); - EXPECT_EQ(1U, entries.size()); - EXPECT_EQ(0xa21069698096fc98ULL, entries[0]->address); - EXPECT_EQ(0xb440ce248169c8d6ULL, entries[0]->size); - EXPECT_EQ(0U, entries[0]->initial_rules.size()); - EXPECT_EQ(0U, entries[0]->rule_changes.size()); -} - -TEST_F(Entry, AcceptOldVersion) { - ASSERT_TRUE(handler.Entry(0xeb60e0fc, 0x75b8806bb09eab78ULL, - 0xc771f44958d40bbcULL, 1, "", 0x093c945e)); - ASSERT_TRUE(handler.End()); - module.GetStackFrameEntries(&entries); - EXPECT_EQ(1U, entries.size()); - EXPECT_EQ(0x75b8806bb09eab78ULL, entries[0]->address); - EXPECT_EQ(0xc771f44958d40bbcULL, entries[0]->size); - EXPECT_EQ(0U, entries[0]->initial_rules.size()); - EXPECT_EQ(0U, entries[0]->rule_changes.size()); -} - -struct RuleFixture: public DwarfCFIToModuleFixture { - RuleFixture() : DwarfCFIToModuleFixture() { - entry_address = 0x89327ebf86b47492ULL; - entry_size = 0x2f8cd573072fe02aULL; - return_reg = 0x7886a346; - } - void StartEntry() { - ASSERT_TRUE(handler.Entry(0x4445c05c, entry_address, entry_size, - 3, "", return_reg)); - } - void CheckEntry() { - module.GetStackFrameEntries(&entries); - EXPECT_EQ(1U, entries.size()); - EXPECT_EQ(entry_address, entries[0]->address); - EXPECT_EQ(entry_size, entries[0]->size); - } - uint64 entry_address, entry_size; - unsigned return_reg; -}; - -class Rule: public RuleFixture, public Test { }; - -TEST_F(Rule, UndefinedRule) { - EXPECT_CALL(reporter, UndefinedNotSupported(_, "reg7")); - StartEntry(); - ASSERT_TRUE(handler.UndefinedRule(entry_address, 7)); - ASSERT_TRUE(handler.End()); - CheckEntry(); - EXPECT_EQ(0U, entries[0]->initial_rules.size()); - EXPECT_EQ(0U, entries[0]->rule_changes.size()); -} - -TEST_F(Rule, RegisterWithEmptyName) { - EXPECT_CALL(reporter, UnnamedRegister(_, 10)); - EXPECT_CALL(reporter, UndefinedNotSupported(_, "unnamed_register10")); - StartEntry(); - ASSERT_TRUE(handler.UndefinedRule(entry_address, 10)); - ASSERT_TRUE(handler.End()); - CheckEntry(); - EXPECT_EQ(0U, entries[0]->initial_rules.size()); - EXPECT_EQ(0U, entries[0]->rule_changes.size()); -} - -TEST_F(Rule, SameValueRule) { - StartEntry(); - ASSERT_TRUE(handler.SameValueRule(entry_address, 6)); - ASSERT_TRUE(handler.End()); - CheckEntry(); - Module::RuleMap expected_initial; - expected_initial["reg6"] = "reg6"; - EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial)); - EXPECT_EQ(0U, entries[0]->rule_changes.size()); -} - -TEST_F(Rule, OffsetRule) { - StartEntry(); - ASSERT_TRUE(handler.OffsetRule(entry_address + 1, return_reg, - DwarfCFIToModule::kCFARegister, - 16927065)); - ASSERT_TRUE(handler.End()); - CheckEntry(); - EXPECT_EQ(0U, entries[0]->initial_rules.size()); - Module::RuleChangeMap expected_changes; - expected_changes[entry_address + 1][".ra"] = ".cfa 16927065 + ^"; - EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes)); -} - -TEST_F(Rule, OffsetRuleNegative) { - StartEntry(); - ASSERT_TRUE(handler.OffsetRule(entry_address + 1, - DwarfCFIToModule::kCFARegister, 4, -34530721)); - ASSERT_TRUE(handler.End()); - CheckEntry(); - EXPECT_EQ(0U, entries[0]->initial_rules.size()); - Module::RuleChangeMap expected_changes; - expected_changes[entry_address + 1][".cfa"] = "reg4 -34530721 + ^"; - EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes)); -} - -TEST_F(Rule, ValOffsetRule) { - // Use an unnamed register number, to exercise that branch of RegisterName. - EXPECT_CALL(reporter, UnnamedRegister(_, 11)); - StartEntry(); - ASSERT_TRUE(handler.ValOffsetRule(entry_address + 0x5ab7, - DwarfCFIToModule::kCFARegister, - 11, 61812979)); - ASSERT_TRUE(handler.End()); - CheckEntry(); - EXPECT_EQ(0U, entries[0]->initial_rules.size()); - Module::RuleChangeMap expected_changes; - expected_changes[entry_address + 0x5ab7][".cfa"] = - "unnamed_register11 61812979 +"; - EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes)); -} - -TEST_F(Rule, RegisterRule) { - StartEntry(); - ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 3)); - ASSERT_TRUE(handler.End()); - CheckEntry(); - Module::RuleMap expected_initial; - expected_initial[".ra"] = "reg3"; - EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial)); - EXPECT_EQ(0U, entries[0]->rule_changes.size()); -} - -TEST_F(Rule, ExpressionRule) { - EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg2")); - StartEntry(); - ASSERT_TRUE(handler.ExpressionRule(entry_address + 0xf326, 2, - "it takes two to tango")); - ASSERT_TRUE(handler.End()); - CheckEntry(); - EXPECT_EQ(0U, entries[0]->initial_rules.size()); - EXPECT_EQ(0U, entries[0]->rule_changes.size()); -} - -TEST_F(Rule, ValExpressionRule) { - EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg0")); - StartEntry(); - ASSERT_TRUE(handler.ValExpressionRule(entry_address + 0x6367, 0, - "bit off more than he could chew")); - ASSERT_TRUE(handler.End()); - CheckEntry(); - EXPECT_EQ(0U, entries[0]->initial_rules.size()); - EXPECT_EQ(0U, entries[0]->rule_changes.size()); -} - -TEST_F(Rule, DefaultReturnAddressRule) { - return_reg = 2; - StartEntry(); - ASSERT_TRUE(handler.RegisterRule(entry_address, 0, 1)); - ASSERT_TRUE(handler.End()); - CheckEntry(); - Module::RuleMap expected_initial; - expected_initial[".ra"] = "reg2"; - expected_initial["reg0"] = "reg1"; - EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial)); - EXPECT_EQ(0U, entries[0]->rule_changes.size()); -} - -TEST_F(Rule, DefaultReturnAddressRuleOverride) { - return_reg = 2; - StartEntry(); - ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 1)); - ASSERT_TRUE(handler.End()); - CheckEntry(); - Module::RuleMap expected_initial; - expected_initial[".ra"] = "reg1"; - EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial)); - EXPECT_EQ(0U, entries[0]->rule_changes.size()); -} - -TEST_F(Rule, DefaultReturnAddressRuleLater) { - return_reg = 2; - StartEntry(); - ASSERT_TRUE(handler.RegisterRule(entry_address + 1, return_reg, 1)); - ASSERT_TRUE(handler.End()); - CheckEntry(); - Module::RuleMap expected_initial; - expected_initial[".ra"] = "reg2"; - EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial)); - Module::RuleChangeMap expected_changes; - expected_changes[entry_address + 1][".ra"] = "reg1"; - EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes)); -} - -TEST(RegisterNames, I386) { - vector names = DwarfCFIToModule::RegisterNames::I386(); - - EXPECT_EQ("$eax", names[0]); - EXPECT_EQ("$ecx", names[1]); - EXPECT_EQ("$esp", names[4]); - EXPECT_EQ("$eip", names[8]); -} - -TEST(RegisterNames, ARM) { - vector names = DwarfCFIToModule::RegisterNames::ARM(); - - EXPECT_EQ("r0", names[0]); - EXPECT_EQ("r10", names[10]); - EXPECT_EQ("sp", names[13]); - EXPECT_EQ("lr", names[14]); - EXPECT_EQ("pc", names[15]); -} - -TEST(RegisterNames, X86_64) { - vector names = DwarfCFIToModule::RegisterNames::X86_64(); - - EXPECT_EQ("$rax", names[0]); - EXPECT_EQ("$rdx", names[1]); - EXPECT_EQ("$rbp", names[6]); - EXPECT_EQ("$rsp", names[7]); - EXPECT_EQ("$rip", names[16]); -} diff --git a/breakpad/common/dwarf_cu_to_module.cc b/breakpad/common/dwarf_cu_to_module.cc deleted file mode 100644 index 8246daf9c..000000000 --- a/breakpad/common/dwarf_cu_to_module.cc +++ /dev/null @@ -1,1054 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// Implement the DwarfCUToModule class; see dwarf_cu_to_module.h. - -// For PRI* macros, before anything else might #include it. -#ifndef __STDC_FORMAT_MACROS -#define __STDC_FORMAT_MACROS -#endif /* __STDC_FORMAT_MACROS */ - -#include "common/dwarf_cu_to_module.h" - -#include -#if !defined(__ANDROID__) -#include -#endif -#include -#include - -#include -#include -#include - -#include "common/dwarf_line_to_module.h" - -namespace google_breakpad { - -using std::map; -using std::pair; -using std::set; -using std::sort; -using std::vector; - -// Data provided by a DWARF specification DIE. -// -// In DWARF, the DIE for a definition may contain a DW_AT_specification -// attribute giving the offset of the corresponding declaration DIE, and -// the definition DIE may omit information given in the declaration. For -// example, it's common for a function's address range to appear only in -// its definition DIE, but its name to appear only in its declaration -// DIE. -// -// The dumper needs to be able to follow DW_AT_specification links to -// bring all this information together in a FUNC record. Conveniently, -// DIEs that are the target of such links have a DW_AT_declaration flag -// set, so we can identify them when we first see them, and record their -// contents for later reference. -// -// A Specification holds information gathered from a declaration DIE that -// we may need if we find a DW_AT_specification link pointing to it. -struct DwarfCUToModule::Specification { - // The qualified name that can be found by demangling DW_AT_MIPS_linkage_name. - string qualified_name; - - // The name of the enclosing scope, or the empty string if there is none. - string enclosing_name; - - // The name for the specification DIE itself, without any enclosing - // name components. - string unqualified_name; -}; - -// An abstract origin -- base definition of an inline function. -struct AbstractOrigin { - AbstractOrigin() : name() {} - explicit AbstractOrigin(const string& name) : name(name) {} - - string name; -}; - -typedef map AbstractOriginByOffset; - -// Data global to the DWARF-bearing file that is private to the -// DWARF-to-Module process. -struct DwarfCUToModule::FilePrivate { - // A set of strings used in this CU. Before storing a string in one of - // our data structures, insert it into this set, and then use the string - // from the set. - // - // In some STL implementations, strings are reference-counted internally, - // meaning that simply using strings from this set, even if passed by - // value, assigned, or held directly in structures and containers - // (map, for example), causes those strings to share a - // single instance of each distinct piece of text. GNU's libstdc++ uses - // reference counts, and I believe MSVC did as well, at some point. - // However, C++ '11 implementations are moving away from reference - // counting. - // - // In other implementations, string assignments copy the string's text, - // so this set will actually hold yet another copy of the string (although - // everything will still work). To improve memory consumption portably, - // we will probably need to use pointers to strings held in this set. - set common_strings; - - // A map from offsets of DIEs within the .debug_info section to - // Specifications describing those DIEs. Specification references can - // cross compilation unit boundaries. - SpecificationByOffset specifications; - - AbstractOriginByOffset origins; -}; - -DwarfCUToModule::FileContext::FileContext(const string &filename, - Module *module, - bool handle_inter_cu_refs) - : filename_(filename), - module_(module), - handle_inter_cu_refs_(handle_inter_cu_refs), - file_private_(new FilePrivate()) { -} - -DwarfCUToModule::FileContext::~FileContext() { -} - -void DwarfCUToModule::FileContext::AddSectionToSectionMap( - const string& name, const char* contents, uint64 length) { - section_map_[name] = std::make_pair(contents, length); -} - -void DwarfCUToModule::FileContext::ClearSectionMapForTest() { - section_map_.clear(); -} - -const dwarf2reader::SectionMap& -DwarfCUToModule::FileContext::section_map() const { - return section_map_; -} - -void DwarfCUToModule::FileContext::ClearSpecifications() { - if (!handle_inter_cu_refs_) - file_private_->specifications.clear(); -} - -bool DwarfCUToModule::FileContext::IsUnhandledInterCUReference( - uint64 offset, uint64 compilation_unit_start) const { - if (handle_inter_cu_refs_) - return false; - return offset < compilation_unit_start; -} - -// Information global to the particular compilation unit we're -// parsing. This is for data shared across the CU's entire DIE tree, -// and parameters from the code invoking the CU parser. -struct DwarfCUToModule::CUContext { - CUContext(FileContext *file_context_arg, WarningReporter *reporter_arg) - : file_context(file_context_arg), - reporter(reporter_arg), - language(Language::CPlusPlus) {} - - ~CUContext() { - for (vector::iterator it = functions.begin(); - it != functions.end(); ++it) { - delete *it; - } - }; - - // The DWARF-bearing file into which this CU was incorporated. - FileContext *file_context; - - // For printing error messages. - WarningReporter *reporter; - - // The source language of this compilation unit. - const Language *language; - - // The functions defined in this compilation unit. We accumulate - // them here during parsing. Then, in DwarfCUToModule::Finish, we - // assign them lines and add them to file_context->module. - // - // Destroying this destroys all the functions this vector points to. - vector functions; -}; - -// Information about the context of a particular DIE. This is for -// information that changes as we descend the tree towards the leaves: -// the containing classes/namespaces, etc. -struct DwarfCUToModule::DIEContext { - // The fully-qualified name of the context. For example, for a - // tree like: - // - // DW_TAG_namespace Foo - // DW_TAG_class Bar - // DW_TAG_subprogram Baz - // - // in a C++ compilation unit, the DIEContext's name for the - // DW_TAG_subprogram DIE would be "Foo::Bar". The DIEContext's - // name for the DW_TAG_namespace DIE would be "". - string name; -}; - -// An abstract base class for all the dumper's DIE handlers. -class DwarfCUToModule::GenericDIEHandler: public dwarf2reader::DIEHandler { - public: - // Create a handler for the DIE at OFFSET whose compilation unit is - // described by CU_CONTEXT, and whose immediate context is described - // by PARENT_CONTEXT. - GenericDIEHandler(CUContext *cu_context, DIEContext *parent_context, - uint64 offset) - : cu_context_(cu_context), - parent_context_(parent_context), - offset_(offset), - declaration_(false), - specification_(NULL) { } - - // Derived classes' ProcessAttributeUnsigned can defer to this to - // handle DW_AT_declaration, or simply not override it. - void ProcessAttributeUnsigned(enum DwarfAttribute attr, - enum DwarfForm form, - uint64 data); - - // Derived classes' ProcessAttributeReference can defer to this to - // handle DW_AT_specification, or simply not override it. - void ProcessAttributeReference(enum DwarfAttribute attr, - enum DwarfForm form, - uint64 data); - - // Derived classes' ProcessAttributeReference can defer to this to - // handle DW_AT_specification, or simply not override it. - void ProcessAttributeString(enum DwarfAttribute attr, - enum DwarfForm form, - const string &data); - - protected: - // Compute and return the fully-qualified name of the DIE. If this - // DIE is a declaration DIE, to be cited by other DIEs' - // DW_AT_specification attributes, record its enclosing name and - // unqualified name in the specification table. - // - // Use this from EndAttributes member functions, not ProcessAttribute* - // functions; only the former can be sure that all the DIE's attributes - // have been seen. - string ComputeQualifiedName(); - - CUContext *cu_context_; - DIEContext *parent_context_; - uint64 offset_; - - // Place the name in the global set of strings. Even though this looks - // like a copy, all the major std::string implementations use reference - // counting internally, so the effect is to have all the data structures - // share copies of strings whenever possible. - // FIXME: Should this return something like a string_ref to avoid the - // assumption about how strings are implemented? - string AddStringToPool(const string &str); - - // If this DIE has a DW_AT_declaration attribute, this is its value. - // It is false on DIEs with no DW_AT_declaration attribute. - bool declaration_; - - // If this DIE has a DW_AT_specification attribute, this is the - // Specification structure for the DIE the attribute refers to. - // Otherwise, this is NULL. - Specification *specification_; - - // The value of the DW_AT_name attribute, or the empty string if the - // DIE has no such attribute. - string name_attribute_; - - // The demangled value of the DW_AT_MIPS_linkage_name attribute, or the empty - // string if the DIE has no such attribute or its content could not be - // demangled. - string demangled_name_; -}; - -void DwarfCUToModule::GenericDIEHandler::ProcessAttributeUnsigned( - enum DwarfAttribute attr, - enum DwarfForm form, - uint64 data) { - switch (attr) { - case dwarf2reader::DW_AT_declaration: declaration_ = (data != 0); break; - default: break; - } -} - -void DwarfCUToModule::GenericDIEHandler::ProcessAttributeReference( - enum DwarfAttribute attr, - enum DwarfForm form, - uint64 data) { - switch (attr) { - case dwarf2reader::DW_AT_specification: { - FileContext *file_context = cu_context_->file_context; - if (file_context->IsUnhandledInterCUReference( - data, cu_context_->reporter->cu_offset())) { - cu_context_->reporter->UnhandledInterCUReference(offset_, data); - break; - } - // Find the Specification to which this attribute refers, and - // set specification_ appropriately. We could do more processing - // here, but it's better to leave the real work to our - // EndAttribute member function, at which point we know we have - // seen all the DIE's attributes. - SpecificationByOffset *specifications = - &file_context->file_private_->specifications; - SpecificationByOffset::iterator spec = specifications->find(data); - if (spec != specifications->end()) { - specification_ = &spec->second; - } else { - // Technically, there's no reason a DW_AT_specification - // couldn't be a forward reference, but supporting that would - // be a lot of work (changing to a two-pass structure), and I - // don't think any producers we care about ever emit such - // things. - cu_context_->reporter->UnknownSpecification(offset_, data); - } - break; - } - default: break; - } -} - -string DwarfCUToModule::GenericDIEHandler::AddStringToPool(const string &str) { - pair::iterator, bool> result = - cu_context_->file_context->file_private_->common_strings.insert(str); - return *result.first; -} - -void DwarfCUToModule::GenericDIEHandler::ProcessAttributeString( - enum DwarfAttribute attr, - enum DwarfForm form, - const string &data) { - switch (attr) { - case dwarf2reader::DW_AT_name: - name_attribute_ = AddStringToPool(data); - break; - case dwarf2reader::DW_AT_MIPS_linkage_name: { - char* demangled = NULL; -#if !defined(__ANDROID__) - demangled = abi::__cxa_demangle(data.c_str(), NULL, NULL, NULL); -#endif - if (demangled) { - demangled_name_ = AddStringToPool(demangled); - free(reinterpret_cast(demangled)); - } - break; - } - default: break; - } -} - -string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() { - // Use the demangled name, if one is available. Demangled names are - // preferable to those inferred from the DWARF structure because they - // include argument types. - const string *qualified_name = NULL; - if (!demangled_name_.empty()) { - // Found it is this DIE. - qualified_name = &demangled_name_; - } else if (specification_ && !specification_->qualified_name.empty()) { - // Found it on the specification. - qualified_name = &specification_->qualified_name; - } - - const string *unqualified_name; - const string *enclosing_name; - if (!qualified_name) { - // Find our unqualified name. If the DIE has its own DW_AT_name - // attribute, then use that; otherwise, check our specification. - if (name_attribute_.empty() && specification_) - unqualified_name = &specification_->unqualified_name; - else - unqualified_name = &name_attribute_; - - // Find the name of our enclosing context. If we have a - // specification, it's the specification's enclosing context that - // counts; otherwise, use this DIE's context. - if (specification_) - enclosing_name = &specification_->enclosing_name; - else - enclosing_name = &parent_context_->name; - } - - // If this DIE was marked as a declaration, record its names in the - // specification table. - if (declaration_) { - Specification spec; - if (qualified_name) { - spec.qualified_name = *qualified_name; - } else { - spec.enclosing_name = *enclosing_name; - spec.unqualified_name = *unqualified_name; - } - cu_context_->file_context->file_private_->specifications[offset_] = spec; - } - - if (qualified_name) - return *qualified_name; - - // Combine the enclosing name and unqualified name to produce our - // own fully-qualified name. - return cu_context_->language->MakeQualifiedName(*enclosing_name, - *unqualified_name); -} - -// A handler class for DW_TAG_subprogram DIEs. -class DwarfCUToModule::FuncHandler: public GenericDIEHandler { - public: - FuncHandler(CUContext *cu_context, DIEContext *parent_context, - uint64 offset) - : GenericDIEHandler(cu_context, parent_context, offset), - low_pc_(0), high_pc_(0), high_pc_form_(dwarf2reader::DW_FORM_addr), - abstract_origin_(NULL), inline_(false) { } - void ProcessAttributeUnsigned(enum DwarfAttribute attr, - enum DwarfForm form, - uint64 data); - void ProcessAttributeSigned(enum DwarfAttribute attr, - enum DwarfForm form, - int64 data); - void ProcessAttributeReference(enum DwarfAttribute attr, - enum DwarfForm form, - uint64 data); - - bool EndAttributes(); - void Finish(); - - private: - // The fully-qualified name, as derived from name_attribute_, - // specification_, parent_context_. Computed in EndAttributes. - string name_; - uint64 low_pc_, high_pc_; // DW_AT_low_pc, DW_AT_high_pc - DwarfForm high_pc_form_; // DW_AT_high_pc can be length or address. - const AbstractOrigin* abstract_origin_; - bool inline_; -}; - -void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned( - enum DwarfAttribute attr, - enum DwarfForm form, - uint64 data) { - switch (attr) { - // If this attribute is present at all --- even if its value is - // DW_INL_not_inlined --- then GCC may cite it as someone else's - // DW_AT_abstract_origin attribute. - case dwarf2reader::DW_AT_inline: inline_ = true; break; - - case dwarf2reader::DW_AT_low_pc: low_pc_ = data; break; - case dwarf2reader::DW_AT_high_pc: - high_pc_form_ = form; - high_pc_ = data; - break; - - default: - GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data); - break; - } -} - -void DwarfCUToModule::FuncHandler::ProcessAttributeSigned( - enum DwarfAttribute attr, - enum DwarfForm form, - int64 data) { - switch (attr) { - // If this attribute is present at all --- even if its value is - // DW_INL_not_inlined --- then GCC may cite it as someone else's - // DW_AT_abstract_origin attribute. - case dwarf2reader::DW_AT_inline: inline_ = true; break; - - default: - break; - } -} - -void DwarfCUToModule::FuncHandler::ProcessAttributeReference( - enum DwarfAttribute attr, - enum DwarfForm form, - uint64 data) { - switch (attr) { - case dwarf2reader::DW_AT_abstract_origin: { - const AbstractOriginByOffset& origins = - cu_context_->file_context->file_private_->origins; - AbstractOriginByOffset::const_iterator origin = origins.find(data); - if (origin != origins.end()) { - abstract_origin_ = &(origin->second); - } else { - cu_context_->reporter->UnknownAbstractOrigin(offset_, data); - } - break; - } - default: - GenericDIEHandler::ProcessAttributeReference(attr, form, data); - break; - } -} - -bool DwarfCUToModule::FuncHandler::EndAttributes() { - // Compute our name, and record a specification, if appropriate. - name_ = ComputeQualifiedName(); - if (name_.empty() && abstract_origin_) { - name_ = abstract_origin_->name; - } - return true; -} - -void DwarfCUToModule::FuncHandler::Finish() { - // Make high_pc_ an address, if it isn't already. - if (high_pc_form_ != dwarf2reader::DW_FORM_addr) { - high_pc_ += low_pc_; - } - - // Did we collect the information we need? Not all DWARF function - // entries have low and high addresses (for example, inlined - // functions that were never used), but all the ones we're - // interested in cover a non-empty range of bytes. - if (low_pc_ < high_pc_) { - // Create a Module::Function based on the data we've gathered, and - // add it to the functions_ list. - Module::Function *func = new Module::Function; - // Malformed DWARF may omit the name, but all Module::Functions must - // have names. - if (!name_.empty()) { - func->name = name_; - } else { - cu_context_->reporter->UnnamedFunction(offset_); - func->name = ""; - } - func->address = low_pc_; - func->size = high_pc_ - low_pc_; - func->parameter_size = 0; - if (func->address) { - // If the function address is zero this is a sign that this function - // description is just empty debug data and should just be discarded. - cu_context_->functions.push_back(func); - } - } else if (inline_) { - AbstractOrigin origin(name_); - cu_context_->file_context->file_private_->origins[offset_] = origin; - } -} - -// A handler for DIEs that contain functions and contribute a -// component to their names: namespaces, classes, etc. -class DwarfCUToModule::NamedScopeHandler: public GenericDIEHandler { - public: - NamedScopeHandler(CUContext *cu_context, DIEContext *parent_context, - uint64 offset) - : GenericDIEHandler(cu_context, parent_context, offset) { } - bool EndAttributes(); - DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag); - - private: - DIEContext child_context_; // A context for our children. -}; - -bool DwarfCUToModule::NamedScopeHandler::EndAttributes() { - child_context_.name = ComputeQualifiedName(); - return true; -} - -dwarf2reader::DIEHandler *DwarfCUToModule::NamedScopeHandler::FindChildHandler( - uint64 offset, - enum DwarfTag tag) { - switch (tag) { - case dwarf2reader::DW_TAG_subprogram: - return new FuncHandler(cu_context_, &child_context_, offset); - case dwarf2reader::DW_TAG_namespace: - case dwarf2reader::DW_TAG_class_type: - case dwarf2reader::DW_TAG_structure_type: - case dwarf2reader::DW_TAG_union_type: - return new NamedScopeHandler(cu_context_, &child_context_, offset); - default: - return NULL; - } -} - -void DwarfCUToModule::WarningReporter::CUHeading() { - if (printed_cu_header_) - return; - fprintf(stderr, "%s: in compilation unit '%s' (offset 0x%llx):\n", - filename_.c_str(), cu_name_.c_str(), cu_offset_); - printed_cu_header_ = true; -} - -void DwarfCUToModule::WarningReporter::UnknownSpecification(uint64 offset, - uint64 target) { - CUHeading(); - fprintf(stderr, "%s: the DIE at offset 0x%llx has a DW_AT_specification" - " attribute referring to the die at offset 0x%llx, which either" - " was not marked as a declaration, or comes later in the file\n", - filename_.c_str(), offset, target); -} - -void DwarfCUToModule::WarningReporter::UnknownAbstractOrigin(uint64 offset, - uint64 target) { - CUHeading(); - fprintf(stderr, "%s: the DIE at offset 0x%llx has a DW_AT_abstract_origin" - " attribute referring to the die at offset 0x%llx, which either" - " was not marked as an inline, or comes later in the file\n", - filename_.c_str(), offset, target); -} - -void DwarfCUToModule::WarningReporter::MissingSection(const string &name) { - CUHeading(); - fprintf(stderr, "%s: warning: couldn't find DWARF '%s' section\n", - filename_.c_str(), name.c_str()); -} - -void DwarfCUToModule::WarningReporter::BadLineInfoOffset(uint64 offset) { - CUHeading(); - fprintf(stderr, "%s: warning: line number data offset beyond end" - " of '.debug_line' section\n", - filename_.c_str()); -} - -void DwarfCUToModule::WarningReporter::UncoveredHeading() { - if (printed_unpaired_header_) - return; - CUHeading(); - fprintf(stderr, "%s: warning: skipping unpaired lines/functions:\n", - filename_.c_str()); - printed_unpaired_header_ = true; -} - -void DwarfCUToModule::WarningReporter::UncoveredFunction( - const Module::Function &function) { - if (!uncovered_warnings_enabled_) - return; - UncoveredHeading(); - fprintf(stderr, " function%s: %s\n", - function.size == 0 ? " (zero-length)" : "", - function.name.c_str()); -} - -void DwarfCUToModule::WarningReporter::UncoveredLine(const Module::Line &line) { - if (!uncovered_warnings_enabled_) - return; - UncoveredHeading(); - fprintf(stderr, " line%s: %s:%d at 0x%" PRIx64 "\n", - (line.size == 0 ? " (zero-length)" : ""), - line.file->name.c_str(), line.number, line.address); -} - -void DwarfCUToModule::WarningReporter::UnnamedFunction(uint64 offset) { - CUHeading(); - fprintf(stderr, "%s: warning: function at offset 0x%llx has no name\n", - filename_.c_str(), offset); -} - -void DwarfCUToModule::WarningReporter::UnhandledInterCUReference( - uint64 offset, uint64 target) { - CUHeading(); - fprintf(stderr, "%s: warning: the DIE at offset 0x%llx has a " - "DW_FORM_ref_addr attribute with an inter-CU reference to " - "0x%llx, but inter-CU reference handling is turned off.\n", - filename_.c_str(), offset, target); -} - -DwarfCUToModule::DwarfCUToModule(FileContext *file_context, - LineToModuleHandler *line_reader, - WarningReporter *reporter) - : line_reader_(line_reader), - cu_context_(new CUContext(file_context, reporter)), - child_context_(new DIEContext()), - has_source_line_info_(false) { -} - -DwarfCUToModule::~DwarfCUToModule() { -} - -void DwarfCUToModule::ProcessAttributeSigned(enum DwarfAttribute attr, - enum DwarfForm form, - int64 data) { - switch (attr) { - case dwarf2reader::DW_AT_language: // source language of this CU - SetLanguage(static_cast(data)); - break; - default: - break; - } -} - -void DwarfCUToModule::ProcessAttributeUnsigned(enum DwarfAttribute attr, - enum DwarfForm form, - uint64 data) { - switch (attr) { - case dwarf2reader::DW_AT_stmt_list: // Line number information. - has_source_line_info_ = true; - source_line_offset_ = data; - break; - case dwarf2reader::DW_AT_language: // source language of this CU - SetLanguage(static_cast(data)); - break; - default: - break; - } -} - -void DwarfCUToModule::ProcessAttributeString(enum DwarfAttribute attr, - enum DwarfForm form, - const string &data) { - switch (attr) { - case dwarf2reader::DW_AT_name: - cu_context_->reporter->SetCUName(data); - break; - case dwarf2reader::DW_AT_comp_dir: - line_reader_->StartCompilationUnit(data); - break; - default: - break; - } -} - -bool DwarfCUToModule::EndAttributes() { - return true; -} - -dwarf2reader::DIEHandler *DwarfCUToModule::FindChildHandler( - uint64 offset, - enum DwarfTag tag) { - switch (tag) { - case dwarf2reader::DW_TAG_subprogram: - return new FuncHandler(cu_context_.get(), child_context_.get(), offset); - case dwarf2reader::DW_TAG_namespace: - case dwarf2reader::DW_TAG_class_type: - case dwarf2reader::DW_TAG_structure_type: - case dwarf2reader::DW_TAG_union_type: - return new NamedScopeHandler(cu_context_.get(), child_context_.get(), - offset); - default: - return NULL; - } -} - -void DwarfCUToModule::SetLanguage(DwarfLanguage language) { - switch (language) { - case dwarf2reader::DW_LANG_Java: - cu_context_->language = Language::Java; - break; - - // DWARF has no generic language code for assembly language; this is - // what the GNU toolchain uses. - case dwarf2reader::DW_LANG_Mips_Assembler: - cu_context_->language = Language::Assembler; - break; - - // C++ covers so many cases that it probably has some way to cope - // with whatever the other languages throw at us. So make it the - // default. - // - // Objective C and Objective C++ seem to create entries for - // methods whose DW_AT_name values are already fully-qualified: - // "-[Classname method:]". These appear at the top level. - // - // DWARF data for C should never include namespaces or functions - // nested in struct types, but if it ever does, then C++'s - // notation is probably not a bad choice for that. - default: - case dwarf2reader::DW_LANG_ObjC: - case dwarf2reader::DW_LANG_ObjC_plus_plus: - case dwarf2reader::DW_LANG_C: - case dwarf2reader::DW_LANG_C89: - case dwarf2reader::DW_LANG_C99: - case dwarf2reader::DW_LANG_C_plus_plus: - cu_context_->language = Language::CPlusPlus; - break; - } -} - -void DwarfCUToModule::ReadSourceLines(uint64 offset) { - const dwarf2reader::SectionMap §ion_map - = cu_context_->file_context->section_map(); - dwarf2reader::SectionMap::const_iterator map_entry - = section_map.find(".debug_line"); - // Mac OS X puts DWARF data in sections whose names begin with "__" - // instead of ".". - if (map_entry == section_map.end()) - map_entry = section_map.find("__debug_line"); - if (map_entry == section_map.end()) { - cu_context_->reporter->MissingSection(".debug_line"); - return; - } - const char *section_start = map_entry->second.first; - uint64 section_length = map_entry->second.second; - if (offset >= section_length) { - cu_context_->reporter->BadLineInfoOffset(offset); - return; - } - line_reader_->ReadProgram(section_start + offset, section_length - offset, - cu_context_->file_context->module_, &lines_); -} - -namespace { -// Return true if ADDRESS falls within the range of ITEM. -template -inline bool within(const T &item, Module::Address address) { - // Because Module::Address is unsigned, and unsigned arithmetic - // wraps around, this will be false if ADDRESS falls before the - // start of ITEM, or if it falls after ITEM's end. - return address - item.address < item.size; -} -} - -void DwarfCUToModule::AssignLinesToFunctions() { - vector *functions = &cu_context_->functions; - WarningReporter *reporter = cu_context_->reporter; - - // This would be simpler if we assumed that source line entries - // don't cross function boundaries. However, there's no real reason - // to assume that (say) a series of function definitions on the same - // line wouldn't get coalesced into one line number entry. The - // DWARF spec certainly makes no such promises. - // - // So treat the functions and lines as peers, and take the trouble - // to compute their ranges' intersections precisely. In any case, - // the hair here is a constant factor for performance; the - // complexity from here on out is linear. - - // Put both our functions and lines in order by address. - std::sort(functions->begin(), functions->end(), - Module::Function::CompareByAddress); - std::sort(lines_.begin(), lines_.end(), Module::Line::CompareByAddress); - - // The last line that we used any piece of. We use this only for - // generating warnings. - const Module::Line *last_line_used = NULL; - - // The last function and line we warned about --- so we can avoid - // doing so more than once. - const Module::Function *last_function_cited = NULL; - const Module::Line *last_line_cited = NULL; - - // Make a single pass through both vectors from lower to higher - // addresses, populating each Function's lines vector with lines - // from our lines_ vector that fall within the function's address - // range. - vector::iterator func_it = functions->begin(); - vector::const_iterator line_it = lines_.begin(); - - Module::Address current; - - // Pointers to the referents of func_it and line_it, or NULL if the - // iterator is at the end of the sequence. - Module::Function *func; - const Module::Line *line; - - // Start current at the beginning of the first line or function, - // whichever is earlier. - if (func_it != functions->end() && line_it != lines_.end()) { - func = *func_it; - line = &*line_it; - current = std::min(func->address, line->address); - } else if (line_it != lines_.end()) { - func = NULL; - line = &*line_it; - current = line->address; - } else if (func_it != functions->end()) { - func = *func_it; - line = NULL; - current = (*func_it)->address; - } else { - return; - } - - while (func || line) { - // This loop has two invariants that hold at the top. - // - // First, at least one of the iterators is not at the end of its - // sequence, and those that are not refer to the earliest - // function or line that contains or starts after CURRENT. - // - // Note that every byte is in one of four states: it is covered - // or not covered by a function, and, independently, it is - // covered or not covered by a line. - // - // The second invariant is that CURRENT refers to a byte whose - // state is different from its predecessor, or it refers to the - // first byte in the address space. In other words, CURRENT is - // always the address of a transition. - // - // Note that, although each iteration advances CURRENT from one - // transition address to the next in each iteration, it might - // not advance the iterators. Suppose we have a function that - // starts with a line, has a gap, and then a second line, and - // suppose that we enter an iteration with CURRENT at the end of - // the first line. The next transition address is the start of - // the second line, after the gap, so the iteration should - // advance CURRENT to that point. At the head of that iteration, - // the invariants require that the line iterator be pointing at - // the second line. But this is also true at the head of the - // next. And clearly, the iteration must not change the function - // iterator. So neither iterator moves. - - // Assert the first invariant (see above). - assert(!func || current < func->address || within(*func, current)); - assert(!line || current < line->address || within(*line, current)); - - // The next transition after CURRENT. - Module::Address next_transition; - - // Figure out which state we're in, add lines or warn, and compute - // the next transition address. - if (func && current >= func->address) { - if (line && current >= line->address) { - // Covered by both a line and a function. - Module::Address func_left = func->size - (current - func->address); - Module::Address line_left = line->size - (current - line->address); - // This may overflow, but things work out. - next_transition = current + std::min(func_left, line_left); - Module::Line l = *line; - l.address = current; - l.size = next_transition - current; - func->lines.push_back(l); - last_line_used = line; - } else { - // Covered by a function, but no line. - if (func != last_function_cited) { - reporter->UncoveredFunction(*func); - last_function_cited = func; - } - if (line && within(*func, line->address)) - next_transition = line->address; - else - // If this overflows, we'll catch it below. - next_transition = func->address + func->size; - } - } else { - if (line && current >= line->address) { - // Covered by a line, but no function. - // - // If GCC emits padding after one function to align the start - // of the next, then it will attribute the padding - // instructions to the last source line of function (to reduce - // the size of the line number info), but omit it from the - // DW_AT_{low,high}_pc range given in .debug_info (since it - // costs nothing to be precise there). If we did use at least - // some of the line we're about to skip, and it ends at the - // start of the next function, then assume this is what - // happened, and don't warn. - if (line != last_line_cited - && !(func - && line == last_line_used - && func->address - line->address == line->size)) { - reporter->UncoveredLine(*line); - last_line_cited = line; - } - if (func && within(*line, func->address)) - next_transition = func->address; - else - // If this overflows, we'll catch it below. - next_transition = line->address + line->size; - } else { - // Covered by neither a function nor a line. By the invariant, - // both func and line begin after CURRENT. The next transition - // is the start of the next function or next line, whichever - // is earliest. - assert(func || line); - if (func && line) - next_transition = std::min(func->address, line->address); - else if (func) - next_transition = func->address; - else - next_transition = line->address; - } - } - - // If a function or line abuts the end of the address space, then - // next_transition may end up being zero, in which case we've completed - // our pass. Handle that here, instead of trying to deal with it in - // each place we compute next_transition. - if (!next_transition) - break; - - // Advance iterators as needed. If lines overlap or functions overlap, - // then we could go around more than once. We don't worry too much - // about what result we produce in that case, just as long as we don't - // hang or crash. - while (func_it != functions->end() - && next_transition >= (*func_it)->address - && !within(**func_it, next_transition)) - func_it++; - func = (func_it != functions->end()) ? *func_it : NULL; - while (line_it != lines_.end() - && next_transition >= line_it->address - && !within(*line_it, next_transition)) - line_it++; - line = (line_it != lines_.end()) ? &*line_it : NULL; - - // We must make progress. - assert(next_transition > current); - current = next_transition; - } -} - -void DwarfCUToModule::Finish() { - // Assembly language files have no function data, and that gives us - // no place to store our line numbers (even though the GNU toolchain - // will happily produce source line info for assembly language - // files). To avoid spurious warnings about lines we can't assign - // to functions, skip CUs in languages that lack functions. - if (!cu_context_->language->HasFunctions()) - return; - - // Read source line info, if we have any. - if (has_source_line_info_) - ReadSourceLines(source_line_offset_); - - vector *functions = &cu_context_->functions; - - // Dole out lines to the appropriate functions. - AssignLinesToFunctions(); - - // Add our functions, which now have source lines assigned to them, - // to module_. - cu_context_->file_context->module_->AddFunctions(functions->begin(), - functions->end()); - - // Ownership of the function objects has shifted from cu_context to - // the Module. - functions->clear(); - - cu_context_->file_context->ClearSpecifications(); -} - -bool DwarfCUToModule::StartCompilationUnit(uint64 offset, - uint8 address_size, - uint8 offset_size, - uint64 cu_length, - uint8 dwarf_version) { - return dwarf_version >= 2; -} - -bool DwarfCUToModule::StartRootDIE(uint64 offset, enum DwarfTag tag) { - // We don't deal with partial compilation units (the only other tag - // likely to be used for root DIE). - return tag == dwarf2reader::DW_TAG_compile_unit; -} - -} // namespace google_breakpad diff --git a/breakpad/common/dwarf_cu_to_module.h b/breakpad/common/dwarf_cu_to_module.h deleted file mode 100644 index ab95485fc..000000000 --- a/breakpad/common/dwarf_cu_to_module.h +++ /dev/null @@ -1,315 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// Add DWARF debugging information to a Breakpad symbol file. This -// file defines the DwarfCUToModule class, which accepts parsed DWARF -// data and populates a google_breakpad::Module with the results; the -// Module can then write its contents as a Breakpad symbol file. - -#ifndef COMMON_LINUX_DWARF_CU_TO_MODULE_H__ -#define COMMON_LINUX_DWARF_CU_TO_MODULE_H__ - -#include - -#include "common/language.h" -#include "common/module.h" -#include "common/dwarf/bytereader.h" -#include "common/dwarf/dwarf2diehandler.h" -#include "common/dwarf/dwarf2reader.h" -#include "common/scoped_ptr.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -using dwarf2reader::DwarfAttribute; -using dwarf2reader::DwarfForm; -using dwarf2reader::DwarfLanguage; -using dwarf2reader::DwarfTag; - -// Populate a google_breakpad::Module with DWARF debugging information. -// -// An instance of this class can be provided as a handler to a -// dwarf2reader::DIEDispatcher, which can in turn be a handler for a -// dwarf2reader::CompilationUnit DWARF parser. The handler uses the results -// of parsing to populate a google_breakpad::Module with source file, -// function, and source line information. -class DwarfCUToModule: public dwarf2reader::RootDIEHandler { - struct FilePrivate; - public: - // Information global to the DWARF-bearing file we are processing, - // for use by DwarfCUToModule. Each DwarfCUToModule instance deals - // with a single compilation unit within the file, but information - // global to the whole file is held here. The client is responsible - // for filling it in appropriately (except for the 'file_private' - // field, which the constructor and destructor take care of), and - // then providing it to the DwarfCUToModule instance for each - // compilation unit we process in that file. Set HANDLE_INTER_CU_REFS - // to true to handle debugging symbols with DW_FORM_ref_addr entries. - class FileContext { - public: - FileContext(const string &filename, - Module *module, - bool handle_inter_cu_refs); - ~FileContext(); - - // Add CONTENTS of size LENGTH to the section map as NAME. - void AddSectionToSectionMap(const string& name, - const char* contents, - uint64 length); - - // Clear the section map for testing. - void ClearSectionMapForTest(); - - const dwarf2reader::SectionMap& section_map() const; - - private: - friend class DwarfCUToModule; - - // Clears all the Specifications if HANDLE_INTER_CU_REFS_ is false. - void ClearSpecifications(); - - // Given an OFFSET and a CU that starts at COMPILATION_UNIT_START, returns - // true if this is an inter-compilation unit reference that is not being - // handled. - bool IsUnhandledInterCUReference(uint64 offset, - uint64 compilation_unit_start) const; - - // The name of this file, for use in error messages. - const string filename_; - - // A map of this file's sections, used for finding other DWARF - // sections that the .debug_info section may refer to. - dwarf2reader::SectionMap section_map_; - - // The Module to which we're contributing definitions. - Module *module_; - - // True if we are handling references between compilation units. - const bool handle_inter_cu_refs_; - - // Inter-compilation unit data used internally by the handlers. - scoped_ptr file_private_; - }; - - // An abstract base class for handlers that handle DWARF line data - // for DwarfCUToModule. DwarfCUToModule could certainly just use - // dwarf2reader::LineInfo itself directly, but decoupling things - // this way makes unit testing a little easier. - class LineToModuleHandler { - public: - LineToModuleHandler() { } - virtual ~LineToModuleHandler() { } - - // Called at the beginning of a new compilation unit, prior to calling - // ReadProgram(). compilation_dir will indicate the path that the - // current compilation unit was compiled in, consistent with the - // DW_AT_comp_dir DIE. - virtual void StartCompilationUnit(const string& compilation_dir) = 0; - - // Populate MODULE and LINES with source file names and code/line - // mappings, given a pointer to some DWARF line number data - // PROGRAM, and an overestimate of its size. Add no zero-length - // lines to LINES. - virtual void ReadProgram(const char *program, uint64 length, - Module *module, vector *lines) = 0; - }; - - // The interface DwarfCUToModule uses to report warnings. The member - // function definitions for this class write messages to stderr, but - // you can override them if you'd like to detect or report these - // conditions yourself. - class WarningReporter { - public: - // Warn about problems in the DWARF file FILENAME, in the - // compilation unit at OFFSET. - WarningReporter(const string &filename, uint64 cu_offset) - : filename_(filename), cu_offset_(cu_offset), printed_cu_header_(false), - printed_unpaired_header_(false), - uncovered_warnings_enabled_(false) { } - virtual ~WarningReporter() { } - - // Set the name of the compilation unit we're processing to NAME. - virtual void SetCUName(const string &name) { cu_name_ = name; } - - // Accessor and setter for uncovered_warnings_enabled_. - // UncoveredFunction and UncoveredLine only report a problem if that is - // true. By default, these warnings are disabled, because those - // conditions occur occasionally in healthy code. - virtual bool uncovered_warnings_enabled() const { - return uncovered_warnings_enabled_; - } - virtual void set_uncovered_warnings_enabled(bool value) { - uncovered_warnings_enabled_ = value; - } - - // A DW_AT_specification in the DIE at OFFSET refers to a DIE we - // haven't processed yet, or that wasn't marked as a declaration, - // at TARGET. - virtual void UnknownSpecification(uint64 offset, uint64 target); - - // A DW_AT_abstract_origin in the DIE at OFFSET refers to a DIE we - // haven't processed yet, or that wasn't marked as inline, at TARGET. - virtual void UnknownAbstractOrigin(uint64 offset, uint64 target); - - // We were unable to find the DWARF section named SECTION_NAME. - virtual void MissingSection(const string §ion_name); - - // The CU's DW_AT_stmt_list offset OFFSET is bogus. - virtual void BadLineInfoOffset(uint64 offset); - - // FUNCTION includes code covered by no line number data. - virtual void UncoveredFunction(const Module::Function &function); - - // Line number NUMBER in LINE_FILE, of length LENGTH, includes code - // covered by no function. - virtual void UncoveredLine(const Module::Line &line); - - // The DW_TAG_subprogram DIE at OFFSET has no name specified directly - // in the DIE, nor via a DW_AT_specification or DW_AT_abstract_origin - // link. - virtual void UnnamedFunction(uint64 offset); - - // The DW_FORM_ref_addr at OFFSET to TARGET was not handled because - // FilePrivate did not retain the inter-CU specification data. - virtual void UnhandledInterCUReference(uint64 offset, uint64 target); - - uint64 cu_offset() const { - return cu_offset_; - } - - protected: - const string filename_; - const uint64 cu_offset_; - string cu_name_; - bool printed_cu_header_; - bool printed_unpaired_header_; - bool uncovered_warnings_enabled_; - - private: - // Print a per-CU heading, once. - void CUHeading(); - // Print an unpaired function/line heading, once. - void UncoveredHeading(); - }; - - // Create a DWARF debugging info handler for a compilation unit - // within FILE_CONTEXT. This uses information received from the - // dwarf2reader::CompilationUnit DWARF parser to populate - // FILE_CONTEXT->module. Use LINE_READER to handle the compilation - // unit's line number data. Use REPORTER to report problems with the - // data we find. - DwarfCUToModule(FileContext *file_context, - LineToModuleHandler *line_reader, - WarningReporter *reporter); - ~DwarfCUToModule(); - - void ProcessAttributeSigned(enum DwarfAttribute attr, - enum DwarfForm form, - int64 data); - void ProcessAttributeUnsigned(enum DwarfAttribute attr, - enum DwarfForm form, - uint64 data); - void ProcessAttributeString(enum DwarfAttribute attr, - enum DwarfForm form, - const string &data); - bool EndAttributes(); - DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag); - - // Assign all our source Lines to the Functions that cover their - // addresses, and then add them to module_. - void Finish(); - - bool StartCompilationUnit(uint64 offset, uint8 address_size, - uint8 offset_size, uint64 cu_length, - uint8 dwarf_version); - bool StartRootDIE(uint64 offset, enum DwarfTag tag); - - private: - // Used internally by the handler. Full definitions are in - // dwarf_cu_to_module.cc. - struct CUContext; - struct DIEContext; - struct Specification; - class GenericDIEHandler; - class FuncHandler; - class NamedScopeHandler; - - // A map from section offsets to specifications. - typedef map SpecificationByOffset; - - // Set this compilation unit's source language to LANGUAGE. - void SetLanguage(DwarfLanguage language); - - // Read source line information at OFFSET in the .debug_line - // section. Record source files in module_, but record source lines - // in lines_; we apportion them to functions in - // AssignLinesToFunctions. - void ReadSourceLines(uint64 offset); - - // Assign the lines in lines_ to the individual line lists of the - // functions in functions_. (DWARF line information maps an entire - // compilation unit at a time, and gives no indication of which - // lines belong to which functions, beyond their addresses.) - void AssignLinesToFunctions(); - - // The only reason cu_context_ and child_context_ are pointers is - // that we want to keep their definitions private to - // dwarf_cu_to_module.cc, instead of listing them all here. They are - // owned by this DwarfCUToModule: the constructor sets them, and the - // destructor deletes them. - - // The handler to use to handle line number data. - LineToModuleHandler *line_reader_; - - // This compilation unit's context. - scoped_ptr cu_context_; - - // A context for our children. - scoped_ptr child_context_; - - // True if this compilation unit has source line information. - bool has_source_line_info_; - - // The offset of this compilation unit's line number information in - // the .debug_line section. - uint64 source_line_offset_; - - // The line numbers we have seen thus far. We accumulate these here - // during parsing. Then, in Finish, we call AssignLinesToFunctions - // to dole them out to the appropriate functions. - vector lines_; -}; - -} // namespace google_breakpad - -#endif // COMMON_LINUX_DWARF_CU_TO_MODULE_H__ diff --git a/breakpad/common/dwarf_cu_to_module_unittest.cc b/breakpad/common/dwarf_cu_to_module_unittest.cc deleted file mode 100644 index 5f61a58e9..000000000 --- a/breakpad/common/dwarf_cu_to_module_unittest.cc +++ /dev/null @@ -1,1780 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// dwarf_cu_to_module.cc: Unit tests for google_breakpad::DwarfCUToModule. - -#include -#include -#include - -#include "breakpad_googletest_includes.h" -#include "common/dwarf_cu_to_module.h" -#include "common/using_std_string.h" - -using std::make_pair; -using std::vector; - -using dwarf2reader::DIEHandler; -using dwarf2reader::DwarfTag; -using dwarf2reader::DwarfAttribute; -using dwarf2reader::DwarfForm; -using dwarf2reader::DwarfInline; -using dwarf2reader::RootDIEHandler; -using google_breakpad::DwarfCUToModule; -using google_breakpad::Module; - -using ::testing::_; -using ::testing::AtMost; -using ::testing::Invoke; -using ::testing::Return; -using ::testing::Test; -using ::testing::TestWithParam; -using ::testing::Values; -using ::testing::ValuesIn; - -// Mock classes. - -class MockLineToModuleHandler: public DwarfCUToModule::LineToModuleHandler { - public: - MOCK_METHOD1(StartCompilationUnit, void(const string& compilation_dir)); - MOCK_METHOD4(ReadProgram, void(const char* program, uint64 length, - Module *module, vector *lines)); -}; - -class MockWarningReporter: public DwarfCUToModule::WarningReporter { - public: - MockWarningReporter(const string &filename, uint64 cu_offset) - : DwarfCUToModule::WarningReporter(filename, cu_offset) { } - MOCK_METHOD1(SetCUName, void(const string &name)); - MOCK_METHOD2(UnknownSpecification, void(uint64 offset, uint64 target)); - MOCK_METHOD2(UnknownAbstractOrigin, void(uint64 offset, uint64 target)); - MOCK_METHOD1(MissingSection, void(const string §ion_name)); - MOCK_METHOD1(BadLineInfoOffset, void(uint64 offset)); - MOCK_METHOD1(UncoveredFunction, void(const Module::Function &function)); - MOCK_METHOD1(UncoveredLine, void(const Module::Line &line)); - MOCK_METHOD1(UnnamedFunction, void(uint64 offset)); - MOCK_METHOD2(UnhandledInterCUReference, void(uint64 offset, uint64 target)); -}; - -// A fixture class including all the objects needed to handle a -// compilation unit, and their entourage. It includes member functions -// for doing common kinds of setup and tests. -class CUFixtureBase { - public: - // If we have: - // - // vector lines; - // AppendLinesFunctor appender(lines); - // - // then doing: - // - // appender(line_program, length, module, line_vector); - // - // will append lines to the end of line_vector. We can use this with - // MockLineToModuleHandler like this: - // - // MockLineToModuleHandler l2m; - // EXPECT_CALL(l2m, ReadProgram(_,_,_,_)) - // .WillOnce(DoAll(Invoke(appender), Return())); - // - // in which case calling l2m with some line vector will append lines. - class AppendLinesFunctor { - public: - explicit AppendLinesFunctor( - const vector *lines) : lines_(lines) { } - void operator()(const char *program, uint64 length, - Module *module, vector *lines) { - lines->insert(lines->end(), lines_->begin(), lines_->end()); - } - private: - const vector *lines_; - }; - - CUFixtureBase() - : module_("module-name", "module-os", "module-arch", "module-id"), - file_context_("dwarf-filename", &module_, true), - language_(dwarf2reader::DW_LANG_none), - language_signed_(false), - appender_(&lines_), - reporter_("dwarf-filename", 0xcf8f9bb6443d29b5LL), - root_handler_(&file_context_, &line_reader_, &reporter_), - functions_filled_(false) { - // By default, expect no warnings to be reported, and expect the - // compilation unit's name to be provided. The test can override - // these expectations. - EXPECT_CALL(reporter_, SetCUName("compilation-unit-name")).Times(1); - EXPECT_CALL(reporter_, UnknownSpecification(_, _)).Times(0); - EXPECT_CALL(reporter_, UnknownAbstractOrigin(_, _)).Times(0); - EXPECT_CALL(reporter_, MissingSection(_)).Times(0); - EXPECT_CALL(reporter_, BadLineInfoOffset(_)).Times(0); - EXPECT_CALL(reporter_, UncoveredFunction(_)).Times(0); - EXPECT_CALL(reporter_, UncoveredLine(_)).Times(0); - EXPECT_CALL(reporter_, UnnamedFunction(_)).Times(0); - EXPECT_CALL(reporter_, UnhandledInterCUReference(_, _)).Times(0); - - // By default, expect the line program reader not to be invoked. We - // may override this in StartCU. - EXPECT_CALL(line_reader_, StartCompilationUnit(_)).Times(0); - EXPECT_CALL(line_reader_, ReadProgram(_,_,_,_)).Times(0); - - // The handler will consult this section map to decide what to - // pass to our line reader. - file_context_.AddSectionToSectionMap(".debug_line", - dummy_line_program_, - dummy_line_size_); - } - - // Add a line with the given address, size, filename, and line - // number to the end of the statement list the handler will receive - // when it invokes its LineToModuleHandler. Call this before calling - // StartCU. - void PushLine(Module::Address address, Module::Address size, - const string &filename, int line_number); - - // Use LANGUAGE for the compilation unit. More precisely, arrange - // for StartCU to pass the compilation unit's root DIE a - // DW_AT_language attribute whose value is LANGUAGE. - void SetLanguage(dwarf2reader::DwarfLanguage language) { - language_ = language; - } - - // If SIGNED true, have StartCU report DW_AT_language as a signed - // attribute; if false, have it report it as unsigned. - void SetLanguageSigned(bool is_signed) { language_signed_ = is_signed; } - - // Call the handler this.root_handler_'s StartCompilationUnit and - // StartRootDIE member functions, passing it appropriate attributes as - // determined by prior calls to PushLine and SetLanguage. Leave - // this.root_handler_ ready to hear about children: call - // this.root_handler_.EndAttributes, but not this.root_handler_.Finish. - void StartCU(); - - // Have HANDLER process some strange attribute/form/value triples. - void ProcessStrangeAttributes(dwarf2reader::DIEHandler *handler); - - // Start a child DIE of PARENT with the given tag and name. Leave - // the handler ready to hear about children: call EndAttributes, but - // not Finish. - DIEHandler *StartNamedDIE(DIEHandler *parent, DwarfTag tag, - const string &name); - - // Start a child DIE of PARENT with the given tag and a - // DW_AT_specification attribute whose value is SPECIFICATION. Leave - // the handler ready to hear about children: call EndAttributes, but - // not Finish. If NAME is non-zero, use it as the DW_AT_name - // attribute. - DIEHandler *StartSpecifiedDIE(DIEHandler *parent, DwarfTag tag, - uint64 specification, const char *name = NULL); - - // Define a function as a child of PARENT with the given name, address, and - // size. If high_pc_form is DW_FORM_addr then the DW_AT_high_pc attribute - // will be written as an address; otherwise it will be written as the - // function's size. Call EndAttributes and Finish; one cannot define - // children of the defined function's DIE. - void DefineFunction(DIEHandler *parent, const string &name, - Module::Address address, Module::Address size, - const char* mangled_name, - DwarfForm high_pc_form = dwarf2reader::DW_FORM_addr); - - // Create a declaration DIE as a child of PARENT with the given - // offset, tag and name. If NAME is the empty string, don't provide - // a DW_AT_name attribute. Call EndAttributes and Finish. - void DeclarationDIE(DIEHandler *parent, uint64 offset, - DwarfTag tag, const string &name, - const string &mangled_name); - - // Create a definition DIE as a child of PARENT with the given tag - // that refers to the declaration DIE at offset SPECIFICATION as its - // specification. If NAME is non-empty, pass it as the DW_AT_name - // attribute. If SIZE is non-zero, record ADDRESS and SIZE as - // low_pc/high_pc attributes. - void DefinitionDIE(DIEHandler *parent, DwarfTag tag, - uint64 specification, const string &name, - Module::Address address = 0, Module::Address size = 0); - - // Create an inline DW_TAG_subprogram DIE as a child of PARENT. If - // SPECIFICATION is non-zero, then the DIE refers to the declaration DIE at - // offset SPECIFICATION as its specification. If Name is non-empty, pass it - // as the DW_AT_name attribute. - void AbstractInstanceDIE(DIEHandler *parent, uint64 offset, - DwarfInline type, uint64 specification, - const string &name, - DwarfForm form = dwarf2reader::DW_FORM_data1); - - // Create a DW_TAG_subprogram DIE as a child of PARENT that refers to - // ORIGIN in its DW_AT_abstract_origin attribute. If NAME is the empty - // string, don't provide a DW_AT_name attribute. - void DefineInlineInstanceDIE(DIEHandler *parent, const string &name, - uint64 origin, Module::Address address, - Module::Address size); - - // The following Test* functions should be called after calling - // this.root_handler_.Finish. After that point, no further calls - // should be made on the handler. - - // Test that the number of functions defined in the module this.module_ is - // equal to EXPECTED. - void TestFunctionCount(size_t expected); - - // Test that the I'th function (ordered by address) in the module - // this.module_ has the given name, address, and size, and that its - // parameter size is zero. - void TestFunction(int i, const string &name, - Module::Address address, Module::Address size); - - // Test that the number of source lines owned by the I'th function - // in the module this.module_ is equal to EXPECTED. - void TestLineCount(int i, size_t expected); - - // Test that the J'th line (ordered by address) of the I'th function - // (again, by address) has the given address, size, filename, and - // line number. - void TestLine(int i, int j, Module::Address address, Module::Address size, - const string &filename, int number); - - // Actual objects under test. - Module module_; - DwarfCUToModule::FileContext file_context_; - - // If this is not DW_LANG_none, we'll pass it as a DW_AT_language - // attribute to the compilation unit. This defaults to DW_LANG_none. - dwarf2reader::DwarfLanguage language_; - - // If this is true, report DW_AT_language as a signed value; if false, - // report it as an unsigned value. - bool language_signed_; - - // If this is not empty, we'll give the CU a DW_AT_comp_dir attribute that - // indicates the path that this compilation unit was compiled in. - string compilation_dir_; - - // If this is not empty, we'll give the CU a DW_AT_stmt_list - // attribute that, when passed to line_reader_, adds these lines to the - // provided lines array. - vector lines_; - - // Mock line program reader. - MockLineToModuleHandler line_reader_; - AppendLinesFunctor appender_; - static const char dummy_line_program_[]; - static const size_t dummy_line_size_; - - MockWarningReporter reporter_; - DwarfCUToModule root_handler_; - - private: - // Fill functions_, if we haven't already. - void FillFunctions(); - - // If functions_filled_ is true, this is a table of functions we've - // extracted from module_, sorted by address. - vector functions_; - // True if we have filled the above vector with this.module_'s function list. - bool functions_filled_; -}; - -const char CUFixtureBase::dummy_line_program_[] = "lots of fun data"; -const size_t CUFixtureBase::dummy_line_size_ = - sizeof(CUFixtureBase::dummy_line_program_); - -void CUFixtureBase::PushLine(Module::Address address, Module::Address size, - const string &filename, int line_number) { - Module::Line l; - l.address = address; - l.size = size; - l.file = module_.FindFile(filename); - l.number = line_number; - lines_.push_back(l); -} - -void CUFixtureBase::StartCU() { - if (!compilation_dir_.empty()) - EXPECT_CALL(line_reader_, - StartCompilationUnit(compilation_dir_)).Times(1); - - // If we have lines, make the line reader expect to be invoked at - // most once. (Hey, if the handler can pass its tests without - // bothering to read the line number data, that's great.) - // Have it add the lines passed to PushLine. Otherwise, leave the - // initial expectation (no calls) in force. - if (!lines_.empty()) - EXPECT_CALL(line_reader_, - ReadProgram(&dummy_line_program_[0], dummy_line_size_, - &module_, _)) - .Times(AtMost(1)) - .WillOnce(DoAll(Invoke(appender_), Return())); - - ASSERT_TRUE(root_handler_ - .StartCompilationUnit(0x51182ec307610b51ULL, 0x81, 0x44, - 0x4241b4f33720dd5cULL, 3)); - { - ASSERT_TRUE(root_handler_.StartRootDIE(0x02e56bfbda9e7337ULL, - dwarf2reader::DW_TAG_compile_unit)); - } - root_handler_.ProcessAttributeString(dwarf2reader::DW_AT_name, - dwarf2reader::DW_FORM_strp, - "compilation-unit-name"); - if (!compilation_dir_.empty()) - root_handler_.ProcessAttributeString(dwarf2reader::DW_AT_comp_dir, - dwarf2reader::DW_FORM_strp, - compilation_dir_); - if (!lines_.empty()) - root_handler_.ProcessAttributeUnsigned(dwarf2reader::DW_AT_stmt_list, - dwarf2reader::DW_FORM_ref4, - 0); - if (language_ != dwarf2reader::DW_LANG_none) { - if (language_signed_) - root_handler_.ProcessAttributeSigned(dwarf2reader::DW_AT_language, - dwarf2reader::DW_FORM_sdata, - language_); - else - root_handler_.ProcessAttributeUnsigned(dwarf2reader::DW_AT_language, - dwarf2reader::DW_FORM_udata, - language_); - } - ASSERT_TRUE(root_handler_.EndAttributes()); -} - -void CUFixtureBase::ProcessStrangeAttributes( - dwarf2reader::DIEHandler *handler) { - handler->ProcessAttributeUnsigned((DwarfAttribute) 0xf560dead, - (DwarfForm) 0x4106e4db, - 0xa592571997facda1ULL); - handler->ProcessAttributeSigned((DwarfAttribute) 0x85380095, - (DwarfForm) 0x0f16fe87, - 0x12602a4e3bf1f446LL); - handler->ProcessAttributeReference((DwarfAttribute) 0xf7f7480f, - (DwarfForm) 0x829e038a, - 0x50fddef44734fdecULL); - static const char buffer[10] = "frobynode"; - handler->ProcessAttributeBuffer((DwarfAttribute) 0xa55ffb51, - (DwarfForm) 0x2f43b041, - buffer, sizeof(buffer)); - handler->ProcessAttributeString((DwarfAttribute) 0x2f43b041, - (DwarfForm) 0x895ffa23, - "strange string"); -} - -DIEHandler *CUFixtureBase::StartNamedDIE(DIEHandler *parent, - DwarfTag tag, - const string &name) { - dwarf2reader::DIEHandler *handler - = parent->FindChildHandler(0x8f4c783c0467c989ULL, tag); - if (!handler) - return NULL; - handler->ProcessAttributeString(dwarf2reader::DW_AT_name, - dwarf2reader::DW_FORM_strp, - name); - ProcessStrangeAttributes(handler); - if (!handler->EndAttributes()) { - handler->Finish(); - delete handler; - return NULL; - } - - return handler; -} - -DIEHandler *CUFixtureBase::StartSpecifiedDIE(DIEHandler *parent, - DwarfTag tag, - uint64 specification, - const char *name) { - dwarf2reader::DIEHandler *handler - = parent->FindChildHandler(0x8f4c783c0467c989ULL, tag); - if (!handler) - return NULL; - if (name) - handler->ProcessAttributeString(dwarf2reader::DW_AT_name, - dwarf2reader::DW_FORM_strp, - name); - handler->ProcessAttributeReference(dwarf2reader::DW_AT_specification, - dwarf2reader::DW_FORM_ref4, - specification); - if (!handler->EndAttributes()) { - handler->Finish(); - delete handler; - return NULL; - } - - return handler; -} - -void CUFixtureBase::DefineFunction(dwarf2reader::DIEHandler *parent, - const string &name, Module::Address address, - Module::Address size, - const char* mangled_name, - DwarfForm high_pc_form) { - dwarf2reader::DIEHandler *func - = parent->FindChildHandler(0xe34797c7e68590a8LL, - dwarf2reader::DW_TAG_subprogram); - ASSERT_TRUE(func != NULL); - func->ProcessAttributeString(dwarf2reader::DW_AT_name, - dwarf2reader::DW_FORM_strp, - name); - func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc, - dwarf2reader::DW_FORM_addr, - address); - - Module::Address high_pc = size; - if (high_pc_form == dwarf2reader::DW_FORM_addr) { - high_pc += address; - } - func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc, - high_pc_form, - high_pc); - - if (mangled_name) - func->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name, - dwarf2reader::DW_FORM_strp, - mangled_name); - - ProcessStrangeAttributes(func); - EXPECT_TRUE(func->EndAttributes()); - func->Finish(); - delete func; -} - -void CUFixtureBase::DeclarationDIE(DIEHandler *parent, uint64 offset, - DwarfTag tag, - const string &name, - const string &mangled_name) { - dwarf2reader::DIEHandler *die = parent->FindChildHandler(offset, tag); - ASSERT_TRUE(die != NULL); - if (!name.empty()) - die->ProcessAttributeString(dwarf2reader::DW_AT_name, - dwarf2reader::DW_FORM_strp, - name); - if (!mangled_name.empty()) - die->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name, - dwarf2reader::DW_FORM_strp, - mangled_name); - - die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_declaration, - dwarf2reader::DW_FORM_flag, - 1); - EXPECT_TRUE(die->EndAttributes()); - die->Finish(); - delete die; -} - -void CUFixtureBase::DefinitionDIE(DIEHandler *parent, - DwarfTag tag, - uint64 specification, - const string &name, - Module::Address address, - Module::Address size) { - dwarf2reader::DIEHandler *die - = parent->FindChildHandler(0x6ccfea031a9e6cc9ULL, tag); - ASSERT_TRUE(die != NULL); - die->ProcessAttributeReference(dwarf2reader::DW_AT_specification, - dwarf2reader::DW_FORM_ref4, - specification); - if (!name.empty()) - die->ProcessAttributeString(dwarf2reader::DW_AT_name, - dwarf2reader::DW_FORM_strp, - name); - if (size) { - die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc, - dwarf2reader::DW_FORM_addr, - address); - die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc, - dwarf2reader::DW_FORM_addr, - address + size); - } - EXPECT_TRUE(die->EndAttributes()); - die->Finish(); - delete die; -} - -void CUFixtureBase::AbstractInstanceDIE(DIEHandler *parent, - uint64 offset, - DwarfInline type, - uint64 specification, - const string &name, - DwarfForm form) { - dwarf2reader::DIEHandler *die - = parent->FindChildHandler(offset, dwarf2reader::DW_TAG_subprogram); - ASSERT_TRUE(die != NULL); - if (specification != 0ULL) - die->ProcessAttributeReference(dwarf2reader::DW_AT_specification, - dwarf2reader::DW_FORM_ref4, - specification); - if (form == dwarf2reader::DW_FORM_sdata) { - die->ProcessAttributeSigned(dwarf2reader::DW_AT_inline, form, type); - } else { - die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_inline, form, type); - } - if (!name.empty()) - die->ProcessAttributeString(dwarf2reader::DW_AT_name, - dwarf2reader::DW_FORM_strp, - name); - - EXPECT_TRUE(die->EndAttributes()); - die->Finish(); - delete die; -} - -void CUFixtureBase::DefineInlineInstanceDIE(DIEHandler *parent, - const string &name, - uint64 origin, - Module::Address address, - Module::Address size) { - dwarf2reader::DIEHandler *func - = parent->FindChildHandler(0x11c70f94c6e87ccdLL, - dwarf2reader::DW_TAG_subprogram); - ASSERT_TRUE(func != NULL); - if (!name.empty()) { - func->ProcessAttributeString(dwarf2reader::DW_AT_name, - dwarf2reader::DW_FORM_strp, - name); - } - func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc, - dwarf2reader::DW_FORM_addr, - address); - func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc, - dwarf2reader::DW_FORM_addr, - address + size); - func->ProcessAttributeReference(dwarf2reader::DW_AT_abstract_origin, - dwarf2reader::DW_FORM_ref4, - origin); - ProcessStrangeAttributes(func); - EXPECT_TRUE(func->EndAttributes()); - func->Finish(); - delete func; -} - -void CUFixtureBase::FillFunctions() { - if (functions_filled_) - return; - module_.GetFunctions(&functions_, functions_.end()); - sort(functions_.begin(), functions_.end(), - Module::Function::CompareByAddress); - functions_filled_ = true; -} - -void CUFixtureBase::TestFunctionCount(size_t expected) { - FillFunctions(); - ASSERT_EQ(expected, functions_.size()); -} - -void CUFixtureBase::TestFunction(int i, const string &name, - Module::Address address, - Module::Address size) { - FillFunctions(); - ASSERT_LT((size_t) i, functions_.size()); - - Module::Function *function = functions_[i]; - EXPECT_EQ(name, function->name); - EXPECT_EQ(address, function->address); - EXPECT_EQ(size, function->size); - EXPECT_EQ(0U, function->parameter_size); -} - -void CUFixtureBase::TestLineCount(int i, size_t expected) { - FillFunctions(); - ASSERT_LT((size_t) i, functions_.size()); - - ASSERT_EQ(expected, functions_[i]->lines.size()); -} - -void CUFixtureBase::TestLine(int i, int j, - Module::Address address, Module::Address size, - const string &filename, int number) { - FillFunctions(); - ASSERT_LT((size_t) i, functions_.size()); - ASSERT_LT((size_t) j, functions_[i]->lines.size()); - - Module::Line *line = &functions_[i]->lines[j]; - EXPECT_EQ(address, line->address); - EXPECT_EQ(size, line->size); - EXPECT_EQ(filename, line->file->name.c_str()); - EXPECT_EQ(number, line->number); -} - -// Include caller locations for our test subroutines. -#define TRACE(call) do { SCOPED_TRACE("called from here"); call; } while (0) -#define PushLine(a,b,c,d) TRACE(PushLine((a),(b),(c),(d))) -#define SetLanguage(a) TRACE(SetLanguage(a)) -#define StartCU() TRACE(StartCU()) -#define DefineFunction(a,b,c,d,e) TRACE(DefineFunction((a),(b),(c),(d),(e))) -// (DefineFunction) instead of DefineFunction to avoid macro expansion. -#define DefineFunction6(a,b,c,d,e,f) \ - TRACE((DefineFunction)((a),(b),(c),(d),(e),(f))) -#define DeclarationDIE(a,b,c,d,e) TRACE(DeclarationDIE((a),(b),(c),(d),(e))) -#define DefinitionDIE(a,b,c,d,e,f) \ - TRACE(DefinitionDIE((a),(b),(c),(d),(e),(f))) -#define TestFunctionCount(a) TRACE(TestFunctionCount(a)) -#define TestFunction(a,b,c,d) TRACE(TestFunction((a),(b),(c),(d))) -#define TestLineCount(a,b) TRACE(TestLineCount((a),(b))) -#define TestLine(a,b,c,d,e,f) TRACE(TestLine((a),(b),(c),(d),(e),(f))) - -class SimpleCU: public CUFixtureBase, public Test { -}; - -TEST_F(SimpleCU, CompilationDir) { - compilation_dir_ = "/src/build/"; - - StartCU(); - root_handler_.Finish(); -} - -TEST_F(SimpleCU, OneFunc) { - PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772); - - StartCU(); - DefineFunction(&root_handler_, "function1", - 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, NULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "function1", 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL); - TestLineCount(0, 1); - TestLine(0, 0, 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", - 246571772); -} - -// As above, only DW_AT_high_pc is a length rather than an address. -TEST_F(SimpleCU, OneFuncHighPcIsLength) { - PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772); - - StartCU(); - DefineFunction6(&root_handler_, "function1", - 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, NULL, - dwarf2reader::DW_FORM_udata); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "function1", 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL); - TestLineCount(0, 1); - TestLine(0, 0, 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", - 246571772); -} - -TEST_F(SimpleCU, MangledName) { - PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772); - - StartCU(); - DefineFunction(&root_handler_, "function1", - 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "_ZN1n1fEi"); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "n::f(int)", 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL); -} - -TEST_F(SimpleCU, IrrelevantRootChildren) { - StartCU(); - EXPECT_FALSE(root_handler_ - .FindChildHandler(0x7db32bff4e2dcfb1ULL, - dwarf2reader::DW_TAG_lexical_block)); -} - -TEST_F(SimpleCU, IrrelevantNamedScopeChildren) { - StartCU(); - DIEHandler *class_A_handler - = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "class_A"); - EXPECT_TRUE(class_A_handler != NULL); - EXPECT_FALSE(class_A_handler - ->FindChildHandler(0x02e55999b865e4e9ULL, - dwarf2reader::DW_TAG_lexical_block)); - delete class_A_handler; -} - -// Verify that FileContexts can safely be deleted unused. -TEST_F(SimpleCU, UnusedFileContext) { - Module m("module-name", "module-os", "module-arch", "module-id"); - DwarfCUToModule::FileContext fc("dwarf-filename", &m, true); - - // Kludge: satisfy reporter_'s expectation. - reporter_.SetCUName("compilation-unit-name"); -} - -TEST_F(SimpleCU, InlineFunction) { - PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118); - - StartCU(); - AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL, - dwarf2reader::DW_INL_inlined, 0, "inline-name"); - DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL, - 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "inline-name", - 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL); -} - -TEST_F(SimpleCU, InlineFunctionSignedAttribute) { - PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118); - - StartCU(); - AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL, - dwarf2reader::DW_INL_inlined, 0, "inline-name", - dwarf2reader::DW_FORM_sdata); - DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL, - 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "inline-name", - 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL); -} - -// Any DIE with an DW_AT_inline attribute can be cited by -// DW_AT_abstract_origin attributes --- even if the value of the -// DW_AT_inline attribute is DW_INL_not_inlined. -TEST_F(SimpleCU, AbstractOriginNotInlined) { - PushLine(0x2805c4531be6ca0eULL, 0x686b52155a8d4d2cULL, "line-file", 6111581); - - StartCU(); - AbstractInstanceDIE(&root_handler_, 0x93e9cdad52826b39ULL, - dwarf2reader::DW_INL_not_inlined, 0, "abstract-instance"); - DefineInlineInstanceDIE(&root_handler_, "", 0x93e9cdad52826b39ULL, - 0x2805c4531be6ca0eULL, 0x686b52155a8d4d2cULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "abstract-instance", - 0x2805c4531be6ca0eULL, 0x686b52155a8d4d2cULL); -} - -TEST_F(SimpleCU, UnknownAbstractOrigin) { - EXPECT_CALL(reporter_, UnknownAbstractOrigin(_, 1ULL)).WillOnce(Return()); - EXPECT_CALL(reporter_, UnnamedFunction(0x11c70f94c6e87ccdLL)) - .WillOnce(Return()); - PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118); - - StartCU(); - AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL, - dwarf2reader::DW_INL_inlined, 0, "inline-name"); - DefineInlineInstanceDIE(&root_handler_, "", 1ULL, - 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "", - 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL); -} - -TEST_F(SimpleCU, UnnamedFunction) { - EXPECT_CALL(reporter_, UnnamedFunction(0xe34797c7e68590a8LL)) - .WillOnce(Return()); - PushLine(0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL, "line-file", 14044850); - - StartCU(); - DefineFunction(&root_handler_, "", - 0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL, NULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "", - 0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL); -} - -// An address range. -struct Range { - Module::Address start, end; -}; - -// Test data for pairing functions and lines. -struct Situation { - // Two function intervals, and two line intervals. - Range functions[2], lines[2]; - - // The number of lines we expect to be assigned to each of the - // functions, and the address ranges. - int paired_count[2]; - Range paired[2][2]; - - // The number of functions that are not entirely covered by lines, - // and vice versa. - int uncovered_functions, uncovered_lines; -}; - -#define PAIRING(func1_start, func1_end, func2_start, func2_end, \ - line1_start, line1_end, line2_start, line2_end, \ - func1_num_lines, func2_num_lines, \ - func1_line1_start, func1_line1_end, \ - func1_line2_start, func1_line2_end, \ - func2_line1_start, func2_line1_end, \ - func2_line2_start, func2_line2_end, \ - uncovered_functions, uncovered_lines) \ - { { { func1_start, func1_end }, { func2_start, func2_end } }, \ - { { line1_start, line1_end }, { line2_start, line2_end } }, \ - { func1_num_lines, func2_num_lines }, \ - { { { func1_line1_start, func1_line1_end }, \ - { func1_line2_start, func1_line2_end } }, \ - { { func2_line1_start, func2_line1_end }, \ - { func2_line2_start, func2_line2_end } } }, \ - uncovered_functions, uncovered_lines }, - -Situation situations[] = { -#include "common/testdata/func-line-pairing.h" -}; - -#undef PAIRING - -class FuncLinePairing: public CUFixtureBase, - public TestWithParam { }; - -INSTANTIATE_TEST_CASE_P(AllSituations, FuncLinePairing, - ValuesIn(situations)); - -TEST_P(FuncLinePairing, Pairing) { - const Situation &s = GetParam(); - PushLine(s.lines[0].start, - s.lines[0].end - s.lines[0].start, - "line-file", 67636963); - PushLine(s.lines[1].start, - s.lines[1].end - s.lines[1].start, - "line-file", 67636963); - if (s.uncovered_functions) - EXPECT_CALL(reporter_, UncoveredFunction(_)) - .Times(s.uncovered_functions) - .WillRepeatedly(Return()); - if (s.uncovered_lines) - EXPECT_CALL(reporter_, UncoveredLine(_)) - .Times(s.uncovered_lines) - .WillRepeatedly(Return()); - - StartCU(); - DefineFunction(&root_handler_, "function1", - s.functions[0].start, - s.functions[0].end - s.functions[0].start, NULL); - DefineFunction(&root_handler_, "function2", - s.functions[1].start, - s.functions[1].end - s.functions[1].start, NULL); - root_handler_.Finish(); - - TestFunctionCount(2); - TestFunction(0, "function1", - s.functions[0].start, - s.functions[0].end - s.functions[0].start); - TestLineCount(0, s.paired_count[0]); - for (int i = 0; i < s.paired_count[0]; i++) - TestLine(0, i, s.paired[0][i].start, - s.paired[0][i].end - s.paired[0][i].start, - "line-file", 67636963); - TestFunction(1, "function2", - s.functions[1].start, - s.functions[1].end - s.functions[1].start); - TestLineCount(1, s.paired_count[1]); - for (int i = 0; i < s.paired_count[1]; i++) - TestLine(1, i, s.paired[1][i].start, - s.paired[1][i].end - s.paired[1][i].start, - "line-file", 67636963); -} - -TEST_F(FuncLinePairing, EmptyCU) { - StartCU(); - root_handler_.Finish(); - - TestFunctionCount(0); -} - -TEST_F(FuncLinePairing, LinesNoFuncs) { - PushLine(40, 2, "line-file", 82485646); - EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return()); - - StartCU(); - root_handler_.Finish(); - - TestFunctionCount(0); -} - -TEST_F(FuncLinePairing, FuncsNoLines) { - EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return()); - - StartCU(); - DefineFunction(&root_handler_, "function1", 0x127da12ffcf5c51fULL, 0x1000U, - NULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "function1", 0x127da12ffcf5c51fULL, 0x1000U); -} - -TEST_F(FuncLinePairing, GapThenFunction) { - PushLine(20, 2, "line-file-2", 174314698); - PushLine(10, 2, "line-file-1", 263008005); - - StartCU(); - DefineFunction(&root_handler_, "function1", 10, 2, NULL); - DefineFunction(&root_handler_, "function2", 20, 2, NULL); - root_handler_.Finish(); - - TestFunctionCount(2); - TestFunction(0, "function1", 10, 2); - TestLineCount(0, 1); - TestLine(0, 0, 10, 2, "line-file-1", 263008005); - TestFunction(1, "function2", 20, 2); - TestLineCount(1, 1); - TestLine(1, 0, 20, 2, "line-file-2", 174314698); -} - -// If GCC emits padding after one function to align the start of -// the next, then it will attribute the padding instructions to -// the last source line of function (to reduce the size of the -// line number info), but omit it from the DW_AT_{low,high}_pc -// range given in .debug_info (since it costs nothing to be -// precise there). If we did use at least some of the line -// we're about to skip, then assume this is what happened, and -// don't warn. -TEST_F(FuncLinePairing, GCCAlignmentStretch) { - PushLine(10, 10, "line-file", 63351048); - PushLine(20, 10, "line-file", 61661044); - - StartCU(); - DefineFunction(&root_handler_, "function1", 10, 5, NULL); - // five-byte gap between functions, covered by line 63351048. - // This should not elicit a warning. - DefineFunction(&root_handler_, "function2", 20, 10, NULL); - root_handler_.Finish(); - - TestFunctionCount(2); - TestFunction(0, "function1", 10, 5); - TestLineCount(0, 1); - TestLine(0, 0, 10, 5, "line-file", 63351048); - TestFunction(1, "function2", 20, 10); - TestLineCount(1, 1); - TestLine(1, 0, 20, 10, "line-file", 61661044); -} - -// Unfortunately, neither the DWARF parser's handler interface nor the -// DIEHandler interface is capable of expressing a function that abuts -// the end of the address space: the high_pc value looks like zero. - -TEST_F(FuncLinePairing, LineAtEndOfAddressSpace) { - PushLine(0xfffffffffffffff0ULL, 16, "line-file", 63351048); - EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return()); - - StartCU(); - DefineFunction(&root_handler_, "function1", 0xfffffffffffffff0ULL, 6, NULL); - DefineFunction(&root_handler_, "function2", 0xfffffffffffffffaULL, 5, NULL); - root_handler_.Finish(); - - TestFunctionCount(2); - TestFunction(0, "function1", 0xfffffffffffffff0ULL, 6); - TestLineCount(0, 1); - TestLine(0, 0, 0xfffffffffffffff0ULL, 6, "line-file", 63351048); - TestFunction(1, "function2", 0xfffffffffffffffaULL, 5); - TestLineCount(1, 1); - TestLine(1, 0, 0xfffffffffffffffaULL, 5, "line-file", 63351048); -} - -// A function with more than one uncovered area should only be warned -// about once. -TEST_F(FuncLinePairing, WarnOnceFunc) { - PushLine(20, 1, "line-file-2", 262951329); - PushLine(11, 1, "line-file-1", 219964021); - EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return()); - - StartCU(); - DefineFunction(&root_handler_, "function", 10, 11, NULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "function", 10, 11); - TestLineCount(0, 2); - TestLine(0, 0, 11, 1, "line-file-1", 219964021); - TestLine(0, 1, 20, 1, "line-file-2", 262951329); -} - -// A line with more than one uncovered area should only be warned -// about once. -TEST_F(FuncLinePairing, WarnOnceLine) { - PushLine(10, 20, "filename1", 118581871); - EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return()); - - StartCU(); - DefineFunction(&root_handler_, "function1", 11, 1, NULL); - DefineFunction(&root_handler_, "function2", 13, 1, NULL); - root_handler_.Finish(); - - TestFunctionCount(2); - TestFunction(0, "function1", 11, 1); - TestLineCount(0, 1); - TestLine(0, 0, 11, 1, "filename1", 118581871); - TestFunction(1, "function2", 13, 1); - TestLineCount(1, 1); - TestLine(1, 0, 13, 1, "filename1", 118581871); -} - -class CXXQualifiedNames: public CUFixtureBase, - public TestWithParam { }; - -INSTANTIATE_TEST_CASE_P(VersusEnclosures, CXXQualifiedNames, - Values(dwarf2reader::DW_TAG_class_type, - dwarf2reader::DW_TAG_structure_type, - dwarf2reader::DW_TAG_union_type, - dwarf2reader::DW_TAG_namespace)); - -TEST_P(CXXQualifiedNames, TwoFunctions) { - DwarfTag tag = GetParam(); - - SetLanguage(dwarf2reader::DW_LANG_C_plus_plus); - PushLine(10, 1, "filename1", 69819327); - PushLine(20, 1, "filename2", 95115701); - - StartCU(); - DIEHandler *enclosure_handler = StartNamedDIE(&root_handler_, tag, - "Enclosure"); - EXPECT_TRUE(enclosure_handler != NULL); - DefineFunction(enclosure_handler, "func_B", 10, 1, NULL); - DefineFunction(enclosure_handler, "func_C", 20, 1, NULL); - enclosure_handler->Finish(); - delete enclosure_handler; - root_handler_.Finish(); - - TestFunctionCount(2); - TestFunction(0, "Enclosure::func_B", 10, 1); - TestFunction(1, "Enclosure::func_C", 20, 1); -} - -TEST_P(CXXQualifiedNames, FuncInEnclosureInNamespace) { - DwarfTag tag = GetParam(); - - SetLanguage(dwarf2reader::DW_LANG_C_plus_plus); - PushLine(10, 1, "line-file", 69819327); - - StartCU(); - DIEHandler *namespace_handler - = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace, - "Namespace"); - EXPECT_TRUE(namespace_handler != NULL); - DIEHandler *enclosure_handler = StartNamedDIE(namespace_handler, tag, - "Enclosure"); - EXPECT_TRUE(enclosure_handler != NULL); - DefineFunction(enclosure_handler, "function", 10, 1, NULL); - enclosure_handler->Finish(); - delete enclosure_handler; - namespace_handler->Finish(); - delete namespace_handler; - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "Namespace::Enclosure::function", 10, 1); -} - -TEST_F(CXXQualifiedNames, FunctionInClassInStructInNamespace) { - SetLanguage(dwarf2reader::DW_LANG_C_plus_plus); - PushLine(10, 1, "filename1", 69819327); - - StartCU(); - DIEHandler *namespace_handler - = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace, - "namespace_A"); - EXPECT_TRUE(namespace_handler != NULL); - DIEHandler *struct_handler - = StartNamedDIE(namespace_handler, dwarf2reader::DW_TAG_structure_type, - "struct_B"); - EXPECT_TRUE(struct_handler != NULL); - DIEHandler *class_handler - = StartNamedDIE(struct_handler, dwarf2reader::DW_TAG_class_type, - "class_C"); - DefineFunction(class_handler, "function_D", 10, 1, NULL); - class_handler->Finish(); - delete class_handler; - struct_handler->Finish(); - delete struct_handler; - namespace_handler->Finish(); - delete namespace_handler; - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "namespace_A::struct_B::class_C::function_D", 10, 1); -} - -struct LanguageAndQualifiedName { - dwarf2reader::DwarfLanguage language; - const char *name; -}; - -const LanguageAndQualifiedName LanguageAndQualifiedNameCases[] = { - { dwarf2reader::DW_LANG_none, "class_A::function_B" }, - { dwarf2reader::DW_LANG_C, "class_A::function_B" }, - { dwarf2reader::DW_LANG_C89, "class_A::function_B" }, - { dwarf2reader::DW_LANG_C99, "class_A::function_B" }, - { dwarf2reader::DW_LANG_C_plus_plus, "class_A::function_B" }, - { dwarf2reader::DW_LANG_Java, "class_A.function_B" }, - { dwarf2reader::DW_LANG_Cobol74, "class_A::function_B" }, - { dwarf2reader::DW_LANG_Mips_Assembler, NULL } -}; - -class QualifiedForLanguage - : public CUFixtureBase, - public TestWithParam { }; - -INSTANTIATE_TEST_CASE_P(LanguageAndQualifiedName, QualifiedForLanguage, - ValuesIn(LanguageAndQualifiedNameCases)); - -TEST_P(QualifiedForLanguage, MemberFunction) { - const LanguageAndQualifiedName ¶m = GetParam(); - - PushLine(10, 1, "line-file", 212966758); - SetLanguage(param.language); - - StartCU(); - DIEHandler *class_handler - = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, - "class_A"); - DefineFunction(class_handler, "function_B", 10, 1, NULL); - class_handler->Finish(); - delete class_handler; - root_handler_.Finish(); - - if (param.name) { - TestFunctionCount(1); - TestFunction(0, param.name, 10, 1); - } else { - TestFunctionCount(0); - } -} - -TEST_P(QualifiedForLanguage, MemberFunctionSignedLanguage) { - const LanguageAndQualifiedName ¶m = GetParam(); - - PushLine(10, 1, "line-file", 212966758); - SetLanguage(param.language); - SetLanguageSigned(true); - - StartCU(); - DIEHandler *class_handler - = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, - "class_A"); - DefineFunction(class_handler, "function_B", 10, 1, NULL); - class_handler->Finish(); - delete class_handler; - root_handler_.Finish(); - - if (param.name) { - TestFunctionCount(1); - TestFunction(0, param.name, 10, 1); - } else { - TestFunctionCount(0); - } -} - -class Specifications: public CUFixtureBase, public Test { }; - -TEST_F(Specifications, Function) { - PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661); - - StartCU(); - DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL, - dwarf2reader::DW_TAG_subprogram, "declaration-name", ""); - DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, - 0xcd3c51b946fb1eeeLL, "", - 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "declaration-name", - 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); -} - -TEST_F(Specifications, MangledName) { - PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661); - - StartCU(); - DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL, - dwarf2reader::DW_TAG_subprogram, "declaration-name", - "_ZN1C1fEi"); - DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, - 0xcd3c51b946fb1eeeLL, "", - 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "C::f(int)", - 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); -} - -TEST_F(Specifications, MemberFunction) { - PushLine(0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL, "line-file", 18116691); - - StartCU(); - DIEHandler *class_handler - = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "class_A"); - DeclarationDIE(class_handler, 0x7d83028c431406e8ULL, - dwarf2reader::DW_TAG_subprogram, "declaration-name", ""); - class_handler->Finish(); - delete class_handler; - DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, - 0x7d83028c431406e8ULL, "", - 0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "class_A::declaration-name", - 0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL); -} - -// This case should gather the name from both the definition and the -// declaration's parent. -TEST_F(Specifications, FunctionDeclarationParent) { - PushLine(0x463c9ddf405be227ULL, 0x6a47774af5049680ULL, "line-file", 70254922); - - StartCU(); - { - DIEHandler *class_handler - = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, - "class_A"); - ASSERT_TRUE(class_handler != NULL); - DeclarationDIE(class_handler, 0x0e0e877c8404544aULL, - dwarf2reader::DW_TAG_subprogram, "declaration-name", ""); - class_handler->Finish(); - delete class_handler; - } - - DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, - 0x0e0e877c8404544aULL, "definition-name", - 0x463c9ddf405be227ULL, 0x6a47774af5049680ULL); - - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "class_A::definition-name", - 0x463c9ddf405be227ULL, 0x6a47774af5049680ULL); -} - -// Named scopes should also gather enclosing name components from -// their declarations. -TEST_F(Specifications, NamedScopeDeclarationParent) { - PushLine(0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL, "line-file", 77392604); - - StartCU(); - { - DIEHandler *space_handler - = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace, - "space_A"); - ASSERT_TRUE(space_handler != NULL); - DeclarationDIE(space_handler, 0x419bb1d12f9a73a2ULL, - dwarf2reader::DW_TAG_class_type, "class-declaration-name", - ""); - space_handler->Finish(); - delete space_handler; - } - - { - DIEHandler *class_handler - = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, - 0x419bb1d12f9a73a2ULL, "class-definition-name"); - ASSERT_TRUE(class_handler != NULL); - DefineFunction(class_handler, "function", - 0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL, NULL); - class_handler->Finish(); - delete class_handler; - } - - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "space_A::class-definition-name::function", - 0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL); -} - -// This test recreates bug 364. -TEST_F(Specifications, InlineFunction) { - PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118); - - StartCU(); - DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL, - dwarf2reader::DW_TAG_subprogram, "inline-name", ""); - AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL, - dwarf2reader::DW_INL_inlined, 0xcd3c51b946fb1eeeLL, ""); - DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL, - 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "inline-name", - 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL); -} - -// Check name construction for a long chain containing each combination of: -// - struct, union, class, namespace -// - direct and definition -TEST_F(Specifications, LongChain) { - PushLine(0x5a0dd6bb85db754cULL, 0x3bccb213d08c7fd3ULL, "line-file", 21192926); - SetLanguage(dwarf2reader::DW_LANG_C_plus_plus); - - StartCU(); - // The structure we're building here is: - // space_A full definition - // space_B declaration - // space_B definition - // struct_C full definition - // struct_D declaration - // struct_D definition - // union_E full definition - // union_F declaration - // union_F definition - // class_G full definition - // class_H declaration - // class_H definition - // func_I declaration - // func_I definition - // - // So: - // - space_A, struct_C, union_E, and class_G don't use specifications; - // - space_B, struct_D, union_F, and class_H do. - // - func_I uses a specification. - // - // The full name for func_I is thus: - // - // space_A::space_B::struct_C::struct_D::union_E::union_F:: - // class_G::class_H::func_I - { - DIEHandler *space_A_handler - = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace, - "space_A"); - DeclarationDIE(space_A_handler, 0x2e111126496596e2ULL, - dwarf2reader::DW_TAG_namespace, "space_B", ""); - space_A_handler->Finish(); - delete space_A_handler; - } - - { - DIEHandler *space_B_handler - = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace, - 0x2e111126496596e2ULL); - DIEHandler *struct_C_handler - = StartNamedDIE(space_B_handler, dwarf2reader::DW_TAG_structure_type, - "struct_C"); - DeclarationDIE(struct_C_handler, 0x20cd423bf2a25a4cULL, - dwarf2reader::DW_TAG_structure_type, "struct_D", ""); - struct_C_handler->Finish(); - delete struct_C_handler; - space_B_handler->Finish(); - delete space_B_handler; - } - - { - DIEHandler *struct_D_handler - = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_structure_type, - 0x20cd423bf2a25a4cULL); - DIEHandler *union_E_handler - = StartNamedDIE(struct_D_handler, dwarf2reader::DW_TAG_union_type, - "union_E"); - DeclarationDIE(union_E_handler, 0xe25c84805aa58c32ULL, - dwarf2reader::DW_TAG_union_type, "union_F", ""); - union_E_handler->Finish(); - delete union_E_handler; - struct_D_handler->Finish(); - delete struct_D_handler; - } - - { - DIEHandler *union_F_handler - = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_union_type, - 0xe25c84805aa58c32ULL); - DIEHandler *class_G_handler - = StartNamedDIE(union_F_handler, dwarf2reader::DW_TAG_class_type, - "class_G"); - DeclarationDIE(class_G_handler, 0xb70d960dcc173b6eULL, - dwarf2reader::DW_TAG_class_type, "class_H", ""); - class_G_handler->Finish(); - delete class_G_handler; - union_F_handler->Finish(); - delete union_F_handler; - } - - { - DIEHandler *class_H_handler - = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, - 0xb70d960dcc173b6eULL); - DeclarationDIE(class_H_handler, 0x27ff829e3bf69f37ULL, - dwarf2reader::DW_TAG_subprogram, "func_I", ""); - class_H_handler->Finish(); - delete class_H_handler; - } - - DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, - 0x27ff829e3bf69f37ULL, "", - 0x5a0dd6bb85db754cULL, 0x3bccb213d08c7fd3ULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "space_A::space_B::struct_C::struct_D::union_E::union_F" - "::class_G::class_H::func_I", - 0x5a0dd6bb85db754cULL, 0x3bccb213d08c7fd3ULL); -} - -TEST_F(Specifications, InterCU) { - Module m("module-name", "module-os", "module-arch", "module-id"); - DwarfCUToModule::FileContext fc("dwarf-filename", &m, true); - EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return()); - MockLineToModuleHandler lr; - EXPECT_CALL(lr, ReadProgram(_,_,_,_)).Times(0); - - // Kludge: satisfy reporter_'s expectation. - reporter_.SetCUName("compilation-unit-name"); - - // First CU. Declares class_A. - { - DwarfCUToModule root1_handler(&fc, &lr, &reporter_); - ASSERT_TRUE(root1_handler.StartCompilationUnit(0, 1, 2, 3, 3)); - ASSERT_TRUE(root1_handler.StartRootDIE(1, - dwarf2reader::DW_TAG_compile_unit)); - ProcessStrangeAttributes(&root1_handler); - ASSERT_TRUE(root1_handler.EndAttributes()); - DeclarationDIE(&root1_handler, 0xb8fbfdd5f0b26fceULL, - dwarf2reader::DW_TAG_class_type, "class_A", ""); - root1_handler.Finish(); - } - - // Second CU. Defines class_A, declares member_func_B. - { - DwarfCUToModule root2_handler(&fc, &lr, &reporter_); - ASSERT_TRUE(root2_handler.StartCompilationUnit(0, 1, 2, 3, 3)); - ASSERT_TRUE(root2_handler.StartRootDIE(1, - dwarf2reader::DW_TAG_compile_unit)); - ASSERT_TRUE(root2_handler.EndAttributes()); - DIEHandler *class_A_handler - = StartSpecifiedDIE(&root2_handler, dwarf2reader::DW_TAG_class_type, - 0xb8fbfdd5f0b26fceULL); - DeclarationDIE(class_A_handler, 0xb01fef8b380bd1a2ULL, - dwarf2reader::DW_TAG_subprogram, "member_func_B", ""); - class_A_handler->Finish(); - delete class_A_handler; - root2_handler.Finish(); - } - - // Third CU. Defines member_func_B. - { - DwarfCUToModule root3_handler(&fc, &lr, &reporter_); - ASSERT_TRUE(root3_handler.StartCompilationUnit(0, 1, 2, 3, 3)); - ASSERT_TRUE(root3_handler.StartRootDIE(1, - dwarf2reader::DW_TAG_compile_unit)); - ASSERT_TRUE(root3_handler.EndAttributes()); - DefinitionDIE(&root3_handler, dwarf2reader::DW_TAG_subprogram, - 0xb01fef8b380bd1a2ULL, "", - 0x2618f00a1a711e53ULL, 0x4fd94b76d7c2caf5ULL); - root3_handler.Finish(); - } - - vector functions; - m.GetFunctions(&functions, functions.end()); - EXPECT_EQ(1U, functions.size()); - EXPECT_STREQ("class_A::member_func_B", functions[0]->name.c_str()); -} - -TEST_F(Specifications, UnhandledInterCU) { - Module m("module-name", "module-os", "module-arch", "module-id"); - DwarfCUToModule::FileContext fc("dwarf-filename", &m, false); - EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return()); - MockLineToModuleHandler lr; - EXPECT_CALL(lr, ReadProgram(_,_,_,_)).Times(0); - - // Kludge: satisfy reporter_'s expectation. - reporter_.SetCUName("compilation-unit-name"); - - // First CU. Declares class_A. - { - DwarfCUToModule root1_handler(&fc, &lr, &reporter_); - ASSERT_TRUE(root1_handler.StartCompilationUnit(0, 1, 2, 3, 3)); - ASSERT_TRUE(root1_handler.StartRootDIE(1, - dwarf2reader::DW_TAG_compile_unit)); - ProcessStrangeAttributes(&root1_handler); - ASSERT_TRUE(root1_handler.EndAttributes()); - DeclarationDIE(&root1_handler, 0xb8fbfdd5f0b26fceULL, - dwarf2reader::DW_TAG_class_type, "class_A", ""); - root1_handler.Finish(); - } - - // Second CU. Defines class_A, declares member_func_B. - { - DwarfCUToModule root2_handler(&fc, &lr, &reporter_); - ASSERT_TRUE(root2_handler.StartCompilationUnit(0, 1, 2, 3, 3)); - ASSERT_TRUE(root2_handler.StartRootDIE(1, - dwarf2reader::DW_TAG_compile_unit)); - ASSERT_TRUE(root2_handler.EndAttributes()); - EXPECT_CALL(reporter_, UnhandledInterCUReference(_, _)).Times(1); - DIEHandler *class_A_handler - = StartSpecifiedDIE(&root2_handler, dwarf2reader::DW_TAG_class_type, - 0xb8fbfdd5f0b26fceULL); - DeclarationDIE(class_A_handler, 0xb01fef8b380bd1a2ULL, - dwarf2reader::DW_TAG_subprogram, "member_func_B", ""); - class_A_handler->Finish(); - delete class_A_handler; - root2_handler.Finish(); - } - - // Third CU. Defines member_func_B. - { - DwarfCUToModule root3_handler(&fc, &lr, &reporter_); - ASSERT_TRUE(root3_handler.StartCompilationUnit(0, 1, 2, 3, 3)); - ASSERT_TRUE(root3_handler.StartRootDIE(1, - dwarf2reader::DW_TAG_compile_unit)); - ASSERT_TRUE(root3_handler.EndAttributes()); - EXPECT_CALL(reporter_, UnhandledInterCUReference(_, _)).Times(1); - EXPECT_CALL(reporter_, UnnamedFunction(_)).Times(1); - DefinitionDIE(&root3_handler, dwarf2reader::DW_TAG_subprogram, - 0xb01fef8b380bd1a2ULL, "", - 0x2618f00a1a711e53ULL, 0x4fd94b76d7c2caf5ULL); - root3_handler.Finish(); - } -} - -TEST_F(Specifications, BadOffset) { - PushLine(0xa0277efd7ce83771ULL, 0x149554a184c730c1ULL, "line-file", 56636272); - EXPECT_CALL(reporter_, UnknownSpecification(_, 0x2be953efa6f9a996ULL)) - .WillOnce(Return()); - - StartCU(); - DeclarationDIE(&root_handler_, 0xefd7f7752c27b7e4ULL, - dwarf2reader::DW_TAG_subprogram, "", ""); - DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, - 0x2be953efa6f9a996ULL, "function", - 0xa0277efd7ce83771ULL, 0x149554a184c730c1ULL); - root_handler_.Finish(); -} - -TEST_F(Specifications, FunctionDefinitionHasOwnName) { - PushLine(0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL, "line-file", 56792403); - - StartCU(); - DeclarationDIE(&root_handler_, 0xc34ff4786cae78bdULL, - dwarf2reader::DW_TAG_subprogram, "declaration-name", ""); - DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, - 0xc34ff4786cae78bdULL, "definition-name", - 0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL); - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "definition-name", - 0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL); -} - -TEST_F(Specifications, ClassDefinitionHasOwnName) { - PushLine(0x1d0f5e0f6ce309bdULL, 0x654e1852ec3599e7ULL, "line-file", 57119241); - - StartCU(); - DeclarationDIE(&root_handler_, 0xd0fe467ec2f1a58cULL, - dwarf2reader::DW_TAG_class_type, "class-declaration-name", ""); - - dwarf2reader::DIEHandler *class_definition - = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, - 0xd0fe467ec2f1a58cULL, "class-definition-name"); - ASSERT_TRUE(class_definition); - DeclarationDIE(class_definition, 0x6d028229c15623dbULL, - dwarf2reader::DW_TAG_subprogram, - "function-declaration-name", ""); - class_definition->Finish(); - delete class_definition; - - DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, - 0x6d028229c15623dbULL, "function-definition-name", - 0x1d0f5e0f6ce309bdULL, 0x654e1852ec3599e7ULL); - - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "class-definition-name::function-definition-name", - 0x1d0f5e0f6ce309bdULL, 0x654e1852ec3599e7ULL); -} - -// DIEs that cite a specification should prefer the specification's -// parents over their own when choosing qualified names. In this test, -// we take the name from our definition but the enclosing scope name -// from our declaration. I don't see why they'd ever be different, but -// we want to verify what DwarfCUToModule is looking at. -TEST_F(Specifications, PreferSpecificationParents) { - PushLine(0xbbd9d54dce3b95b7ULL, 0x39188b7b52b0899fULL, "line-file", 79488694); - - StartCU(); - { - dwarf2reader::DIEHandler *declaration_class_handler = - StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, - "declaration-class"); - DeclarationDIE(declaration_class_handler, 0x9ddb35517455ef7aULL, - dwarf2reader::DW_TAG_subprogram, "function-declaration", - ""); - declaration_class_handler->Finish(); - delete declaration_class_handler; - } - { - dwarf2reader::DIEHandler *definition_class_handler - = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, - "definition-class"); - DefinitionDIE(definition_class_handler, dwarf2reader::DW_TAG_subprogram, - 0x9ddb35517455ef7aULL, "function-definition", - 0xbbd9d54dce3b95b7ULL, 0x39188b7b52b0899fULL); - definition_class_handler->Finish(); - delete definition_class_handler; - } - root_handler_.Finish(); - - TestFunctionCount(1); - TestFunction(0, "declaration-class::function-definition", - 0xbbd9d54dce3b95b7ULL, 0x39188b7b52b0899fULL); -} - -class CUErrors: public CUFixtureBase, public Test { }; - -TEST_F(CUErrors, BadStmtList) { - EXPECT_CALL(reporter_, BadLineInfoOffset(dummy_line_size_ + 10)).Times(1); - - ASSERT_TRUE(root_handler_ - .StartCompilationUnit(0xc591d5b037543d7cULL, 0x11, 0xcd, - 0x2d7d19546cf6590cULL, 3)); - ASSERT_TRUE(root_handler_.StartRootDIE(0xae789dc102cfca54ULL, - dwarf2reader::DW_TAG_compile_unit)); - root_handler_.ProcessAttributeString(dwarf2reader::DW_AT_name, - dwarf2reader::DW_FORM_strp, - "compilation-unit-name"); - root_handler_.ProcessAttributeUnsigned(dwarf2reader::DW_AT_stmt_list, - dwarf2reader::DW_FORM_ref4, - dummy_line_size_ + 10); - root_handler_.EndAttributes(); - root_handler_.Finish(); -} - -TEST_F(CUErrors, NoLineSection) { - EXPECT_CALL(reporter_, MissingSection(".debug_line")).Times(1); - PushLine(0x88507fb678052611ULL, 0x42c8e9de6bbaa0faULL, "line-file", 64472290); - // Delete the entry for .debug_line added by the fixture class's constructor. - file_context_.ClearSectionMapForTest(); - - StartCU(); - root_handler_.Finish(); -} - -TEST_F(CUErrors, BadDwarfVersion1) { - // Kludge: satisfy reporter_'s expectation. - reporter_.SetCUName("compilation-unit-name"); - - ASSERT_FALSE(root_handler_ - .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90, - 0xc9de224ccb99ac3eULL, 1)); -} - -TEST_F(CUErrors, GoodDwarfVersion2) { - // Kludge: satisfy reporter_'s expectation. - reporter_.SetCUName("compilation-unit-name"); - - ASSERT_TRUE(root_handler_ - .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90, - 0xc9de224ccb99ac3eULL, 2)); -} - -TEST_F(CUErrors, GoodDwarfVersion3) { - // Kludge: satisfy reporter_'s expectation. - reporter_.SetCUName("compilation-unit-name"); - - ASSERT_TRUE(root_handler_ - .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90, - 0xc9de224ccb99ac3eULL, 3)); -} - -TEST_F(CUErrors, BadCURootDIETag) { - // Kludge: satisfy reporter_'s expectation. - reporter_.SetCUName("compilation-unit-name"); - - ASSERT_TRUE(root_handler_ - .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90, - 0xc9de224ccb99ac3eULL, 3)); - - ASSERT_FALSE(root_handler_.StartRootDIE(0x02e56bfbda9e7337ULL, - dwarf2reader::DW_TAG_subprogram)); -} - -// Tests for DwarfCUToModule::Reporter. These just produce (or fail to -// produce) output, so their results need to be checked by hand. -struct Reporter: public Test { - Reporter() - : reporter("filename", 0x123456789abcdef0ULL) { - reporter.SetCUName("compilation-unit-name"); - - function.name = "function name"; - function.address = 0x19c45c30770c1eb0ULL; - function.size = 0x89808a5bdfa0a6a3ULL; - function.parameter_size = 0x6a329f18683dcd51ULL; - - file.name = "source file name"; - - line.address = 0x3606ac6267aebeccULL; - line.size = 0x5de482229f32556aULL; - line.file = &file; - line.number = 93400201; - } - - DwarfCUToModule::WarningReporter reporter; - Module::Function function; - Module::File file; - Module::Line line; -}; - -TEST_F(Reporter, UnknownSpecification) { - reporter.UnknownSpecification(0x123456789abcdef1ULL, 0x323456789abcdef2ULL); -} - -TEST_F(Reporter, UnknownAbstractOrigin) { - reporter.UnknownAbstractOrigin(0x123456789abcdef1ULL, 0x323456789abcdef2ULL); -} - -TEST_F(Reporter, MissingSection) { - reporter.MissingSection("section name"); -} - -TEST_F(Reporter, BadLineInfoOffset) { - reporter.BadLineInfoOffset(0x123456789abcdef1ULL); -} - -TEST_F(Reporter, UncoveredFunctionDisabled) { - reporter.UncoveredFunction(function); - EXPECT_FALSE(reporter.uncovered_warnings_enabled()); -} - -TEST_F(Reporter, UncoveredFunctionEnabled) { - reporter.set_uncovered_warnings_enabled(true); - reporter.UncoveredFunction(function); - EXPECT_TRUE(reporter.uncovered_warnings_enabled()); -} - -TEST_F(Reporter, UncoveredLineDisabled) { - reporter.UncoveredLine(line); - EXPECT_FALSE(reporter.uncovered_warnings_enabled()); -} - -TEST_F(Reporter, UncoveredLineEnabled) { - reporter.set_uncovered_warnings_enabled(true); - reporter.UncoveredLine(line); - EXPECT_TRUE(reporter.uncovered_warnings_enabled()); -} - -TEST_F(Reporter, UnnamedFunction) { - reporter.UnnamedFunction(0x90c0baff9dedb2d9ULL); -} - -// Would be nice to also test: -// - overlapping lines, functions diff --git a/breakpad/common/dwarf_line_to_module.cc b/breakpad/common/dwarf_line_to_module.cc deleted file mode 100644 index 258b0b603..000000000 --- a/breakpad/common/dwarf_line_to_module.cc +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// dwarf_line_to_module.cc: Implementation of DwarfLineToModule class. -// See dwarf_line_to_module.h for details. - -#include - -#include - -#include "common/dwarf_line_to_module.h" -#include "common/using_std_string.h" - -// Trying to support Windows paths in a reasonable way adds a lot of -// variations to test; it would be better to just put off dealing with -// it until we actually have to deal with DWARF on Windows. - -// Return true if PATH is an absolute path, false if it is relative. -static bool PathIsAbsolute(const string &path) { - return (path.size() >= 1 && path[0] == '/'); -} - -static bool HasTrailingSlash(const string &path) { - return (path.size() >= 1 && path[path.size() - 1] == '/'); -} - -// If PATH is an absolute path, return PATH. If PATH is a relative path, -// treat it as relative to BASE and return the combined path. -static string ExpandPath(const string &path, - const string &base) { - if (PathIsAbsolute(path) || base.empty()) - return path; - return base + (HasTrailingSlash(base) ? "" : "/") + path; -} - -namespace google_breakpad { - -void DwarfLineToModule::DefineDir(const string &name, uint32 dir_num) { - // Directory number zero is reserved to mean the compilation - // directory. Silently ignore attempts to redefine it. - if (dir_num != 0) - directories_[dir_num] = ExpandPath(name, compilation_dir_); -} - -void DwarfLineToModule::DefineFile(const string &name, int32 file_num, - uint32 dir_num, uint64 mod_time, - uint64 length) { - if (file_num == -1) - file_num = ++highest_file_number_; - else if (file_num > highest_file_number_) - highest_file_number_ = file_num; - - string dir_name; - if (dir_num == 0) { - // Directory number zero is the compilation directory, and is stored as - // an attribute on the compilation unit, rather than in the program table. - dir_name = compilation_dir_; - } else { - DirectoryTable::const_iterator directory_it = directories_.find(dir_num); - if (directory_it != directories_.end()) { - dir_name = directory_it->second; - } else { - if (!warned_bad_directory_number_) { - fprintf(stderr, "warning: DWARF line number data refers to undefined" - " directory numbers\n"); - warned_bad_directory_number_ = true; - } - } - } - - string full_name = ExpandPath(name, dir_name); - - // Find a Module::File object of the given name, and add it to the - // file table. - files_[file_num] = module_->FindFile(full_name); -} - -void DwarfLineToModule::AddLine(uint64 address, uint64 length, - uint32 file_num, uint32 line_num, - uint32 column_num) { - if (length == 0) - return; - - // Clip lines not to extend beyond the end of the address space. - if (address + length < address) - length = -address; - - // Should we omit this line? (See the comments for omitted_line_end_.) - if (address == 0 || address == omitted_line_end_) { - omitted_line_end_ = address + length; - return; - } else { - omitted_line_end_ = 0; - } - - // Find the source file being referred to. - Module::File *file = files_[file_num]; - if (!file) { - if (!warned_bad_file_number_) { - fprintf(stderr, "warning: DWARF line number data refers to " - "undefined file numbers\n"); - warned_bad_file_number_ = true; - } - return; - } - Module::Line line; - line.address = address; - // We set the size when we get the next line or the EndSequence call. - line.size = length; - line.file = file; - line.number = line_num; - lines_->push_back(line); -} - -} // namespace google_breakpad diff --git a/breakpad/common/dwarf_line_to_module.h b/breakpad/common/dwarf_line_to_module.h deleted file mode 100644 index 1fdd4cb71..000000000 --- a/breakpad/common/dwarf_line_to_module.h +++ /dev/null @@ -1,188 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// The DwarfLineToModule class accepts line number information from a -// DWARF parser and adds it to a google_breakpad::Module. The Module -// can write that data out as a Breakpad symbol file. - -#ifndef COMMON_LINUX_DWARF_LINE_TO_MODULE_H -#define COMMON_LINUX_DWARF_LINE_TO_MODULE_H - -#include - -#include "common/module.h" -#include "common/dwarf/dwarf2reader.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -// A class for producing a vector of google_breakpad::Module::Line -// instances from parsed DWARF line number data. -// -// An instance of this class can be provided as a handler to a -// dwarf2reader::LineInfo DWARF line number information parser. The -// handler accepts source location information from the parser and -// uses it to produce a vector of google_breakpad::Module::Line -// objects, referring to google_breakpad::Module::File objects added -// to a particular google_breakpad::Module. -// -// GNU toolchain omitted sections support: -// ====================================== -// -// Given the right options, the GNU toolchain will omit unreferenced -// functions from the final executable. Unfortunately, when it does so, it -// does not remove the associated portions of the DWARF line number -// program; instead, it gives the DW_LNE_set_address instructions referring -// to the now-deleted code addresses of zero. Given this input, the DWARF -// line parser will call AddLine with a series of lines starting at address -// zero. For example, here is the output from 'readelf -wl' for a program -// with four functions, the first three of which have been omitted: -// -// Line Number Statements: -// Extended opcode 2: set Address to 0x0 -// Advance Line by 14 to 15 -// Copy -// Special opcode 48: advance Address by 3 to 0x3 and Line by 1 to 16 -// Special opcode 119: advance Address by 8 to 0xb and Line by 2 to 18 -// Advance PC by 2 to 0xd -// Extended opcode 1: End of Sequence -// -// Extended opcode 2: set Address to 0x0 -// Advance Line by 14 to 15 -// Copy -// Special opcode 48: advance Address by 3 to 0x3 and Line by 1 to 16 -// Special opcode 119: advance Address by 8 to 0xb and Line by 2 to 18 -// Advance PC by 2 to 0xd -// Extended opcode 1: End of Sequence -// -// Extended opcode 2: set Address to 0x0 -// Advance Line by 19 to 20 -// Copy -// Special opcode 48: advance Address by 3 to 0x3 and Line by 1 to 21 -// Special opcode 76: advance Address by 5 to 0x8 and Line by 1 to 22 -// Advance PC by 2 to 0xa -// Extended opcode 1: End of Sequence -// -// Extended opcode 2: set Address to 0x80483a4 -// Advance Line by 23 to 24 -// Copy -// Special opcode 202: advance Address by 14 to 0x80483b2 and Line by 1 to 25 -// Special opcode 76: advance Address by 5 to 0x80483b7 and Line by 1 to 26 -// Advance PC by 6 to 0x80483bd -// Extended opcode 1: End of Sequence -// -// Instead of collecting runs of lines describing code that is not there, -// we try to recognize and drop them. Since the linker doesn't explicitly -// distinguish references to dropped sections from genuine references to -// code at address zero, we must use a heuristic. We have chosen: -// -// - If a line starts at address zero, omit it. (On the platforms -// breakpad targets, it is extremely unlikely that there will be code -// at address zero.) -// -// - If a line starts immediately after an omitted line, omit it too. -class DwarfLineToModule: public dwarf2reader::LineInfoHandler { - public: - // As the DWARF line info parser passes us line records, add source - // files to MODULE, and add all lines to the end of LINES. LINES - // need not be empty. If the parser hands us a zero-length line, we - // omit it. If the parser hands us a line that extends beyond the - // end of the address space, we clip it. It's up to our client to - // sort out which lines belong to which functions; we don't add them - // to any particular function in MODULE ourselves. - DwarfLineToModule(Module *module, const string& compilation_dir, - vector *lines) - : module_(module), - compilation_dir_(compilation_dir), - lines_(lines), - highest_file_number_(-1), - omitted_line_end_(0), - warned_bad_file_number_(false), - warned_bad_directory_number_(false) { } - - ~DwarfLineToModule() { } - - void DefineDir(const string &name, uint32 dir_num); - void DefineFile(const string &name, int32 file_num, - uint32 dir_num, uint64 mod_time, - uint64 length); - void AddLine(uint64 address, uint64 length, - uint32 file_num, uint32 line_num, uint32 column_num); - - private: - - typedef std::map DirectoryTable; - typedef std::map FileTable; - - // The module we're contributing debugging info to. Owned by our - // client. - Module *module_; - - // The compilation directory for the current compilation unit whose - // lines are being accumulated. - string compilation_dir_; - - // The vector of lines we're accumulating. Owned by our client. - // - // In a Module, as in a breakpad symbol file, lines belong to - // specific functions, but DWARF simply assigns lines to addresses; - // one must infer the line/function relationship using the - // functions' beginning and ending addresses. So we can't add these - // to the appropriate function from module_ until we've read the - // function info as well. Instead, we accumulate lines here, and let - // whoever constructed this sort it all out. - vector *lines_; - - // A table mapping directory numbers to paths. - DirectoryTable directories_; - - // A table mapping file numbers to Module::File pointers. - FileTable files_; - - // The highest file number we've seen so far, or -1 if we've seen - // none. Used for dynamically defined file numbers. - int32 highest_file_number_; - - // This is the ending address of the last line we omitted, or zero if we - // didn't omit the previous line. It is zero before we have received any - // AddLine calls. - uint64 omitted_line_end_; - - // True if we've warned about: - bool warned_bad_file_number_; // bad file numbers - bool warned_bad_directory_number_; // bad directory numbers -}; - -} // namespace google_breakpad - -#endif // COMMON_LINUX_DWARF_LINE_TO_MODULE_H diff --git a/breakpad/common/dwarf_line_to_module_unittest.cc b/breakpad/common/dwarf_line_to_module_unittest.cc deleted file mode 100644 index 7c0fcfd35..000000000 --- a/breakpad/common/dwarf_line_to_module_unittest.cc +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// dwarf_line_to_module.cc: Unit tests for google_breakpad::DwarfLineToModule. - -#include - -#include "breakpad_googletest_includes.h" -#include "common/dwarf_line_to_module.h" - -using std::vector; - -using google_breakpad::DwarfLineToModule; -using google_breakpad::Module; -using google_breakpad::Module; - -TEST(SimpleModule, One) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineFile("file1", 0x30bf0f27, 0, 0, 0); - h.AddLine(0x6fd126fbf74f2680LL, 0x63c9a14cf556712bLL, 0x30bf0f27, - 0x4c090cbf, 0x1cf9fe0d); - - vector files; - m.GetFiles(&files); - EXPECT_EQ(1U, files.size()); - EXPECT_STREQ("/file1", files[0]->name.c_str()); - - EXPECT_EQ(1U, lines.size()); - EXPECT_EQ(0x6fd126fbf74f2680ULL, lines[0].address); - EXPECT_EQ(0x63c9a14cf556712bULL, lines[0].size); - EXPECT_TRUE(lines[0].file == files[0]); - EXPECT_EQ(0x4c090cbf, lines[0].number); -} - -TEST(SimpleModule, Many) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineDir("directory1", 0x838299ab); - h.DefineDir("directory2", 0xf85de023); - h.DefineFile("file1", 0x2b80377a, 0x838299ab, 0, 0); - h.DefineFile("file1", 0x63beb4a4, 0xf85de023, 0, 0); - h.DefineFile("file2", 0x1d161d56, 0x838299ab, 0, 0); - h.DefineFile("file2", 0x1e7a667c, 0xf85de023, 0, 0); - h.AddLine(0x69900c5d553b7274ULL, 0x90fded183f0d0d3cULL, 0x2b80377a, - 0x15b0f0a9U, 0x3ff5abd6U); - h.AddLine(0x45811219a39b7101ULL, 0x25a5e6a924afc41fULL, 0x63beb4a4, - 0x4d259ce9U, 0x41c5ee32U); - h.AddLine(0xfa90514c1dc9704bULL, 0x0063efeabc02f313ULL, 0x1d161d56, - 0x1ee9fa4fU, 0xbf70e46aU); - h.AddLine(0x556b55fb6a647b10ULL, 0x3f3089ca2bfd80f5ULL, 0x1e7a667c, - 0x77fc280eU, 0x2c4a728cU); - h.DefineFile("file3", -1, 0, 0, 0); - h.AddLine(0xe2d72a37f8d9403aULL, 0x034dfab5b0d4d236ULL, 0x63beb4a5, - 0x75047044U, 0xb6a0016cU); - - vector files; - m.GetFiles(&files); - ASSERT_EQ(5U, files.size()); - EXPECT_STREQ("/directory1/file1", files[0]->name.c_str()); - EXPECT_STREQ("/directory1/file2", files[1]->name.c_str()); - EXPECT_STREQ("/directory2/file1", files[2]->name.c_str()); - EXPECT_STREQ("/directory2/file2", files[3]->name.c_str()); - EXPECT_STREQ("/file3", files[4]->name.c_str()); - - ASSERT_EQ(5U, lines.size()); - - EXPECT_EQ(0x69900c5d553b7274ULL, lines[0].address); - EXPECT_EQ(0x90fded183f0d0d3cULL, lines[0].size); - EXPECT_TRUE(lines[0].file == files[0]); - EXPECT_EQ(0x15b0f0a9, lines[0].number); - - EXPECT_EQ(0x45811219a39b7101ULL, lines[1].address); - EXPECT_EQ(0x25a5e6a924afc41fULL, lines[1].size); - EXPECT_TRUE(lines[1].file == files[2]); - EXPECT_EQ(0x4d259ce9, lines[1].number); - - EXPECT_EQ(0xfa90514c1dc9704bULL, lines[2].address); - EXPECT_EQ(0x0063efeabc02f313ULL, lines[2].size); - EXPECT_TRUE(lines[2].file == files[1]); - EXPECT_EQ(0x1ee9fa4f, lines[2].number); - - EXPECT_EQ(0x556b55fb6a647b10ULL, lines[3].address); - EXPECT_EQ(0x3f3089ca2bfd80f5ULL, lines[3].size); - EXPECT_TRUE(lines[3].file == files[3]); - EXPECT_EQ(0x77fc280e, lines[3].number); - - EXPECT_EQ(0xe2d72a37f8d9403aULL, lines[4].address); - EXPECT_EQ(0x034dfab5b0d4d236ULL, lines[4].size); - EXPECT_TRUE(lines[4].file == files[4]); - EXPECT_EQ(0x75047044, lines[4].number); -} - -TEST(Filenames, Absolute) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineDir("directory1", 1); - h.DefineFile("/absolute", 1, 1, 0, 0); - - h.AddLine(1, 1, 1, 0, 0); - - vector files; - m.GetFiles(&files); - ASSERT_EQ(1U, files.size()); - EXPECT_STREQ("/absolute", files[0]->name.c_str()); - ASSERT_EQ(1U, lines.size()); - EXPECT_TRUE(lines[0].file == files[0]); -} - -TEST(Filenames, Relative) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineDir("directory1", 1); - h.DefineFile("relative", 1, 1, 0, 0); - - h.AddLine(1, 1, 1, 0, 0); - - vector files; - m.GetFiles(&files); - ASSERT_EQ(1U, files.size()); - EXPECT_STREQ("/directory1/relative", files[0]->name.c_str()); - ASSERT_EQ(1U, lines.size()); - EXPECT_TRUE(lines[0].file == files[0]); -} - -TEST(Filenames, StrangeFile) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineDir("directory1", 1); - h.DefineFile("", 1, 1, 0, 0); - h.AddLine(1, 1, 1, 0, 0); - - ASSERT_EQ(1U, lines.size()); - EXPECT_STREQ("/directory1/", lines[0].file->name.c_str()); -} - -TEST(Filenames, StrangeDirectory) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineDir("", 1); - h.DefineFile("file1", 1, 1, 0, 0); - h.AddLine(1, 1, 1, 0, 0); - - ASSERT_EQ(1U, lines.size()); - EXPECT_STREQ("/file1", lines[0].file->name.c_str()); -} - -TEST(Filenames, StrangeDirectoryAndFile) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineDir("", 1); - h.DefineFile("", 1, 1, 0, 0); - h.AddLine(1, 1, 1, 0, 0); - - ASSERT_EQ(1U, lines.size()); - EXPECT_STREQ("/", lines[0].file->name.c_str()); -} - -// We should use the compilation directory when encountering a file for -// directory number zero. -TEST(Filenames, DirectoryZeroFileIsRelativeToCompilationDir) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "src/build", &lines); - - h.DefineDir("Dir", 1); - h.DefineFile("File", 1, 0, 0, 0); - - h.AddLine(1, 1, 1, 0, 0); - - ASSERT_EQ(1U, lines.size()); - EXPECT_STREQ("src/build/File", lines[0].file->name.c_str()); -} - -// We should treat non-absolute directories as relative to the compilation -// directory. -TEST(Filenames, IncludeDirectoryRelativeToDirectoryZero) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "src/build", &lines); - - h.DefineDir("Dir", 1); - h.DefineFile("File", 1, 1, 0, 0); - - h.AddLine(1, 1, 1, 0, 0); - - ASSERT_EQ(1U, lines.size()); - EXPECT_STREQ("src/build/Dir/File", lines[0].file->name.c_str()); -} - -// We should treat absolute directories as absolute, and not relative to -// the compilation dir. -TEST(Filenames, IncludeDirectoryAbsolute) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "src/build", &lines); - - h.DefineDir("/Dir", 1); - h.DefineFile("File", 1, 1, 0, 0); - - h.AddLine(1, 1, 1, 0, 0); - - ASSERT_EQ(1U, lines.size()); - EXPECT_STREQ("/Dir/File", lines[0].file->name.c_str()); -} - -// We should silently ignore attempts to define directory number zero, -// since that is always the compilation directory. -TEST(ModuleErrors, DirectoryZero) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineDir("directory0", 0); // should be ignored - h.DefineFile("relative", 1, 0, 0, 0); - - h.AddLine(1, 1, 1, 0, 0); - - ASSERT_EQ(1U, lines.size()); - EXPECT_STREQ("/relative", lines[0].file->name.c_str()); -} - -// We should refuse to add lines with bogus file numbers. We should -// produce only one warning, however. -TEST(ModuleErrors, BadFileNumber) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineFile("relative", 1, 0, 0, 0); - h.AddLine(1, 1, 2, 0, 0); // bad file number - h.AddLine(2, 1, 2, 0, 0); // bad file number (no duplicate warning) - - EXPECT_EQ(0U, lines.size()); -} - -// We should treat files with bogus directory numbers as relative to -// the compilation unit. -TEST(ModuleErrors, BadDirectoryNumber) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineDir("directory1", 1); - h.DefineFile("baddirnumber1", 1, 2, 0, 0); // bad directory number - h.DefineFile("baddirnumber2", 2, 2, 0, 0); // bad dir number (no warning) - h.AddLine(1, 1, 1, 0, 0); - - ASSERT_EQ(1U, lines.size()); - EXPECT_STREQ("baddirnumber1", lines[0].file->name.c_str()); -} - -// We promise not to report empty lines. -TEST(ModuleErrors, EmptyLine) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineFile("filename1", 1, 0, 0, 0); - h.AddLine(1, 0, 1, 0, 0); - - ASSERT_EQ(0U, lines.size()); -} - -// We are supposed to clip lines that extend beyond the end of the -// address space. -TEST(ModuleErrors, BigLine) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineFile("filename1", 1, 0, 0, 0); - h.AddLine(0xffffffffffffffffULL, 2, 1, 0, 0); - - ASSERT_EQ(1U, lines.size()); - EXPECT_EQ(1U, lines[0].size); -} - -// The 'Omitted' tests verify that we correctly omit line information -// for code in sections that the linker has dropped. See "GNU -// toolchain omitted sections support" at the top of the -// DwarfLineToModule class. - -TEST(Omitted, DroppedThenGood) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineFile("filename1", 1, 0, 0, 0); - h.AddLine(0, 10, 1, 83816211, 0); // should be omitted - h.AddLine(20, 10, 1, 13059195, 0); // should be recorded - - ASSERT_EQ(1U, lines.size()); - EXPECT_EQ(13059195, lines[0].number); -} - -TEST(Omitted, GoodThenDropped) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineFile("filename1", 1, 0, 0, 0); - h.AddLine(0x9dd6a372, 10, 1, 41454594, 0); // should be recorded - h.AddLine(0, 10, 1, 44793413, 0); // should be omitted - - ASSERT_EQ(1U, lines.size()); - EXPECT_EQ(41454594, lines[0].number); -} - -TEST(Omitted, Mix1) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineFile("filename1", 1, 0, 0, 0); - h.AddLine(0x679ed72f, 10, 1, 58932642, 0); // should be recorded - h.AddLine(0xdfb5a72d, 10, 1, 39847385, 0); // should be recorded - h.AddLine(0, 0x78, 1, 23053829, 0); // should be omitted - h.AddLine(0x78, 0x6a, 1, 65317783, 0); // should be omitted - h.AddLine(0x78 + 0x6a, 0x2a, 1, 77601423, 0); // should be omitted - h.AddLine(0x9fe0cea5, 10, 1, 91806582, 0); // should be recorded - h.AddLine(0x7e41a109, 10, 1, 56169221, 0); // should be recorded - - ASSERT_EQ(4U, lines.size()); - EXPECT_EQ(58932642, lines[0].number); - EXPECT_EQ(39847385, lines[1].number); - EXPECT_EQ(91806582, lines[2].number); - EXPECT_EQ(56169221, lines[3].number); -} - -TEST(Omitted, Mix2) { - Module m("name", "os", "architecture", "id"); - vector lines; - DwarfLineToModule h(&m, "/", &lines); - - h.DefineFile("filename1", 1, 0, 0, 0); - h.AddLine(0, 0xf2, 1, 58802211, 0); // should be omitted - h.AddLine(0xf2, 0xb9, 1, 78958222, 0); // should be omitted - h.AddLine(0xf2 + 0xb9, 0xf7, 1, 64861892, 0); // should be omitted - h.AddLine(0x4e4d271e, 9, 1, 67355743, 0); // should be recorded - h.AddLine(0xdfb5a72d, 30, 1, 23365776, 0); // should be recorded - h.AddLine(0, 0x64, 1, 76196762, 0); // should be omitted - h.AddLine(0x64, 0x33, 1, 71066611, 0); // should be omitted - h.AddLine(0x64 + 0x33, 0xe3, 1, 61749337, 0); // should be omitted - - ASSERT_EQ(2U, lines.size()); - EXPECT_EQ(67355743, lines[0].number); - EXPECT_EQ(23365776, lines[1].number); -} diff --git a/breakpad/common/language.cc b/breakpad/common/language.cc deleted file mode 100644 index c2fd81f64..000000000 --- a/breakpad/common/language.cc +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// language.cc: Subclasses and singletons for google_breakpad::Language. -// See language.h for details. - -#include "common/language.h" - -namespace google_breakpad { - -// C++ language-specific operations. -class CPPLanguage: public Language { - public: - CPPLanguage() {} - string MakeQualifiedName(const string &parent_name, - const string &name) const { - if (parent_name.empty()) - return name; - else - return parent_name + "::" + name; - } -}; - -CPPLanguage CPPLanguageSingleton; - -// Java language-specific operations. -class JavaLanguage: public Language { - public: - string MakeQualifiedName(const string &parent_name, - const string &name) const { - if (parent_name.empty()) - return name; - else - return parent_name + "." + name; - } -}; - -JavaLanguage JavaLanguageSingleton; - -// Assembler language-specific operations. -class AssemblerLanguage: public Language { - bool HasFunctions() const { return false; } - string MakeQualifiedName(const string &parent_name, - const string &name) const { - return name; - } -}; - -AssemblerLanguage AssemblerLanguageSingleton; - -const Language * const Language::CPlusPlus = &CPPLanguageSingleton; -const Language * const Language::Java = &JavaLanguageSingleton; -const Language * const Language::Assembler = &AssemblerLanguageSingleton; - -} // namespace google_breakpad diff --git a/breakpad/common/language.h b/breakpad/common/language.h deleted file mode 100644 index bbe303347..000000000 --- a/breakpad/common/language.h +++ /dev/null @@ -1,88 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// language.h: Define google_breakpad::Language. Instances of -// subclasses of this class provide language-appropriate operations -// for the Breakpad symbol dumper. - -#ifndef COMMON_LINUX_LANGUAGE_H__ -#define COMMON_LINUX_LANGUAGE_H__ - -#include - -#include "common/using_std_string.h" - -namespace google_breakpad { - -// An abstract base class for language-specific operations. We choose -// an instance of a subclass of this when we find the CU's language. -// This class's definitions are appropriate for CUs with no specified -// language. -class Language { - public: - // A base class destructor should be either public and virtual, - // or protected and nonvirtual. - virtual ~Language() {} - - // Return true if this language has functions to which we can assign - // line numbers. (Debugging info for assembly language, for example, - // can have source location information, but does not have functions - // recorded using DW_TAG_subprogram DIEs.) - virtual bool HasFunctions() const { return true; } - - // Construct a fully-qualified, language-appropriate form of NAME, - // given that PARENT_NAME is the name of the construct enclosing - // NAME. If PARENT_NAME is the empty string, then NAME is a - // top-level name. - // - // This API sort of assumes that a fully-qualified name is always - // some simple textual composition of the unqualified name and its - // parent's name, and that we don't need to know anything else about - // the parent or the child (say, their DIEs' tags) to do the job. - // This is true for the languages we support at the moment, and - // keeps things concrete. Perhaps a more refined operation would - // take into account the parent and child DIE types, allow languages - // to use their own data type for complex parent names, etc. But if - // C++ doesn't need all that, who would? - virtual string MakeQualifiedName (const string &parent_name, - const string &name) const = 0; - - // Instances for specific languages. - static const Language * const CPlusPlus, - * const Java, - * const Assembler; -}; - -} // namespace google_breakpad - -#endif // COMMON_LINUX_LANGUAGE_H__ diff --git a/breakpad/common/md5.cc b/breakpad/common/md5.cc deleted file mode 100644 index bccf61c60..000000000 --- a/breakpad/common/md5.cc +++ /dev/null @@ -1,251 +0,0 @@ -/* - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ - -#include - -#include "common/md5.h" - -namespace google_breakpad { - -#ifndef WORDS_BIGENDIAN -#define byteReverse(buf, len) /* Nothing */ -#else -/* - * Note: this code is harmless on little-endian machines. - */ -static void byteReverse(unsigned char *buf, unsigned longs) -{ - u32 t; - do { - t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(u32 *) buf = t; - buf += 4; - } while (--longs); -} -#endif - -static void MD5Transform(u32 buf[4], u32 const in[16]); - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void MD5Init(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) -{ - u32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((u32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void MD5Final(unsigned char digest[16], struct MD5Context *ctx) -{ - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((u32 *) ctx->in)[14] = ctx->bits[0]; - ((u32 *) ctx->in)[15] = ctx->bits[1]; - - MD5Transform(ctx->buf, (u32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ -} - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void MD5Transform(u32 buf[4], u32 const in[16]) -{ - register u32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -} // namespace google_breakpad - diff --git a/breakpad/common/md5.h b/breakpad/common/md5.h deleted file mode 100644 index e96521eed..000000000 --- a/breakpad/common/md5.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2007 Google Inc. All Rights Reserved. -// Author: liuli@google.com (Liu Li) -#ifndef COMMON_MD5_H__ -#define COMMON_MD5_H__ - -#include - -namespace google_breakpad { - -typedef uint32_t u32; -typedef uint8_t u8; - -struct MD5Context { - u32 buf[4]; - u32 bits[2]; - u8 in[64]; -}; - -void MD5Init(struct MD5Context *ctx); - -void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len); - -void MD5Final(unsigned char digest[16], struct MD5Context *ctx); - -} // namespace google_breakpad - -#endif // COMMON_MD5_H__ diff --git a/breakpad/common/memory.h b/breakpad/common/memory.h deleted file mode 100644 index 5f9444527..000000000 --- a/breakpad/common/memory.h +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_BREAKPAD_COMMON_MEMORY_H_ -#define GOOGLE_BREAKPAD_COMMON_MEMORY_H_ - -#include -#include -#include -#include - -#include -#include - -#ifdef __APPLE__ -#define sys_mmap mmap -#define sys_mmap2 mmap -#define sys_munmap munmap -#define MAP_ANONYMOUS MAP_ANON -#else -#include "third_party/lss/linux_syscall_support.h" -#endif - -namespace google_breakpad { - -// This is very simple allocator which fetches pages from the kernel directly. -// Thus, it can be used even when the heap may be corrupted. -// -// There is no free operation. The pages are only freed when the object is -// destroyed. -class PageAllocator { - public: - PageAllocator() - : page_size_(getpagesize()), - last_(NULL), - current_page_(NULL), - page_offset_(0) { - } - - ~PageAllocator() { - FreeAll(); - } - - void *Alloc(unsigned bytes) { - if (!bytes) - return NULL; - - if (current_page_ && page_size_ - page_offset_ >= bytes) { - uint8_t *const ret = current_page_ + page_offset_; - page_offset_ += bytes; - if (page_offset_ == page_size_) { - page_offset_ = 0; - current_page_ = NULL; - } - - return ret; - } - - const unsigned pages = - (bytes + sizeof(PageHeader) + page_size_ - 1) / page_size_; - uint8_t *const ret = GetNPages(pages); - if (!ret) - return NULL; - - page_offset_ = - (page_size_ - (page_size_ * pages - (bytes + sizeof(PageHeader)))) % - page_size_; - current_page_ = page_offset_ ? ret + page_size_ * (pages - 1) : NULL; - - return ret + sizeof(PageHeader); - } - - // Checks whether the page allocator owns the passed-in pointer. - // This method exists for testing pursposes only. - bool OwnsPointer(const void* p) { - for (PageHeader* header = last_; header; header = header->next) { - const char* current = reinterpret_cast(header); - if ((p >= current) && (p < current + header->num_pages * page_size_)) - return true; - } - - return false; - } - - private: - uint8_t *GetNPages(unsigned num_pages) { -#ifdef __x86_64 - void *a = sys_mmap(NULL, page_size_ * num_pages, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -#else - void *a = sys_mmap2(NULL, page_size_ * num_pages, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -#endif - if (a == MAP_FAILED) - return NULL; - - struct PageHeader *header = reinterpret_cast(a); - header->next = last_; - header->num_pages = num_pages; - last_ = header; - - return reinterpret_cast(a); - } - - void FreeAll() { - PageHeader *next; - - for (PageHeader *cur = last_; cur; cur = next) { - next = cur->next; - sys_munmap(cur, cur->num_pages * page_size_); - } - } - - struct PageHeader { - PageHeader *next; // pointer to the start of the next set of pages. - unsigned num_pages; // the number of pages in this set. - }; - - const unsigned page_size_; - PageHeader *last_; - uint8_t *current_page_; - unsigned page_offset_; -}; - -// Wrapper to use with STL containers -template -struct PageStdAllocator : public std::allocator { - typedef typename std::allocator::pointer pointer; - typedef typename std::allocator::size_type size_type; - - explicit PageStdAllocator(PageAllocator& allocator): allocator_(allocator) {} - template PageStdAllocator(const PageStdAllocator& other) - : allocator_(other.allocator_) {} - - inline pointer allocate(size_type n, const void* = 0) { - return static_cast(allocator_.Alloc(sizeof(T) * n)); - } - - inline void deallocate(pointer, size_type) { - // The PageAllocator doesn't free. - } - - template struct rebind { - typedef PageStdAllocator other; - }; - - private: - // Silly workaround for the gcc from Android's ndk (gcc 4.6), which will - // otherwise complain that `other.allocator_` is private in the constructor - // code. - template friend struct PageStdAllocator; - - PageAllocator& allocator_; -}; - -// A wasteful vector is a std::vector, except that it allocates memory from a -// PageAllocator. It's wasteful because, when resizing, it always allocates a -// whole new array since the PageAllocator doesn't support realloc. -template -class wasteful_vector : public std::vector > { - public: - wasteful_vector(PageAllocator* allocator, unsigned size_hint = 16) - : std::vector >(PageStdAllocator(*allocator)) { - std::vector >::reserve(size_hint); - } -}; - -} // namespace google_breakpad - -inline void* operator new(size_t nbytes, - google_breakpad::PageAllocator& allocator) { - return allocator.Alloc(nbytes); -} - -#endif // GOOGLE_BREAKPAD_COMMON_MEMORY_H_ diff --git a/breakpad/common/memory_range.h b/breakpad/common/memory_range.h deleted file mode 100644 index 41dd2da62..000000000 --- a/breakpad/common/memory_range.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// memory_range.h: Define the google_breakpad::MemoryRange class, which -// is a lightweight wrapper with a pointer and a length to encapsulate -// a contiguous range of memory. - -#ifndef COMMON_MEMORY_RANGE_H_ -#define COMMON_MEMORY_RANGE_H_ - -#include - -#include "google_breakpad/common/breakpad_types.h" - -namespace google_breakpad { - -// A lightweight wrapper with a pointer and a length to encapsulate a -// contiguous range of memory. It provides helper methods for checked -// access of a subrange of the memory. Its implemementation does not -// allocate memory or call into libc functions, and is thus safer to use -// in a crashed environment. -class MemoryRange { - public: - MemoryRange() : data_(NULL), length_(0) {} - - MemoryRange(const void* data, size_t length) { - Set(data, length); - } - - // Returns true if this memory range contains no data. - bool IsEmpty() const { - // Set() guarantees that |length_| is zero if |data_| is NULL. - return length_ == 0; - } - - // Resets to an empty range. - void Reset() { - data_ = NULL; - length_ = 0; - } - - // Sets this memory range to point to |data| and its length to |length|. - void Set(const void* data, size_t length) { - data_ = reinterpret_cast(data); - // Always set |length_| to zero if |data_| is NULL. - length_ = data ? length : 0; - } - - // Returns true if this range covers a subrange of |sub_length| bytes - // at |sub_offset| bytes of this memory range, or false otherwise. - bool Covers(size_t sub_offset, size_t sub_length) const { - // The following checks verify that: - // 1. sub_offset is within [ 0 .. length_ - 1 ] - // 2. sub_offset + sub_length is within - // [ sub_offset .. length_ ] - return sub_offset < length_ && - sub_offset + sub_length >= sub_offset && - sub_offset + sub_length <= length_; - } - - // Returns a raw data pointer to a subrange of |sub_length| bytes at - // |sub_offset| bytes of this memory range, or NULL if the subrange - // is out of bounds. - const void* GetData(size_t sub_offset, size_t sub_length) const { - return Covers(sub_offset, sub_length) ? (data_ + sub_offset) : NULL; - } - - // Same as the two-argument version of GetData() but uses sizeof(DataType) - // as the subrange length and returns an |DataType| pointer for convenience. - template - const DataType* GetData(size_t sub_offset) const { - return reinterpret_cast( - GetData(sub_offset, sizeof(DataType))); - } - - // Returns a raw pointer to the |element_index|-th element of an array - // of elements of length |element_size| starting at |sub_offset| bytes - // of this memory range, or NULL if the element is out of bounds. - const void* GetArrayElement(size_t element_offset, - size_t element_size, - unsigned element_index) const { - size_t sub_offset = element_offset + element_index * element_size; - return GetData(sub_offset, element_size); - } - - // Same as the three-argument version of GetArrayElement() but deduces - // the element size using sizeof(ElementType) and returns an |ElementType| - // pointer for convenience. - template - const ElementType* GetArrayElement(size_t element_offset, - unsigned element_index) const { - return reinterpret_cast( - GetArrayElement(element_offset, sizeof(ElementType), element_index)); - } - - // Returns a subrange of |sub_length| bytes at |sub_offset| bytes of - // this memory range, or an empty range if the subrange is out of bounds. - MemoryRange Subrange(size_t sub_offset, size_t sub_length) const { - return Covers(sub_offset, sub_length) ? - MemoryRange(data_ + sub_offset, sub_length) : MemoryRange(); - } - - // Returns a pointer to the beginning of this memory range. - const uint8_t* data() const { return data_; } - - // Returns the length, in bytes, of this memory range. - size_t length() const { return length_; } - - private: - // Pointer to the beginning of this memory range. - const uint8_t* data_; - - // Length, in bytes, of this memory range. - size_t length_; -}; - -} // namespace google_breakpad - -#endif // COMMON_MEMORY_RANGE_H_ diff --git a/breakpad/common/memory_range_unittest.cc b/breakpad/common/memory_range_unittest.cc deleted file mode 100644 index f6cf8c8b2..000000000 --- a/breakpad/common/memory_range_unittest.cc +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// memory_range_unittest.cc: Unit tests for google_breakpad::MemoryRange. - -#include "breakpad_googletest_includes.h" -#include "common/memory_range.h" - -using google_breakpad::MemoryRange; -using testing::Message; - -namespace { - -const uint32_t kBuffer[10] = { 0 }; -const size_t kBufferSize = sizeof(kBuffer); -const uint8_t* kBufferPointer = reinterpret_cast(kBuffer); - -// Test vectors for verifying Covers, GetData, and Subrange. -const struct { - bool valid; - size_t offset; - size_t length; -} kSubranges[] = { - { true, 0, 0 }, - { true, 0, 2 }, - { true, 0, kBufferSize }, - { true, 2, 0 }, - { true, 2, 4 }, - { true, 2, kBufferSize - 2 }, - { true, kBufferSize - 1, 1 }, - { false, kBufferSize, 0 }, - { false, kBufferSize, static_cast(-1) }, - { false, kBufferSize + 1, 0 }, - { false, static_cast(-1), 2 }, - { false, 1, kBufferSize }, - { false, kBufferSize - 1, 2 }, - { false, 0, static_cast(-1) }, - { false, 1, static_cast(-1) }, -}; -const size_t kNumSubranges = sizeof(kSubranges) / sizeof(kSubranges[0]); - -// Test vectors for verifying GetArrayElement. -const struct { - size_t offset; - size_t size; - size_t index; - const void* const pointer; -} kElements[] = { - // Valid array elemenets - { 0, 1, 0, kBufferPointer }, - { 0, 1, 1, kBufferPointer + 1 }, - { 0, 1, kBufferSize - 1, kBufferPointer + kBufferSize - 1 }, - { 0, 2, 1, kBufferPointer + 2 }, - { 0, 4, 2, kBufferPointer + 8 }, - { 0, 4, 9, kBufferPointer + 36 }, - { kBufferSize - 1, 1, 0, kBufferPointer + kBufferSize - 1 }, - // Invalid array elemenets - { 0, 1, kBufferSize, NULL }, - { 0, 4, 10, NULL }, - { kBufferSize - 1, 1, 1, NULL }, - { kBufferSize - 1, 2, 0, NULL }, - { kBufferSize, 1, 0, NULL }, -}; -const size_t kNumElements = sizeof(kElements) / sizeof(kElements[0]); - -} // namespace - -TEST(MemoryRangeTest, DefaultConstructor) { - MemoryRange range; - EXPECT_EQ(NULL, range.data()); - EXPECT_EQ(0U, range.length()); -} - -TEST(MemoryRangeTest, ConstructorWithDataAndLength) { - MemoryRange range(kBuffer, kBufferSize); - EXPECT_EQ(kBufferPointer, range.data()); - EXPECT_EQ(kBufferSize, range.length()); -} - -TEST(MemoryRangeTest, Reset) { - MemoryRange range; - range.Reset(); - EXPECT_EQ(NULL, range.data()); - EXPECT_EQ(0U, range.length()); - - range.Set(kBuffer, kBufferSize); - EXPECT_EQ(kBufferPointer, range.data()); - EXPECT_EQ(kBufferSize, range.length()); - - range.Reset(); - EXPECT_EQ(NULL, range.data()); - EXPECT_EQ(0U, range.length()); -} - -TEST(MemoryRangeTest, Set) { - MemoryRange range; - range.Set(kBuffer, kBufferSize); - EXPECT_EQ(kBufferPointer, range.data()); - EXPECT_EQ(kBufferSize, range.length()); - - range.Set(NULL, 0); - EXPECT_EQ(NULL, range.data()); - EXPECT_EQ(0U, range.length()); -} - -TEST(MemoryRangeTest, SubrangeOfEmptyMemoryRange) { - MemoryRange range; - MemoryRange subrange = range.Subrange(0, 10); - EXPECT_EQ(NULL, subrange.data()); - EXPECT_EQ(0U, subrange.length()); -} - -TEST(MemoryRangeTest, SubrangeAndGetData) { - MemoryRange range(kBuffer, kBufferSize); - for (size_t i = 0; i < kNumSubranges; ++i) { - bool valid = kSubranges[i].valid; - size_t sub_offset = kSubranges[i].offset; - size_t sub_length = kSubranges[i].length; - SCOPED_TRACE(Message() << "offset=" << sub_offset - << ", length=" << sub_length); - - MemoryRange subrange = range.Subrange(sub_offset, sub_length); - if (valid) { - EXPECT_TRUE(range.Covers(sub_offset, sub_length)); - EXPECT_EQ(kBufferPointer + sub_offset, - range.GetData(sub_offset, sub_length)); - EXPECT_EQ(kBufferPointer + sub_offset, subrange.data()); - EXPECT_EQ(sub_length, subrange.length()); - } else { - EXPECT_FALSE(range.Covers(sub_offset, sub_length)); - EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length)); - EXPECT_EQ(NULL, subrange.data()); - EXPECT_EQ(0U, subrange.length()); - } - } -} - -TEST(MemoryRangeTest, GetDataWithTemplateType) { - MemoryRange range(kBuffer, kBufferSize); - const char* char_pointer = range.GetData(0); - EXPECT_EQ(reinterpret_cast(kBufferPointer), char_pointer); - const int* int_pointer = range.GetData(0); - EXPECT_EQ(reinterpret_cast(kBufferPointer), int_pointer); -} - -TEST(MemoryRangeTest, GetArrayElement) { - MemoryRange range(kBuffer, kBufferSize); - for (size_t i = 0; i < kNumElements; ++i) { - size_t element_offset = kElements[i].offset; - size_t element_size = kElements[i].size; - unsigned element_index = kElements[i].index; - const void* const element_pointer = kElements[i].pointer; - SCOPED_TRACE(Message() << "offset=" << element_offset - << ", size=" << element_size - << ", index=" << element_index); - EXPECT_EQ(element_pointer, range.GetArrayElement( - element_offset, element_size, element_index)); - } -} - -TEST(MemoryRangeTest, GetArrayElmentWithTemplateType) { - MemoryRange range(kBuffer, kBufferSize); - const char* char_pointer = range.GetArrayElement(0, 0); - EXPECT_EQ(reinterpret_cast(kBufferPointer), char_pointer); - const int* int_pointer = range.GetArrayElement(0, 0); - EXPECT_EQ(reinterpret_cast(kBufferPointer), int_pointer); -} diff --git a/breakpad/common/memory_unittest.cc b/breakpad/common/memory_unittest.cc deleted file mode 100644 index 1e511ca56..000000000 --- a/breakpad/common/memory_unittest.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "breakpad_googletest_includes.h" -#include "common/memory.h" - -using namespace google_breakpad; - -namespace { -typedef testing::Test PageAllocatorTest; -} - -TEST(PageAllocatorTest, Setup) { - PageAllocator allocator; -} - -TEST(PageAllocatorTest, SmallObjects) { - PageAllocator allocator; - - for (unsigned i = 1; i < 1024; ++i) { - uint8_t *p = reinterpret_cast(allocator.Alloc(i)); - ASSERT_FALSE(p == NULL); - memset(p, 0, i); - } -} - -TEST(PageAllocatorTest, LargeObject) { - PageAllocator allocator; - - uint8_t *p = reinterpret_cast(allocator.Alloc(10000)); - ASSERT_FALSE(p == NULL); - for (unsigned i = 1; i < 10; ++i) { - uint8_t *p = reinterpret_cast(allocator.Alloc(i)); - ASSERT_FALSE(p == NULL); - memset(p, 0, i); - } -} - -namespace { -typedef testing::Test WastefulVectorTest; -} - -TEST(WastefulVectorTest, Setup) { - PageAllocator allocator_; - wasteful_vector v(&allocator_); - ASSERT_TRUE(v.empty()); - ASSERT_EQ(v.size(), 0u); -} - -TEST(WastefulVectorTest, Simple) { - PageAllocator allocator_; - wasteful_vector v(&allocator_); - - for (unsigned i = 0; i < 256; ++i) { - v.push_back(i); - ASSERT_EQ(i, v.back()); - ASSERT_EQ(&v.back(), &v[i]); - } - ASSERT_FALSE(v.empty()); - ASSERT_EQ(v.size(), 256u); - for (unsigned i = 0; i < 256; ++i) - ASSERT_EQ(v[i], i); -} - -TEST(WastefulVectorTest, UsesPageAllocator) { - PageAllocator allocator_; - wasteful_vector v(&allocator_); - - v.push_back(1); - ASSERT_TRUE(allocator_.OwnsPointer(&v[0])); -} diff --git a/breakpad/common/module.cc b/breakpad/common/module.cc deleted file mode 100644 index 2d2e4efc4..000000000 --- a/breakpad/common/module.cc +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright (c) 2011 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// module.cc: Implement google_breakpad::Module. See module.h. - -#include "common/module.h" - -#include -#include -#include -#include - -#include -#include - -namespace google_breakpad { - -using std::dec; -using std::endl; -using std::hex; - - -Module::Module(const string &name, const string &os, - const string &architecture, const string &id) : - name_(name), - os_(os), - architecture_(architecture), - id_(id), - load_address_(0) { } - -Module::~Module() { - for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it) - delete it->second; - for (FunctionSet::iterator it = functions_.begin(); - it != functions_.end(); ++it) { - delete *it; - } - for (vector::iterator it = stack_frame_entries_.begin(); - it != stack_frame_entries_.end(); ++it) { - delete *it; - } - for (ExternSet::iterator it = externs_.begin(); it != externs_.end(); ++it) - delete *it; -} - -void Module::SetLoadAddress(Address address) { - load_address_ = address; -} - -void Module::AddFunction(Function *function) { - // FUNC lines must not hold an empty name, so catch the problem early if - // callers try to add one. - assert(!function->name.empty()); - std::pair ret = functions_.insert(function); - if (!ret.second) { - // Free the duplicate that was not inserted because this Module - // now owns it. - delete function; - } -} - -void Module::AddFunctions(vector::iterator begin, - vector::iterator end) { - for (vector::iterator it = begin; it != end; ++it) - AddFunction(*it); -} - -void Module::AddStackFrameEntry(StackFrameEntry *stack_frame_entry) { - stack_frame_entries_.push_back(stack_frame_entry); -} - -void Module::AddExtern(Extern *ext) { - std::pair ret = externs_.insert(ext); - if (!ret.second) { - // Free the duplicate that was not inserted because this Module - // now owns it. - delete ext; - } -} - -void Module::GetFunctions(vector *vec, - vector::iterator i) { - vec->insert(i, functions_.begin(), functions_.end()); -} - -void Module::GetExterns(vector *vec, - vector::iterator i) { - vec->insert(i, externs_.begin(), externs_.end()); -} - -Module::File *Module::FindFile(const string &name) { - // A tricky bit here. The key of each map entry needs to be a - // pointer to the entry's File's name string. This means that we - // can't do the initial lookup with any operation that would create - // an empty entry for us if the name isn't found (like, say, - // operator[] or insert do), because such a created entry's key will - // be a pointer the string passed as our argument. Since the key of - // a map's value type is const, we can't fix it up once we've - // created our file. lower_bound does the lookup without doing an - // insertion, and returns a good hint iterator to pass to insert. - // Our "destiny" is where we belong, whether we're there or not now. - FileByNameMap::iterator destiny = files_.lower_bound(&name); - if (destiny == files_.end() - || *destiny->first != name) { // Repeated string comparison, boo hoo. - File *file = new File; - file->name = name; - file->source_id = -1; - destiny = files_.insert(destiny, - FileByNameMap::value_type(&file->name, file)); - } - return destiny->second; -} - -Module::File *Module::FindFile(const char *name) { - string name_string = name; - return FindFile(name_string); -} - -Module::File *Module::FindExistingFile(const string &name) { - FileByNameMap::iterator it = files_.find(&name); - return (it == files_.end()) ? NULL : it->second; -} - -void Module::GetFiles(vector *vec) { - vec->clear(); - for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it) - vec->push_back(it->second); -} - -void Module::GetStackFrameEntries(vector *vec) { - *vec = stack_frame_entries_; -} - -void Module::AssignSourceIds() { - // First, give every source file an id of -1. - for (FileByNameMap::iterator file_it = files_.begin(); - file_it != files_.end(); ++file_it) { - file_it->second->source_id = -1; - } - - // Next, mark all files actually cited by our functions' line number - // info, by setting each one's source id to zero. - for (FunctionSet::const_iterator func_it = functions_.begin(); - func_it != functions_.end(); ++func_it) { - Function *func = *func_it; - for (vector::iterator line_it = func->lines.begin(); - line_it != func->lines.end(); ++line_it) - line_it->file->source_id = 0; - } - - // Finally, assign source ids to those files that have been marked. - // We could have just assigned source id numbers while traversing - // the line numbers, but doing it this way numbers the files in - // lexicographical order by name, which is neat. - int next_source_id = 0; - for (FileByNameMap::iterator file_it = files_.begin(); - file_it != files_.end(); ++file_it) { - if (!file_it->second->source_id) - file_it->second->source_id = next_source_id++; - } -} - -bool Module::ReportError() { - fprintf(stderr, "error writing symbol file: %s\n", - strerror(errno)); - return false; -} - -bool Module::WriteRuleMap(const RuleMap &rule_map, std::ostream &stream) { - for (RuleMap::const_iterator it = rule_map.begin(); - it != rule_map.end(); ++it) { - if (it != rule_map.begin()) - stream << ' '; - stream << it->first << ": " << it->second; - } - return stream.good(); -} - -bool Module::Write(std::ostream &stream, SymbolData symbol_data) { - stream << "MODULE " << os_ << " " << architecture_ << " " - << id_ << " " << name_ << endl; - if (!stream.good()) - return ReportError(); - - if (symbol_data != ONLY_CFI) { - AssignSourceIds(); - - // Write out files. - for (FileByNameMap::iterator file_it = files_.begin(); - file_it != files_.end(); ++file_it) { - File *file = file_it->second; - if (file->source_id >= 0) { - stream << "FILE " << file->source_id << " " << file->name << endl; - if (!stream.good()) - return ReportError(); - } - } - - // Write out functions and their lines. - for (FunctionSet::const_iterator func_it = functions_.begin(); - func_it != functions_.end(); ++func_it) { - Function *func = *func_it; - stream << "FUNC " << hex - << (func->address - load_address_) << " " - << func->size << " " - << func->parameter_size << " " - << func->name << dec << endl; - if (!stream.good()) - return ReportError(); - - for (vector::iterator line_it = func->lines.begin(); - line_it != func->lines.end(); ++line_it) { - stream << hex - << (line_it->address - load_address_) << " " - << line_it->size << " " - << dec - << line_it->number << " " - << line_it->file->source_id << endl; - if (!stream.good()) - return ReportError(); - } - } - - // Write out 'PUBLIC' records. - for (ExternSet::const_iterator extern_it = externs_.begin(); - extern_it != externs_.end(); ++extern_it) { - Extern *ext = *extern_it; - stream << "PUBLIC " << hex - << (ext->address - load_address_) << " 0 " - << ext->name << dec << endl; - } - } - - if (symbol_data != NO_CFI) { - // Write out 'STACK CFI INIT' and 'STACK CFI' records. - vector::const_iterator frame_it; - for (frame_it = stack_frame_entries_.begin(); - frame_it != stack_frame_entries_.end(); ++frame_it) { - StackFrameEntry *entry = *frame_it; - stream << "STACK CFI INIT " << hex - << (entry->address - load_address_) << " " - << entry->size << " " << dec; - if (!stream.good() - || !WriteRuleMap(entry->initial_rules, stream)) - return ReportError(); - - stream << endl; - - // Write out this entry's delta rules as 'STACK CFI' records. - for (RuleChangeMap::const_iterator delta_it = entry->rule_changes.begin(); - delta_it != entry->rule_changes.end(); ++delta_it) { - stream << "STACK CFI " << hex - << (delta_it->first - load_address_) << " " << dec; - if (!stream.good() - || !WriteRuleMap(delta_it->second, stream)) - return ReportError(); - - stream << endl; - } - } - } - - return true; -} - -} // namespace google_breakpad diff --git a/breakpad/common/module.h b/breakpad/common/module.h deleted file mode 100644 index 398bc3157..000000000 --- a/breakpad/common/module.h +++ /dev/null @@ -1,324 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// module.h: Define google_breakpad::Module. A Module holds debugging -// information, and can write that information out as a Breakpad -// symbol file. - -#ifndef COMMON_LINUX_MODULE_H__ -#define COMMON_LINUX_MODULE_H__ - -#include -#include -#include -#include -#include - -#include "common/symbol_data.h" -#include "common/using_std_string.h" -#include "google_breakpad/common/breakpad_types.h" - -namespace google_breakpad { - -using std::set; -using std::vector; -using std::map; - -// A Module represents the contents of a module, and supports methods -// for adding information produced by parsing STABS or DWARF data -// --- possibly both from the same file --- and then writing out the -// unified contents as a Breakpad-format symbol file. -class Module { - public: - // The type of addresses and sizes in a symbol table. - typedef uint64_t Address; - struct File; - struct Function; - struct Line; - struct Extern; - - // Addresses appearing in File, Function, and Line structures are - // absolute, not relative to the the module's load address. That - // is, if the module were loaded at its nominal load address, the - // addresses would be correct. - - // A source file. - struct File { - // The name of the source file. - string name; - - // The file's source id. The Write member function clears this - // field and assigns source ids a fresh, so any value placed here - // before calling Write will be lost. - int source_id; - }; - - // A function. - struct Function { - // For sorting by address. (Not style-guide compliant, but it's - // stupid not to put this in the struct.) - static bool CompareByAddress(const Function *x, const Function *y) { - return x->address < y->address; - } - - // The function's name. - string name; - - // The start address and length of the function's code. - Address address, size; - - // The function's parameter size. - Address parameter_size; - - // Source lines belonging to this function, sorted by increasing - // address. - vector lines; - }; - - // A source line. - struct Line { - // For sorting by address. (Not style-guide compliant, but it's - // stupid not to put this in the struct.) - static bool CompareByAddress(const Module::Line &x, const Module::Line &y) { - return x.address < y.address; - } - - Address address, size; // The address and size of the line's code. - File *file; // The source file. - int number; // The source line number. - }; - - // An exported symbol. - struct Extern { - Address address; - string name; - }; - - // A map from register names to postfix expressions that recover - // their their values. This can represent a complete set of rules to - // follow at some address, or a set of changes to be applied to an - // extant set of rules. - typedef map RuleMap; - - // A map from addresses to RuleMaps, representing changes that take - // effect at given addresses. - typedef map RuleChangeMap; - - // A range of 'STACK CFI' stack walking information. An instance of - // this structure corresponds to a 'STACK CFI INIT' record and the - // subsequent 'STACK CFI' records that fall within its range. - struct StackFrameEntry { - // The starting address and number of bytes of machine code this - // entry covers. - Address address, size; - - // The initial register recovery rules, in force at the starting - // address. - RuleMap initial_rules; - - // A map from addresses to rule changes. To find the rules in - // force at a given address, start with initial_rules, and then - // apply the changes given in this map for all addresses up to and - // including the address you're interested in. - RuleChangeMap rule_changes; - }; - - struct FunctionCompare { - bool operator() (const Function *lhs, - const Function *rhs) const { - if (lhs->address == rhs->address) - return lhs->name < rhs->name; - return lhs->address < rhs->address; - } - }; - - struct ExternCompare { - bool operator() (const Extern *lhs, - const Extern *rhs) const { - return lhs->address < rhs->address; - } - }; - - // Create a new module with the given name, operating system, - // architecture, and ID string. - Module(const string &name, const string &os, const string &architecture, - const string &id); - ~Module(); - - // Set the module's load address to LOAD_ADDRESS; addresses given - // for functions and lines will be written to the Breakpad symbol - // file as offsets from this address. Construction initializes this - // module's load address to zero: addresses written to the symbol - // file will be the same as they appear in the Function, Line, and - // StackFrameEntry structures. - // - // Note that this member function has no effect on addresses stored - // in the data added to this module; the Write member function - // simply subtracts off the load address from addresses before it - // prints them. Only the last load address given before calling - // Write is used. - void SetLoadAddress(Address load_address); - - // Add FUNCTION to the module. FUNCTION's name must not be empty. - // This module owns all Function objects added with this function: - // destroying the module destroys them as well. - void AddFunction(Function *function); - - // Add all the functions in [BEGIN,END) to the module. - // This module owns all Function objects added with this function: - // destroying the module destroys them as well. - void AddFunctions(vector::iterator begin, - vector::iterator end); - - // Add STACK_FRAME_ENTRY to the module. - // This module owns all StackFrameEntry objects added with this - // function: destroying the module destroys them as well. - void AddStackFrameEntry(StackFrameEntry *stack_frame_entry); - - // Add PUBLIC to the module. - // This module owns all Extern objects added with this function: - // destroying the module destroys them as well. - void AddExtern(Extern *ext); - - // If this module has a file named NAME, return a pointer to it. If - // it has none, then create one and return a pointer to the new - // file. This module owns all File objects created using these - // functions; destroying the module destroys them as well. - File *FindFile(const string &name); - File *FindFile(const char *name); - - // If this module has a file named NAME, return a pointer to it. - // Otherwise, return NULL. - File *FindExistingFile(const string &name); - - // Insert pointers to the functions added to this module at I in - // VEC. The pointed-to Functions are still owned by this module. - // (Since this is effectively a copy of the function list, this is - // mostly useful for testing; other uses should probably get a more - // appropriate interface.) - void GetFunctions(vector *vec, vector::iterator i); - - // Insert pointers to the externs added to this module at I in - // VEC. The pointed-to Externs are still owned by this module. - // (Since this is effectively a copy of the extern list, this is - // mostly useful for testing; other uses should probably get a more - // appropriate interface.) - void GetExterns(vector *vec, vector::iterator i); - - // Clear VEC and fill it with pointers to the Files added to this - // module, sorted by name. The pointed-to Files are still owned by - // this module. (Since this is effectively a copy of the file list, - // this is mostly useful for testing; other uses should probably get - // a more appropriate interface.) - void GetFiles(vector *vec); - - // Clear VEC and fill it with pointers to the StackFrameEntry - // objects that have been added to this module. (Since this is - // effectively a copy of the stack frame entry list, this is mostly - // useful for testing; other uses should probably get - // a more appropriate interface.) - void GetStackFrameEntries(vector *vec); - - // Find those files in this module that are actually referred to by - // functions' line number data, and assign them source id numbers. - // Set the source id numbers for all other files --- unused by the - // source line data --- to -1. We do this before writing out the - // symbol file, at which point we omit any unused files. - void AssignSourceIds(); - - // Call AssignSourceIds, and write this module to STREAM in the - // breakpad symbol format. Return true if all goes well, or false if - // an error occurs. This method writes out: - // - a header based on the values given to the constructor, - // If symbol_data is not ONLY_CFI then: - // - the source files added via FindFile, - // - the functions added via AddFunctions, each with its lines, - // - all public records, - // If symbol_data is not NO_CFI then: - // - all CFI records. - // Addresses in the output are all relative to the load address - // established by SetLoadAddress. - bool Write(std::ostream &stream, SymbolData symbol_data); - - private: - // Report an error that has occurred writing the symbol file, using - // errno to find the appropriate cause. Return false. - static bool ReportError(); - - // Write RULE_MAP to STREAM, in the form appropriate for 'STACK CFI' - // records, without a final newline. Return true if all goes well; - // if an error occurs, return false, and leave errno set. - static bool WriteRuleMap(const RuleMap &rule_map, std::ostream &stream); - - // Module header entries. - string name_, os_, architecture_, id_; - - // The module's nominal load address. Addresses for functions and - // lines are absolute, assuming the module is loaded at this - // address. - Address load_address_; - - // Relation for maps whose keys are strings shared with some other - // structure. - struct CompareStringPtrs { - bool operator()(const string *x, const string *y) const { return *x < *y; } - }; - - // A map from filenames to File structures. The map's keys are - // pointers to the Files' names. - typedef map FileByNameMap; - - // A set containing Function structures, sorted by address. - typedef set FunctionSet; - - // A set containing Extern structures, sorted by address. - typedef set ExternSet; - - // The module owns all the files and functions that have been added - // to it; destroying the module frees the Files and Functions these - // point to. - FileByNameMap files_; // This module's source files. - FunctionSet functions_; // This module's functions. - - // The module owns all the call frame info entries that have been - // added to it. - vector stack_frame_entries_; - - // The module owns all the externs that have been added to it; - // destroying the module frees the Externs these point to. - ExternSet externs_; -}; - -} // namespace google_breakpad - -#endif // COMMON_LINUX_MODULE_H__ diff --git a/breakpad/common/module_unittest.cc b/breakpad/common/module_unittest.cc deleted file mode 100644 index 5c0c69757..000000000 --- a/breakpad/common/module_unittest.cc +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// module_unittest.cc: Unit tests for google_breakpad::Module. - -#include -#include -#include -#include - -#include -#include -#include - -#include "breakpad_googletest_includes.h" -#include "common/module.h" -#include "common/using_std_string.h" - -using google_breakpad::Module; -using std::stringstream; -using std::vector; -using testing::ContainerEq; - -static Module::Function *generate_duplicate_function(const string &name) { - const Module::Address DUP_ADDRESS = 0xd35402aac7a7ad5cLL; - const Module::Address DUP_SIZE = 0x200b26e605f99071LL; - const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL; - - Module::Function *function = new(Module::Function); - function->name = name; - function->address = DUP_ADDRESS; - function->size = DUP_SIZE; - function->parameter_size = DUP_PARAMETER_SIZE; - return function; -} - -#define MODULE_NAME "name with spaces" -#define MODULE_OS "os-name" -#define MODULE_ARCH "architecture" -#define MODULE_ID "id-string" - -TEST(Write, Header) { - stringstream s; - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - m.Write(s, ALL_SYMBOL_DATA); - string contents = s.str(); - EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n", - contents.c_str()); -} - -TEST(Write, OneLineFunc) { - stringstream s; - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - - Module::File *file = m.FindFile("file_name.cc"); - Module::Function *function = new(Module::Function); - function->name = "function_name"; - function->address = 0xe165bf8023b9d9abLL; - function->size = 0x1e4bb0eb1cbf5b09LL; - function->parameter_size = 0x772beee89114358aLL; - Module::Line line = { 0xe165bf8023b9d9abLL, 0x1e4bb0eb1cbf5b09LL, - file, 67519080 }; - function->lines.push_back(line); - m.AddFunction(function); - - m.Write(s, ALL_SYMBOL_DATA); - string contents = s.str(); - EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" - "FILE 0 file_name.cc\n" - "FUNC e165bf8023b9d9ab 1e4bb0eb1cbf5b09 772beee89114358a" - " function_name\n" - "e165bf8023b9d9ab 1e4bb0eb1cbf5b09 67519080 0\n", - contents.c_str()); -} - -TEST(Write, RelativeLoadAddress) { - stringstream s; - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - - // Some source files. We will expect to see them in lexicographic order. - Module::File *file1 = m.FindFile("filename-b.cc"); - Module::File *file2 = m.FindFile("filename-a.cc"); - - // A function. - Module::Function *function = new(Module::Function); - function->name = "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)"; - function->address = 0xbec774ea5dd935f3LL; - function->size = 0x2922088f98d3f6fcLL; - function->parameter_size = 0xe5e9aa008bd5f0d0LL; - - // Some source lines. The module should not sort these. - Module::Line line1 = { 0xbec774ea5dd935f3LL, 0x1c2be6d6c5af2611LL, - file1, 41676901 }; - Module::Line line2 = { 0xdaf35bc123885c04LL, 0xcf621b8d324d0ebLL, - file2, 67519080 }; - function->lines.push_back(line2); - function->lines.push_back(line1); - - m.AddFunction(function); - - // Some stack information. - Module::StackFrameEntry *entry = new Module::StackFrameEntry(); - entry->address = 0x30f9e5c83323973dULL; - entry->size = 0x49fc9ca7c7c13dc2ULL; - entry->initial_rules[".cfa"] = "he was a handsome man"; - entry->initial_rules["and"] = "what i want to know is"; - entry->rule_changes[0x30f9e5c83323973eULL]["how"] = - "do you like your blueeyed boy"; - entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = "Death"; - m.AddStackFrameEntry(entry); - - // Set the load address. Doing this after adding all the data to - // the module must work fine. - m.SetLoadAddress(0x2ab698b0b6407073LL); - - m.Write(s, ALL_SYMBOL_DATA); - string contents = s.str(); - EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" - "FILE 0 filename-a.cc\n" - "FILE 1 filename-b.cc\n" - "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0" - " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n" - "b03cc3106d47eb91 cf621b8d324d0eb 67519080 0\n" - "9410dc39a798c580 1c2be6d6c5af2611 41676901 1\n" - "STACK CFI INIT 6434d177ce326ca 49fc9ca7c7c13dc2" - " .cfa: he was a handsome man" - " and: what i want to know is\n" - "STACK CFI 6434d177ce326cb" - " Mister: Death" - " how: do you like your blueeyed boy\n", - contents.c_str()); -} - -TEST(Write, OmitUnusedFiles) { - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - - // Create some source files. - Module::File *file1 = m.FindFile("filename1"); - m.FindFile("filename2"); // not used by any line - Module::File *file3 = m.FindFile("filename3"); - - // Create a function. - Module::Function *function = new(Module::Function); - function->name = "function_name"; - function->address = 0x9b926d464f0b9384LL; - function->size = 0x4f524a4ba795e6a6LL; - function->parameter_size = 0xbbe8133a6641c9b7LL; - - // Source files that refer to some files, but not others. - Module::Line line1 = { 0x595fa44ebacc1086LL, 0x1e1e0191b066c5b3LL, - file1, 137850127 }; - Module::Line line2 = { 0x401ce8c8a12d25e3LL, 0x895751c41b8d2ce2LL, - file3, 28113549 }; - function->lines.push_back(line1); - function->lines.push_back(line2); - m.AddFunction(function); - - m.AssignSourceIds(); - - vector vec; - m.GetFiles(&vec); - EXPECT_EQ((size_t) 3, vec.size()); - EXPECT_STREQ("filename1", vec[0]->name.c_str()); - EXPECT_NE(-1, vec[0]->source_id); - // Expect filename2 not to be used. - EXPECT_STREQ("filename2", vec[1]->name.c_str()); - EXPECT_EQ(-1, vec[1]->source_id); - EXPECT_STREQ("filename3", vec[2]->name.c_str()); - EXPECT_NE(-1, vec[2]->source_id); - - stringstream s; - m.Write(s, ALL_SYMBOL_DATA); - string contents = s.str(); - EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" - "FILE 0 filename1\n" - "FILE 1 filename3\n" - "FUNC 9b926d464f0b9384 4f524a4ba795e6a6 bbe8133a6641c9b7" - " function_name\n" - "595fa44ebacc1086 1e1e0191b066c5b3 137850127 0\n" - "401ce8c8a12d25e3 895751c41b8d2ce2 28113549 1\n", - contents.c_str()); -} - -TEST(Write, NoCFI) { - stringstream s; - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - - // Some source files. We will expect to see them in lexicographic order. - Module::File *file1 = m.FindFile("filename.cc"); - - // A function. - Module::Function *function = new(Module::Function); - function->name = "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)"; - function->address = 0xbec774ea5dd935f3LL; - function->size = 0x2922088f98d3f6fcLL; - function->parameter_size = 0xe5e9aa008bd5f0d0LL; - - // Some source lines. The module should not sort these. - Module::Line line1 = { 0xbec774ea5dd935f3LL, 0x1c2be6d6c5af2611LL, - file1, 41676901 }; - function->lines.push_back(line1); - - m.AddFunction(function); - - // Some stack information. - Module::StackFrameEntry *entry = new Module::StackFrameEntry(); - entry->address = 0x30f9e5c83323973dULL; - entry->size = 0x49fc9ca7c7c13dc2ULL; - entry->initial_rules[".cfa"] = "he was a handsome man"; - entry->initial_rules["and"] = "what i want to know is"; - entry->rule_changes[0x30f9e5c83323973eULL]["how"] = - "do you like your blueeyed boy"; - entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = "Death"; - m.AddStackFrameEntry(entry); - - // Set the load address. Doing this after adding all the data to - // the module must work fine. - m.SetLoadAddress(0x2ab698b0b6407073LL); - - m.Write(s, NO_CFI); - string contents = s.str(); - EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" - "FILE 0 filename.cc\n" - "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0" - " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n" - "9410dc39a798c580 1c2be6d6c5af2611 41676901 0\n", - contents.c_str()); -} - -TEST(Construct, AddFunctions) { - stringstream s; - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - - // Two functions. - Module::Function *function1 = new(Module::Function); - function1->name = "_without_form"; - function1->address = 0xd35024aa7ca7da5cLL; - function1->size = 0x200b26e605f99071LL; - function1->parameter_size = 0xf14ac4fed48c4a99LL; - - Module::Function *function2 = new(Module::Function); - function2->name = "_and_void"; - function2->address = 0x2987743d0b35b13fLL; - function2->size = 0xb369db048deb3010LL; - function2->parameter_size = 0x938e556cb5a79988LL; - - // Put them in a vector. - vector vec; - vec.push_back(function1); - vec.push_back(function2); - - m.AddFunctions(vec.begin(), vec.end()); - - m.Write(s, ALL_SYMBOL_DATA); - string contents = s.str(); - EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" - "FUNC 2987743d0b35b13f b369db048deb3010 938e556cb5a79988" - " _and_void\n" - "FUNC d35024aa7ca7da5c 200b26e605f99071 f14ac4fed48c4a99" - " _without_form\n", - contents.c_str()); - - // Check that m.GetFunctions returns the functions we expect. - vec.clear(); - m.GetFunctions(&vec, vec.end()); - EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function1)); - EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function2)); - EXPECT_EQ((size_t) 2, vec.size()); -} - -TEST(Construct, AddFrames) { - stringstream s; - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - - // First STACK CFI entry, with no initial rules or deltas. - Module::StackFrameEntry *entry1 = new Module::StackFrameEntry(); - entry1->address = 0xddb5f41285aa7757ULL; - entry1->size = 0x1486493370dc5073ULL; - m.AddStackFrameEntry(entry1); - - // Second STACK CFI entry, with initial rules but no deltas. - Module::StackFrameEntry *entry2 = new Module::StackFrameEntry(); - entry2->address = 0x8064f3af5e067e38ULL; - entry2->size = 0x0de2a5ee55509407ULL; - entry2->initial_rules[".cfa"] = "I think that I shall never see"; - entry2->initial_rules["stromboli"] = "a poem lovely as a tree"; - entry2->initial_rules["cannoli"] = "a tree whose hungry mouth is prest"; - m.AddStackFrameEntry(entry2); - - // Third STACK CFI entry, with initial rules and deltas. - Module::StackFrameEntry *entry3 = new Module::StackFrameEntry(); - entry3->address = 0x5e8d0db0a7075c6cULL; - entry3->size = 0x1c7edb12a7aea229ULL; - entry3->initial_rules[".cfa"] = "Whose woods are these"; - entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] = - "the village though"; - entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] = - "he will not see me stopping here"; - entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] = - "his house is in"; - entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] = - "I think I know"; - m.AddStackFrameEntry(entry3); - - // Check that Write writes STACK CFI records properly. - m.Write(s, ALL_SYMBOL_DATA); - string contents = s.str(); - EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" - "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n" - "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407" - " .cfa: I think that I shall never see" - " cannoli: a tree whose hungry mouth is prest" - " stromboli: a poem lovely as a tree\n" - "STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229" - " .cfa: Whose woods are these\n" - "STACK CFI 36682fad3763ffff" - " .cfa: I think I know" - " stromboli: his house is in\n" - "STACK CFI 47ceb0f63c269d7f" - " calzone: the village though" - " cannoli: he will not see me stopping here\n", - contents.c_str()); - - // Check that GetStackFrameEntries works. - vector entries; - m.GetStackFrameEntries(&entries); - ASSERT_EQ(3U, entries.size()); - // Check first entry. - EXPECT_EQ(0xddb5f41285aa7757ULL, entries[0]->address); - EXPECT_EQ(0x1486493370dc5073ULL, entries[0]->size); - ASSERT_EQ(0U, entries[0]->initial_rules.size()); - ASSERT_EQ(0U, entries[0]->rule_changes.size()); - // Check second entry. - EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address); - EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size); - ASSERT_EQ(3U, entries[1]->initial_rules.size()); - Module::RuleMap entry2_initial; - entry2_initial[".cfa"] = "I think that I shall never see"; - entry2_initial["stromboli"] = "a poem lovely as a tree"; - entry2_initial["cannoli"] = "a tree whose hungry mouth is prest"; - EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial)); - ASSERT_EQ(0U, entries[1]->rule_changes.size()); - // Check third entry. - EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[2]->address); - EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[2]->size); - Module::RuleMap entry3_initial; - entry3_initial[".cfa"] = "Whose woods are these"; - EXPECT_THAT(entries[2]->initial_rules, ContainerEq(entry3_initial)); - Module::RuleChangeMap entry3_changes; - entry3_changes[0x36682fad3763ffffULL][".cfa"] = "I think I know"; - entry3_changes[0x36682fad3763ffffULL]["stromboli"] = "his house is in"; - entry3_changes[0x47ceb0f63c269d7fULL]["calzone"] = "the village though"; - entry3_changes[0x47ceb0f63c269d7fULL]["cannoli"] = - "he will not see me stopping here"; - EXPECT_THAT(entries[2]->rule_changes, ContainerEq(entry3_changes)); -} - -TEST(Construct, UniqueFiles) { - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - Module::File *file1 = m.FindFile("foo"); - Module::File *file2 = m.FindFile(string("bar")); - Module::File *file3 = m.FindFile(string("foo")); - Module::File *file4 = m.FindFile("bar"); - EXPECT_NE(file1, file2); - EXPECT_EQ(file1, file3); - EXPECT_EQ(file2, file4); - EXPECT_EQ(file1, m.FindExistingFile("foo")); - EXPECT_TRUE(m.FindExistingFile("baz") == NULL); -} - -TEST(Construct, DuplicateFunctions) { - stringstream s; - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - - // Two functions. - Module::Function *function1 = generate_duplicate_function("_without_form"); - Module::Function *function2 = generate_duplicate_function("_without_form"); - - m.AddFunction(function1); - m.AddFunction(function2); - - m.Write(s, ALL_SYMBOL_DATA); - string contents = s.str(); - EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" - "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99" - " _without_form\n", - contents.c_str()); -} - -TEST(Construct, FunctionsWithSameAddress) { - stringstream s; - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - - // Two functions. - Module::Function *function1 = generate_duplicate_function("_without_form"); - Module::Function *function2 = generate_duplicate_function("_and_void"); - - m.AddFunction(function1); - m.AddFunction(function2); - - m.Write(s, ALL_SYMBOL_DATA); - string contents = s.str(); - EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" - "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99" - " _and_void\n" - "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99" - " _without_form\n", - contents.c_str()); -} - -// Externs should be written out as PUBLIC records, sorted by -// address. -TEST(Construct, Externs) { - stringstream s; - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - - // Two externs. - Module::Extern *extern1 = new(Module::Extern); - extern1->address = 0xffff; - extern1->name = "_abc"; - Module::Extern *extern2 = new(Module::Extern); - extern2->address = 0xaaaa; - extern2->name = "_xyz"; - - m.AddExtern(extern1); - m.AddExtern(extern2); - - m.Write(s, ALL_SYMBOL_DATA); - string contents = s.str(); - - EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " " - MODULE_ID " " MODULE_NAME "\n" - "PUBLIC aaaa 0 _xyz\n" - "PUBLIC ffff 0 _abc\n", - contents.c_str()); -} - -// Externs with the same address should only keep the first entry -// added. -TEST(Construct, DuplicateExterns) { - stringstream s; - Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - - // Two externs. - Module::Extern *extern1 = new(Module::Extern); - extern1->address = 0xffff; - extern1->name = "_xyz"; - Module::Extern *extern2 = new(Module::Extern); - extern2->address = 0xffff; - extern2->name = "_abc"; - - m.AddExtern(extern1); - m.AddExtern(extern2); - - m.Write(s, ALL_SYMBOL_DATA); - string contents = s.str(); - - EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " " - MODULE_ID " " MODULE_NAME "\n" - "PUBLIC ffff 0 _xyz\n", - contents.c_str()); -} diff --git a/breakpad/common/simple_string_dictionary.cc b/breakpad/common/simple_string_dictionary.cc deleted file mode 100644 index e0a74ceeb..000000000 --- a/breakpad/common/simple_string_dictionary.cc +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "common/simple_string_dictionary.h" - -namespace google_breakpad { - -namespace { - -// In C++98 (ISO 14882), section 9.5.1 says that a union cannot have a member -// with a non-trivial ctor, copy ctor, dtor, or assignment operator. Use this -// property to ensure that Entry remains POD. -union Compile_Assert { - NonAllocatingMap<1, 1, 1>::Entry Compile_Assert__entry_must_be_pod; -}; - -} - -} // namespace google_breakpad diff --git a/breakpad/common/simple_string_dictionary.h b/breakpad/common/simple_string_dictionary.h deleted file mode 100644 index e241aff54..000000000 --- a/breakpad/common/simple_string_dictionary.h +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright (c) 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef COMMON_SIMPLE_STRING_DICTIONARY_H_ -#define COMMON_SIMPLE_STRING_DICTIONARY_H_ - -#include -#include - -#include "common/basictypes.h" - -namespace google_breakpad { - -// Opaque type for the serialized representation of a NonAllocatingMap. One is -// created in NonAllocatingMap::Serialize and can be deserialized using one of -// the constructors. -struct SerializedNonAllocatingMap; - -// NonAllocatingMap is an implementation of a map/dictionary collection that -// uses a fixed amount of storage, so that it does not perform any dynamic -// allocations for its operations. -// -// The actual map storage (the Entry) is guaranteed to be POD, so that it can -// be transmitted over various IPC mechanisms. -// -// The template parameters control the amount of storage used for the key, -// value, and map. The KeySize and ValueSize are measured in bytes, not glyphs, -// and includes space for a \0 byte. This gives space for KeySize-1 and -// ValueSize-1 characters in an entry. NumEntries is the total number of -// entries that will fit in the map. -template -class NonAllocatingMap { - public: - // Constant and publicly accessible versions of the template parameters. - static const size_t key_size = KeySize; - static const size_t value_size = ValueSize; - static const size_t num_entries = NumEntries; - - // An Entry object is a single entry in the map. If the key is a 0-length - // NUL-terminated string, the entry is empty. - struct Entry { - char key[KeySize]; - char value[ValueSize]; - - bool is_active() const { - return key[0] != '\0'; - } - }; - - // An Iterator can be used to iterate over all the active entries in a - // NonAllocatingMap. - class Iterator { - public: - explicit Iterator(const NonAllocatingMap& map) - : map_(map), - current_(0) { - } - - // Returns the next entry in the map, or NULL if at the end of the - // collection. - const Entry* Next() { - while (current_ < map_.num_entries) { - const Entry* entry = &map_.entries_[current_++]; - if (entry->is_active()) { - return entry; - } - } - return NULL; - } - - private: - const NonAllocatingMap& map_; - size_t current_; - - DISALLOW_COPY_AND_ASSIGN(Iterator); - }; - - NonAllocatingMap() : entries_() { - } - - NonAllocatingMap(const NonAllocatingMap& other) { - *this = other; - } - - NonAllocatingMap& operator=(const NonAllocatingMap& other) { - assert(other.key_size == key_size); - assert(other.value_size == value_size); - assert(other.num_entries == num_entries); - if (other.key_size == key_size && other.value_size == value_size && - other.num_entries == num_entries) { - memcpy(entries_, other.entries_, sizeof(entries_)); - } - return *this; - } - - // Constructs a map from its serialized form. |map| should be the out - // parameter from Serialize() and |size| should be its return value. - NonAllocatingMap(const SerializedNonAllocatingMap* map, size_t size) { - assert(size == sizeof(entries_)); - if (size == sizeof(entries_)) { - memcpy(entries_, map, size); - } - } - - // Returns the number of active key/value pairs. The upper limit for this - // is NumEntries. - size_t GetCount() const { - size_t count = 0; - for (size_t i = 0; i < num_entries; ++i) { - if (entries_[i].is_active()) { - ++count; - } - } - return count; - } - - // Given |key|, returns its corresponding |value|. |key| must not be NULL. If - // the key is not found, NULL is returned. - const char* GetValueForKey(const char* key) const { - assert(key); - if (!key) - return NULL; - - const Entry* entry = GetConstEntryForKey(key); - if (!entry) - return NULL; - - return entry->value; - } - - // Stores |value| into |key|, replacing the existing value if |key| is - // already present. |key| must not be NULL. If |value| is NULL, the key is - // removed from the map. If there is no more space in the map, then the - // operation silently fails. - void SetKeyValue(const char* key, const char* value) { - if (!value) { - RemoveKey(key); - return; - } - - assert(key); - if (!key) - return; - - // Key must not be an empty string. - assert(key[0] != '\0'); - if (key[0] == '\0') - return; - - Entry* entry = GetEntryForKey(key); - - // If it does not yet exist, attempt to insert it. - if (!entry) { - for (size_t i = 0; i < num_entries; ++i) { - if (!entries_[i].is_active()) { - entry = &entries_[i]; - - assert(strlen(key) < key_size); - - strncpy(entry->key, key, key_size); - entry->key[key_size - 1] = '\0'; - - break; - } - } - } - - // If the map is out of space, entry will be NULL. - if (!entry) - return; - -#ifndef NDEBUG - // Sanity check that the key only appears once. - int count = 0; - for (size_t i = 0; i < num_entries; ++i) { - if (strncmp(entries_[i].key, key, key_size) == 0) - ++count; - } - assert(count == 1); -#endif - - assert(strlen(value) < value_size); - strncpy(entry->value, value, value_size); - entry->value[value_size - 1] = '\0'; - } - - // Given |key|, removes any associated value. |key| must not be NULL. If - // the key is not found, this is a noop. - void RemoveKey(const char* key) { - assert(key); - if (!key) - return; - - Entry* entry = GetEntryForKey(key); - if (entry) { - entry->key[0] = '\0'; - entry->value[0] = '\0'; - } - -#ifndef NDEBUG - assert(GetEntryForKey(key) == NULL); -#endif - } - - // Places a serialized version of the map into |map| and returns the size. - // Both of these should be passed to the deserializing constructor. Note that - // the serialized |map| is scoped to the lifetime of the non-serialized - // instance of this class. The |map| can be copied across IPC boundaries. - size_t Serialize(const SerializedNonAllocatingMap** map) const { - *map = reinterpret_cast(entries_); - return sizeof(entries_); - } - - private: - const Entry* GetConstEntryForKey(const char* key) const { - for (size_t i = 0; i < num_entries; ++i) { - if (strncmp(key, entries_[i].key, key_size) == 0) { - return &entries_[i]; - } - } - return NULL; - } - - Entry* GetEntryForKey(const char* key) { - return const_cast(GetConstEntryForKey(key)); - } - - Entry entries_[NumEntries]; -}; - -// For historical reasons this specialized version is available with the same -// size factors as a previous implementation. -typedef NonAllocatingMap<256, 256, 64> SimpleStringDictionary; - -} // namespace google_breakpad - -#endif // COMMON_SIMPLE_STRING_DICTIONARY_H_ diff --git a/breakpad/common/simple_string_dictionary_unittest.cc b/breakpad/common/simple_string_dictionary_unittest.cc deleted file mode 100644 index 5fbc481c5..000000000 --- a/breakpad/common/simple_string_dictionary_unittest.cc +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "breakpad_googletest_includes.h" -#include "common/simple_string_dictionary.h" - -namespace google_breakpad { - -TEST(NonAllocatingMapTest, Entry) { - typedef NonAllocatingMap<5, 9, 15> TestMap; - TestMap map; - - const TestMap::Entry* entry = TestMap::Iterator(map).Next(); - EXPECT_FALSE(entry); - - // Try setting a key/value and then verify. - map.SetKeyValue("key1", "value1"); - entry = TestMap::Iterator(map).Next(); - ASSERT_TRUE(entry); - EXPECT_STREQ(entry->key, "key1"); - EXPECT_STREQ(entry->value, "value1"); - - // Try setting a new value. - map.SetKeyValue("key1", "value3"); - EXPECT_STREQ(entry->value, "value3"); - - // Make sure the key didn't change. - EXPECT_STREQ(entry->key, "key1"); - - // Clear the entry and verify the key and value are empty strings. - map.RemoveKey("key1"); - EXPECT_FALSE(entry->is_active()); - EXPECT_EQ(strlen(entry->key), 0u); - EXPECT_EQ(strlen(entry->value), 0u); -} - -TEST(NonAllocatingMapTest, SimpleStringDictionary) { - // Make a new dictionary - SimpleStringDictionary dict; - - // Set three distinct values on three keys - dict.SetKeyValue("key1", "value1"); - dict.SetKeyValue("key2", "value2"); - dict.SetKeyValue("key3", "value3"); - - EXPECT_NE(dict.GetValueForKey("key1"), "value1"); - EXPECT_NE(dict.GetValueForKey("key2"), "value2"); - EXPECT_NE(dict.GetValueForKey("key3"), "value3"); - EXPECT_EQ(dict.GetCount(), 3u); - // try an unknown key - EXPECT_FALSE(dict.GetValueForKey("key4")); - - // Remove a key - dict.RemoveKey("key3"); - - // Now make sure it's not there anymore - EXPECT_FALSE(dict.GetValueForKey("key3")); - - // Remove by setting value to NULL - dict.SetKeyValue("key2", NULL); - - // Now make sure it's not there anymore - EXPECT_FALSE(dict.GetValueForKey("key2")); -} - -TEST(NonAllocatingMapTest, CopyAndAssign) { - NonAllocatingMap<10, 10, 10> map; - map.SetKeyValue("one", "a"); - map.SetKeyValue("two", "b"); - map.SetKeyValue("three", "c"); - map.RemoveKey("two"); - EXPECT_EQ(2u, map.GetCount()); - - // Test copy. - NonAllocatingMap<10, 10, 10> map_copy(map); - EXPECT_EQ(2u, map_copy.GetCount()); - EXPECT_STREQ("a", map_copy.GetValueForKey("one")); - EXPECT_STREQ("c", map_copy.GetValueForKey("three")); - map_copy.SetKeyValue("four", "d"); - EXPECT_STREQ("d", map_copy.GetValueForKey("four")); - EXPECT_FALSE(map.GetValueForKey("four")); - - // Test assign. - NonAllocatingMap<10, 10, 10> map_assign; - map_assign = map; - EXPECT_EQ(2u, map_assign.GetCount()); - EXPECT_STREQ("a", map_assign.GetValueForKey("one")); - EXPECT_STREQ("c", map_assign.GetValueForKey("three")); - map_assign.SetKeyValue("four", "d"); - EXPECT_STREQ("d", map_assign.GetValueForKey("four")); - EXPECT_FALSE(map.GetValueForKey("four")); - - map.RemoveKey("one"); - EXPECT_FALSE(map.GetValueForKey("one")); - EXPECT_STREQ("a", map_copy.GetValueForKey("one")); - EXPECT_STREQ("a", map_assign.GetValueForKey("one")); -} - -// Add a bunch of values to the dictionary, remove some entries in the middle, -// and then add more. -TEST(NonAllocatingMapTest, Iterator) { - SimpleStringDictionary* dict = new SimpleStringDictionary(); - ASSERT_TRUE(dict); - - char key[SimpleStringDictionary::key_size]; - char value[SimpleStringDictionary::value_size]; - - const int kDictionaryCapacity = SimpleStringDictionary::num_entries; - const int kPartitionIndex = kDictionaryCapacity - 5; - - // We assume at least this size in the tests below - ASSERT_GE(kDictionaryCapacity, 64); - - // We'll keep track of the number of key/value pairs we think should - // be in the dictionary - int expectedDictionarySize = 0; - - // Set a bunch of key/value pairs like key0/value0, key1/value1, ... - for (int i = 0; i < kPartitionIndex; ++i) { - sprintf(key, "key%d", i); - sprintf(value, "value%d", i); - dict->SetKeyValue(key, value); - } - expectedDictionarySize = kPartitionIndex; - - // set a couple of the keys twice (with the same value) - should be nop - dict->SetKeyValue("key2", "value2"); - dict->SetKeyValue("key4", "value4"); - dict->SetKeyValue("key15", "value15"); - - // Remove some random elements in the middle - dict->RemoveKey("key7"); - dict->RemoveKey("key18"); - dict->RemoveKey("key23"); - dict->RemoveKey("key31"); - expectedDictionarySize -= 4; // we just removed four key/value pairs - - // Set some more key/value pairs like key59/value59, key60/value60, ... - for (int i = kPartitionIndex; i < kDictionaryCapacity; ++i) { - sprintf(key, "key%d", i); - sprintf(value, "value%d", i); - dict->SetKeyValue(key, value); - } - expectedDictionarySize += kDictionaryCapacity - kPartitionIndex; - - // Now create an iterator on the dictionary - SimpleStringDictionary::Iterator iter(*dict); - - // We then verify that it iterates through exactly the number of - // key/value pairs we expect, and that they match one-for-one with what we - // would expect. The ordering of the iteration does not matter... - - // used to keep track of number of occurrences found for key/value pairs - int count[kDictionaryCapacity]; - memset(count, 0, sizeof(count)); - - int totalCount = 0; - - const SimpleStringDictionary::Entry* entry; - while ((entry = iter.Next())) { - totalCount++; - - // Extract keyNumber from a string of the form key - int keyNumber; - sscanf(entry->key, "key%d", &keyNumber); - - // Extract valueNumber from a string of the form value - int valueNumber; - sscanf(entry->value, "value%d", &valueNumber); - - // The value number should equal the key number since that's how we set them - EXPECT_EQ(keyNumber, valueNumber); - - // Key and value numbers should be in proper range: - // 0 <= keyNumber < kDictionaryCapacity - bool isKeyInGoodRange = - (keyNumber >= 0 && keyNumber < kDictionaryCapacity); - bool isValueInGoodRange = - (valueNumber >= 0 && valueNumber < kDictionaryCapacity); - EXPECT_TRUE(isKeyInGoodRange); - EXPECT_TRUE(isValueInGoodRange); - - if (isKeyInGoodRange && isValueInGoodRange) { - ++count[keyNumber]; - } - } - - // Make sure each of the key/value pairs showed up exactly one time, except - // for the ones which we removed. - for (size_t i = 0; i < kDictionaryCapacity; ++i) { - // Skip over key7, key18, key23, and key31, since we removed them - if (!(i == 7 || i == 18 || i == 23 || i == 31)) { - EXPECT_EQ(count[i], 1); - } - } - - // Make sure the number of iterations matches the expected dictionary size. - EXPECT_EQ(totalCount, expectedDictionarySize); -} - - -TEST(NonAllocatingMapTest, AddRemove) { - NonAllocatingMap<5, 7, 6> map; - map.SetKeyValue("rob", "ert"); - map.SetKeyValue("mike", "pink"); - map.SetKeyValue("mark", "allays"); - - EXPECT_EQ(3u, map.GetCount()); - EXPECT_STREQ("ert", map.GetValueForKey("rob")); - EXPECT_STREQ("pink", map.GetValueForKey("mike")); - EXPECT_STREQ("allays", map.GetValueForKey("mark")); - - map.RemoveKey("mike"); - - EXPECT_EQ(2u, map.GetCount()); - EXPECT_FALSE(map.GetValueForKey("mike")); - - map.SetKeyValue("mark", "mal"); - EXPECT_EQ(2u, map.GetCount()); - EXPECT_STREQ("mal", map.GetValueForKey("mark")); - - map.RemoveKey("mark"); - EXPECT_EQ(1u, map.GetCount()); - EXPECT_FALSE(map.GetValueForKey("mark")); -} - -TEST(NonAllocatingMapTest, Serialize) { - typedef NonAllocatingMap<4, 5, 7> TestMap; - TestMap map; - map.SetKeyValue("one", "abc"); - map.SetKeyValue("two", "def"); - map.SetKeyValue("tre", "hig"); - - EXPECT_STREQ("abc", map.GetValueForKey("one")); - EXPECT_STREQ("def", map.GetValueForKey("two")); - EXPECT_STREQ("hig", map.GetValueForKey("tre")); - - const SerializedNonAllocatingMap* serialized; - size_t size = map.Serialize(&serialized); - - SerializedNonAllocatingMap* serialized_copy = - reinterpret_cast(malloc(size)); - ASSERT_TRUE(serialized_copy); - memcpy(serialized_copy, serialized, size); - - TestMap deserialized(serialized_copy, size); - free(serialized_copy); - - EXPECT_EQ(3u, deserialized.GetCount()); - EXPECT_STREQ("abc", deserialized.GetValueForKey("one")); - EXPECT_STREQ("def", deserialized.GetValueForKey("two")); - EXPECT_STREQ("hig", deserialized.GetValueForKey("tre")); -} - -// Running out of space shouldn't crash. -TEST(NonAllocatingMapTest, OutOfSpace) { - NonAllocatingMap<3, 2, 2> map; - map.SetKeyValue("a", "1"); - map.SetKeyValue("b", "2"); - map.SetKeyValue("c", "3"); - EXPECT_EQ(2u, map.GetCount()); - EXPECT_FALSE(map.GetValueForKey("c")); -} - -#ifndef NDEBUG - -TEST(NonAllocatingMapTest, KeyTooLong) { - NonAllocatingMap<3, 10, 12> map; - map.SetKeyValue("ab", "cdefghi"); - ASSERT_DEATH(map.SetKeyValue("abcdef", "1"), ""); -} - -TEST(NonAllocatingMapTest, ValueTooLong) { - NonAllocatingMap<9, 3, 8> map; - map.SetKeyValue("abcd", "ab"); - ASSERT_DEATH(map.SetKeyValue("abcd", "abc"), ""); -} - -TEST(NonAllocatingMapTest, NullKey) { - NonAllocatingMap<4, 6, 6> map; - ASSERT_DEATH(map.SetKeyValue(NULL, "hello"), ""); - - map.SetKeyValue("hi", "there"); - ASSERT_DEATH(map.GetValueForKey(NULL), ""); - EXPECT_STREQ("there", map.GetValueForKey("hi")); - - ASSERT_DEATH(map.GetValueForKey(NULL), ""); - map.RemoveKey("hi"); - EXPECT_EQ(0u, map.GetCount()); -} - -#endif // !NDEBUG - -} // namespace google_breakpad diff --git a/breakpad/common/stabs_reader.cc b/breakpad/common/stabs_reader.cc deleted file mode 100644 index 6019fc7ee..000000000 --- a/breakpad/common/stabs_reader.cc +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright (c) 2010 Google Inc. All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// This file implements the google_breakpad::StabsReader class. -// See stabs_reader.h. - -#include "common/stabs_reader.h" - -#include -#include -#include - -#include - -#include "common/using_std_string.h" - -using std::vector; - -namespace google_breakpad { - -StabsReader::EntryIterator::EntryIterator(const ByteBuffer *buffer, - bool big_endian, size_t value_size) - : value_size_(value_size), cursor_(buffer, big_endian) { - // Actually, we could handle weird sizes just fine, but they're - // probably mistakes --- expressed in bits, say. - assert(value_size == 4 || value_size == 8); - entry_.index = 0; - Fetch(); -} - -void StabsReader::EntryIterator::Fetch() { - cursor_ - .Read(4, false, &entry_.name_offset) - .Read(1, false, &entry_.type) - .Read(1, false, &entry_.other) - .Read(2, false, &entry_.descriptor) - .Read(value_size_, false, &entry_.value); - entry_.at_end = !cursor_; -} - -StabsReader::StabsReader(const uint8_t *stab, size_t stab_size, - const uint8_t *stabstr, size_t stabstr_size, - bool big_endian, size_t value_size, bool unitized, - StabsHandler *handler) - : entries_(stab, stab_size), - strings_(stabstr, stabstr_size), - iterator_(&entries_, big_endian, value_size), - unitized_(unitized), - handler_(handler), - string_offset_(0), - next_cu_string_offset_(0), - current_source_file_(NULL) { } - -const char *StabsReader::SymbolString() { - ptrdiff_t offset = string_offset_ + iterator_->name_offset; - if (offset < 0 || (size_t) offset >= strings_.Size()) { - handler_->Warning("symbol %d: name offset outside the string section\n", - iterator_->index); - // Return our null string, to keep our promise about all names being - // taken from the string section. - offset = 0; - } - return reinterpret_cast(strings_.start + offset); -} - -bool StabsReader::Process() { - while (!iterator_->at_end) { - if (iterator_->type == N_SO) { - if (! ProcessCompilationUnit()) - return false; - } else if (iterator_->type == N_UNDF && unitized_) { - // In unitized STABS (including Linux STABS, and pretty much anything - // else that puts STABS data in sections), at the head of each - // compilation unit's entries there is an N_UNDF stab giving the - // number of symbols in the compilation unit, and the number of bytes - // that compilation unit's strings take up in the .stabstr section. - // Each CU's strings are separate; the n_strx values are offsets - // within the current CU's portion of the .stabstr section. - // - // As an optimization, the GNU linker combines all the - // compilation units into one, with a single N_UNDF at the - // beginning. However, other linkers, like Gold, do not perform - // this optimization. - string_offset_ = next_cu_string_offset_; - next_cu_string_offset_ = iterator_->value; - ++iterator_; - } -#if defined(HAVE_MACH_O_NLIST_H) - // Export symbols in Mach-O binaries look like this. - // This is necessary in order to be able to dump symbols - // from OS X system libraries. - else if ((iterator_->type & N_STAB) == 0 && - (iterator_->type & N_TYPE) == N_SECT) { - ProcessExtern(); - } -#endif - else { - ++iterator_; - } - } - return true; -} - -bool StabsReader::ProcessCompilationUnit() { - assert(!iterator_->at_end && iterator_->type == N_SO); - - // There may be an N_SO entry whose name ends with a slash, - // indicating the directory in which the compilation occurred. - // The build directory defaults to NULL. - const char *build_directory = NULL; - { - const char *name = SymbolString(); - if (name[0] && name[strlen(name) - 1] == '/') { - build_directory = name; - ++iterator_; - } - } - - // We expect to see an N_SO entry with a filename next, indicating - // the start of the compilation unit. - { - if (iterator_->at_end || iterator_->type != N_SO) - return true; - const char *name = SymbolString(); - if (name[0] == '\0') { - // This seems to be a stray end-of-compilation-unit marker; - // consume it, but don't report the end, since we didn't see a - // beginning. - ++iterator_; - return true; - } - current_source_file_ = name; - } - - if (! handler_->StartCompilationUnit(current_source_file_, - iterator_->value, - build_directory)) - return false; - - ++iterator_; - - // The STABS documentation says that some compilers may emit - // additional N_SO entries with names immediately following the - // first, and that they should be ignored. However, the original - // Breakpad STABS reader doesn't ignore them, so we won't either. - - // Process the body of the compilation unit, up to the next N_SO. - while (!iterator_->at_end && iterator_->type != N_SO) { - if (iterator_->type == N_FUN) { - if (! ProcessFunction()) - return false; - } else if (iterator_->type == N_SLINE) { - // Mac OS X STABS place SLINE records before functions. - Line line; - // The value of an N_SLINE entry that appears outside a function is - // the absolute address of the line. - line.address = iterator_->value; - line.filename = current_source_file_; - // The n_desc of a N_SLINE entry is the line number. It's a - // signed 16-bit field; line numbers from 32768 to 65535 are - // stored as n-65536. - line.number = (uint16_t) iterator_->descriptor; - queued_lines_.push_back(line); - ++iterator_; - } else if (iterator_->type == N_SOL) { - current_source_file_ = SymbolString(); - ++iterator_; - } else { - // Ignore anything else. - ++iterator_; - } - } - - // An N_SO with an empty name indicates the end of the compilation - // unit. Default to zero. - uint64_t ending_address = 0; - if (!iterator_->at_end) { - assert(iterator_->type == N_SO); - const char *name = SymbolString(); - if (name[0] == '\0') { - ending_address = iterator_->value; - ++iterator_; - } - } - - if (! handler_->EndCompilationUnit(ending_address)) - return false; - - queued_lines_.clear(); - - return true; -} - -bool StabsReader::ProcessFunction() { - assert(!iterator_->at_end && iterator_->type == N_FUN); - - uint64_t function_address = iterator_->value; - // The STABS string for an N_FUN entry is the name of the function, - // followed by a colon, followed by type information for the - // function. We want to pass the name alone to StartFunction. - const char *stab_string = SymbolString(); - const char *name_end = strchr(stab_string, ':'); - if (! name_end) - name_end = stab_string + strlen(stab_string); - string name(stab_string, name_end - stab_string); - if (! handler_->StartFunction(name, function_address)) - return false; - ++iterator_; - - // If there were any SLINE records given before the function, report them now. - for (vector::const_iterator it = queued_lines_.begin(); - it != queued_lines_.end(); it++) { - if (!handler_->Line(it->address, it->filename, it->number)) - return false; - } - queued_lines_.clear(); - - while (!iterator_->at_end) { - if (iterator_->type == N_SO || iterator_->type == N_FUN) - break; - else if (iterator_->type == N_SLINE) { - // The value of an N_SLINE entry is the offset of the line from - // the function's start address. - uint64_t line_address = function_address + iterator_->value; - // The n_desc of a N_SLINE entry is the line number. It's a - // signed 16-bit field; line numbers from 32768 to 65535 are - // stored as n-65536. - uint16_t line_number = iterator_->descriptor; - if (! handler_->Line(line_address, current_source_file_, line_number)) - return false; - ++iterator_; - } else if (iterator_->type == N_SOL) { - current_source_file_ = SymbolString(); - ++iterator_; - } else - // Ignore anything else. - ++iterator_; - } - - // We've reached the end of the function. See if we can figure out its - // ending address. - uint64_t ending_address = 0; - if (!iterator_->at_end) { - assert(iterator_->type == N_SO || iterator_->type == N_FUN); - if (iterator_->type == N_FUN) { - const char *symbol_name = SymbolString(); - if (symbol_name[0] == '\0') { - // An N_FUN entry with no name is a terminator for this function; - // its value is the function's size. - ending_address = function_address + iterator_->value; - ++iterator_; - } else { - // An N_FUN entry with a name is the next function, and we can take - // its value as our ending address. Don't advance the iterator, as - // we'll use this symbol to start the next function as well. - ending_address = iterator_->value; - } - } else { - // An N_SO entry could be an end-of-compilation-unit marker, or the - // start of the next compilation unit, but in either case, its value - // is our ending address. We don't advance the iterator; - // ProcessCompilationUnit will decide what to do with this symbol. - ending_address = iterator_->value; - } - } - - if (! handler_->EndFunction(ending_address)) - return false; - - return true; -} - -bool StabsReader::ProcessExtern() { -#if defined(HAVE_MACH_O_NLIST_H) - assert(!iterator_->at_end && - (iterator_->type & N_STAB) == 0 && - (iterator_->type & N_TYPE) == N_SECT); -#endif - - // TODO(mark): only do symbols in the text section? - if (!handler_->Extern(SymbolString(), iterator_->value)) - return false; - - ++iterator_; - return true; -} - -} // namespace google_breakpad diff --git a/breakpad/common/stabs_reader.h b/breakpad/common/stabs_reader.h deleted file mode 100644 index d89afc001..000000000 --- a/breakpad/common/stabs_reader.h +++ /dev/null @@ -1,326 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010 Google Inc. All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// stabs_reader.h: Define StabsReader, a parser for STABS debugging -// information. A description of the STABS debugging format can be -// found at: -// -// http://sourceware.org/gdb/current/onlinedocs/stabs_toc.html -// -// The comments here assume you understand the format. -// -// This parser can handle big-endian and little-endian data, and the symbol -// values may be either 32 or 64 bits long. It handles both STABS in -// sections (as used on Linux) and STABS appearing directly in an -// a.out-like symbol table (as used in Darwin OS X Mach-O files). - -#ifndef COMMON_STABS_READER_H__ -#define COMMON_STABS_READER_H__ - -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_A_OUT_H -#include -#endif -#ifdef HAVE_MACH_O_NLIST_H -#include -#endif - -#include -#include - -#include "common/byte_cursor.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -class StabsHandler; - -class StabsReader { - public: - // Create a reader for the STABS debug information whose .stab section is - // being traversed by ITERATOR, and whose .stabstr section is referred to - // by STRINGS. The reader will call the member functions of HANDLER to - // report the information it finds, when the reader's 'Process' member - // function is called. - // - // BIG_ENDIAN should be true if the entries in the .stab section are in - // big-endian form, or false if they are in little-endian form. - // - // VALUE_SIZE should be either 4 or 8, indicating the size of the 'value' - // field in each entry in bytes. - // - // UNITIZED should be true if the STABS data is stored in units with - // N_UNDF headers. This is usually the case for STABS stored in sections, - // like .stab/.stabstr, and usually not the case for STABS stored in the - // actual symbol table; UNITIZED should be true when parsing Linux stabs, - // false when parsing Mac OS X STABS. For details, see: - // http://sourceware.org/gdb/current/onlinedocs/stabs/Stab-Section-Basics.html - // - // Note that, in ELF, the .stabstr section should be found using the - // 'sh_link' field of the .stab section header, not by name. - StabsReader(const uint8_t *stab, size_t stab_size, - const uint8_t *stabstr, size_t stabstr_size, - bool big_endian, size_t value_size, bool unitized, - StabsHandler *handler); - - // Process the STABS data, calling the handler's member functions to - // report what we find. While the handler functions return true, - // continue to process until we reach the end of the section. If we - // processed the entire section and all handlers returned true, - // return true. If any handler returned false, return false. - // - // This is only meant to be called once per StabsReader instance; - // resuming a prior processing pass that stopped abruptly isn't supported. - bool Process(); - - private: - - // An class for walking arrays of STABS entries. This isolates the main - // STABS reader from the exact format (size; endianness) of the entries - // themselves. - class EntryIterator { - public: - // The contents of a STABS entry, adjusted for the host's endianness, - // word size, 'struct nlist' layout, and so on. - struct Entry { - // True if this iterator has reached the end of the entry array. When - // this is set, the other members of this structure are not valid. - bool at_end; - - // The number of this entry within the list. - size_t index; - - // The current entry's name offset. This is the offset within the - // current compilation unit's strings, as establish by the N_UNDF entries. - size_t name_offset; - - // The current entry's type, 'other' field, descriptor, and value. - unsigned char type; - unsigned char other; - short descriptor; - uint64_t value; - }; - - // Create a EntryIterator walking the entries in BUFFER. Treat the - // entries as big-endian if BIG_ENDIAN is true, as little-endian - // otherwise. Assume each entry has a 'value' field whose size is - // VALUE_SIZE. - // - // This would not be terribly clean to extend to other format variations, - // but it's enough to handle Linux and Mac, and we'd like STABS to die - // anyway. - // - // For the record: on Linux, STABS entry values are always 32 bits, - // regardless of the architecture address size (don't ask me why); on - // Mac, they are 32 or 64 bits long. Oddly, the section header's entry - // size for a Linux ELF .stab section varies according to the ELF class - // from 12 to 20 even as the actual entries remain unchanged. - EntryIterator(const ByteBuffer *buffer, bool big_endian, size_t value_size); - - // Move to the next entry. This function's behavior is undefined if - // at_end() is true when it is called. - EntryIterator &operator++() { Fetch(); entry_.index++; return *this; } - - // Dereferencing this iterator produces a reference to an Entry structure - // that holds the current entry's values. The entry is owned by this - // EntryIterator, and will be invalidated at the next call to operator++. - const Entry &operator*() const { return entry_; } - const Entry *operator->() const { return &entry_; } - - private: - // Read the STABS entry at cursor_, and set entry_ appropriately. - void Fetch(); - - // The size of entries' value field, in bytes. - size_t value_size_; - - // A byte cursor traversing buffer_. - ByteCursor cursor_; - - // Values for the entry this iterator refers to. - Entry entry_; - }; - - // A source line, saved to be reported later. - struct Line { - uint64_t address; - const char *filename; - int number; - }; - - // Return the name of the current symbol. - const char *SymbolString(); - - // Process a compilation unit starting at symbol_. Return true - // to continue processing, or false to abort. - bool ProcessCompilationUnit(); - - // Process a function in current_source_file_ starting at symbol_. - // Return true to continue processing, or false to abort. - bool ProcessFunction(); - - // Process an exported function symbol. - // Return true to continue processing, or false to abort. - bool ProcessExtern(); - - // The STABS entries being parsed. - ByteBuffer entries_; - - // The string section to which the entries refer. - ByteBuffer strings_; - - // The iterator walking the STABS entries. - EntryIterator iterator_; - - // True if the data is "unitized"; see the explanation in the comment for - // StabsReader::StabsReader. - bool unitized_; - - StabsHandler *handler_; - - // The offset of the current compilation unit's strings within stabstr_. - size_t string_offset_; - - // The value string_offset_ should have for the next compilation unit, - // as established by N_UNDF entries. - size_t next_cu_string_offset_; - - // The current source file name. - const char *current_source_file_; - - // Mac OS X STABS place SLINE records before functions; we accumulate a - // vector of these until we see the FUN record, and then report them - // after the StartFunction call. - std::vector queued_lines_; -}; - -// Consumer-provided callback structure for the STABS reader. Clients -// of the STABS reader provide an instance of this structure. The -// reader then invokes the member functions of that instance to report -// the information it finds. -// -// The default definitions of the member functions do nothing, and return -// true so processing will continue. -class StabsHandler { - public: - StabsHandler() { } - virtual ~StabsHandler() { } - - // Some general notes about the handler callback functions: - - // Processing proceeds until the end of the .stabs section, or until - // one of these functions returns false. - - // The addresses given are as reported in the STABS info, without - // regard for whether the module may be loaded at different - // addresses at different times (a shared library, say). When - // processing STABS from an ELF shared library, the addresses given - // all assume the library is loaded at its nominal load address. - // They are *not* offsets from the nominal load address. If you - // want offsets, you must subtract off the library's nominal load - // address. - - // The arguments to these functions named FILENAME are all - // references to strings stored in the .stabstr section. Because - // both the Linux and Solaris linkers factor out duplicate strings - // from the .stabstr section, the consumer can assume that if two - // FILENAME values are different addresses, they represent different - // file names. - // - // Thus, it's safe to use (say) std::map, which does - // string address comparisons, not string content comparisons. - // Since all the strings are in same array of characters --- the - // .stabstr section --- comparing their addresses produces - // predictable, if not lexicographically meaningful, results. - - // Begin processing a compilation unit whose main source file is - // named FILENAME, and whose base address is ADDRESS. If - // BUILD_DIRECTORY is non-NULL, it is the name of the build - // directory in which the compilation occurred. - virtual bool StartCompilationUnit(const char *filename, uint64_t address, - const char *build_directory) { - return true; - } - - // Finish processing the compilation unit. If ADDRESS is non-zero, - // it is the ending address of the compilation unit. If ADDRESS is - // zero, then the compilation unit's ending address is not - // available, and the consumer must infer it by other means. - virtual bool EndCompilationUnit(uint64_t address) { return true; } - - // Begin processing a function named NAME, whose starting address is - // ADDRESS. This function belongs to the compilation unit that was - // most recently started but not ended. - // - // Note that, unlike filenames, NAME is not a pointer into the - // .stabstr section; this is because the name as it appears in the - // STABS data is followed by type information. The value passed to - // StartFunction is the function name alone. - // - // In languages that use name mangling, like C++, NAME is mangled. - virtual bool StartFunction(const string &name, uint64_t address) { - return true; - } - - // Finish processing the function. If ADDRESS is non-zero, it is - // the ending address for the function. If ADDRESS is zero, then - // the function's ending address is not available, and the consumer - // must infer it by other means. - virtual bool EndFunction(uint64_t address) { return true; } - - // Report that the code at ADDRESS is attributable to line NUMBER of - // the source file named FILENAME. The caller must infer the ending - // address of the line. - virtual bool Line(uint64_t address, const char *filename, int number) { - return true; - } - - // Report that an exported function NAME is present at ADDRESS. - // The size of the function is unknown. - virtual bool Extern(const string &name, uint64_t address) { - return true; - } - - // Report a warning. FORMAT is a printf-like format string, - // specifying how to format the subsequent arguments. - virtual void Warning(const char *format, ...) = 0; -}; - -} // namespace google_breakpad - -#endif // COMMON_STABS_READER_H__ diff --git a/breakpad/common/stabs_reader_unittest.cc b/breakpad/common/stabs_reader_unittest.cc deleted file mode 100644 index a84da1c4c..000000000 --- a/breakpad/common/stabs_reader_unittest.cc +++ /dev/null @@ -1,611 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// stabs_reader_unittest.cc: Unit tests for google_breakpad::StabsReader. - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "breakpad_googletest_includes.h" -#include "common/stabs_reader.h" -#include "common/test_assembler.h" -#include "common/using_std_string.h" - -using ::testing::Eq; -using ::testing::InSequence; -using ::testing::Return; -using ::testing::StrEq; -using ::testing::Test; -using ::testing::_; -using google_breakpad::StabsHandler; -using google_breakpad::StabsReader; -using google_breakpad::test_assembler::Label; -using google_breakpad::test_assembler::Section; -using google_breakpad::test_assembler::kBigEndian; -using google_breakpad::test_assembler::kLittleEndian; -using std::map; - -namespace { - -// A StringAssembler is a class for generating .stabstr sections to present -// as input to the STABS parser. -class StringAssembler: public Section { - public: - StringAssembler() : in_cu_(false) { StartCU(); } - - // Add the string S to this StringAssembler, and return the string's - // offset within this compilation unit's strings. If S has been added - // already, this returns the offset of its first instance. - size_t Add(const string &s) { - map::iterator it = added_.find(s); - if (it != added_.end()) - return it->second; - size_t offset = Size() - cu_start_; - AppendCString(s); - added_[s] = offset; - return offset; - } - - // Start a fresh compilation unit string collection. - void StartCU() { - // Ignore duplicate calls to StartCU. Our test data don't always call - // StartCU at all, meaning that our constructor has to take care of it, - // meaning that tests that *do* call StartCU call it twice at the - // beginning. This is not worth smoothing out. - if (in_cu_) return; - - added_.clear(); - cu_start_ = Size(); - - // Each compilation unit's strings start with an empty string. - AppendCString(""); - added_[""] = 0; - - in_cu_ = true; - } - - // Finish off the current CU's strings. - size_t EndCU() { - assert(in_cu_); - in_cu_ = false; - return Size() - cu_start_; - } - - private: - // The offset of the start of this compilation unit's strings. - size_t cu_start_; - - // True if we're in a CU. - bool in_cu_; - - // A map from the strings that have been added to this section to - // their starting indices within their compilation unit. - map added_; -}; - -// A StabsAssembler is a class for generating .stab sections to present as -// test input for the STABS parser. -class StabsAssembler: public Section { - public: - // Create a StabsAssembler that uses StringAssembler for its strings. - StabsAssembler(StringAssembler *string_assembler) - : Section(string_assembler->endianness()), - string_assembler_(string_assembler), - value_size_(0), - entry_count_(0), - cu_header_(NULL) { } - ~StabsAssembler() { assert(!cu_header_); } - - // Accessor and setter for value_size_. - size_t value_size() const { return value_size_; } - StabsAssembler &set_value_size(size_t value_size) { - value_size_ = value_size; - return *this; - } - - // Append a STAB entry to the end of this section with the given - // characteristics. NAME is the offset of this entry's name string within - // its compilation unit's portion of the .stabstr section; this can be a - // value generated by a StringAssembler. Return a reference to this - // StabsAssembler. - StabsAssembler &Stab(uint8_t type, uint8_t other, Label descriptor, - Label value, Label name) { - D32(name); - D8(type); - D8(other); - D16(descriptor); - Append(endianness(), value_size_, value); - entry_count_++; - return *this; - } - - // As above, but automatically add NAME to our StringAssembler. - StabsAssembler &Stab(uint8_t type, uint8_t other, Label descriptor, - Label value, const string &name) { - return Stab(type, other, descriptor, value, string_assembler_->Add(name)); - } - - // Start a compilation unit named NAME, with an N_UNDF symbol to start - // it, and its own portion of the string section. Return a reference to - // this StabsAssembler. - StabsAssembler &StartCU(const string &name) { - assert(!cu_header_); - cu_header_ = new CUHeader; - string_assembler_->StartCU(); - entry_count_ = 0; - return Stab(N_UNDF, 0, - cu_header_->final_entry_count, - cu_header_->final_string_size, - string_assembler_->Add(name)); - } - - // Close off the current compilation unit. Return a reference to this - // StabsAssembler. - StabsAssembler &EndCU() { - assert(cu_header_); - cu_header_->final_entry_count = entry_count_; - cu_header_->final_string_size = string_assembler_->EndCU(); - delete cu_header_; - cu_header_ = NULL; - return *this; - } - - private: - // Data used in a compilation unit header STAB that we won't know until - // we've finished the compilation unit. - struct CUHeader { - // The final number of entries this compilation unit will hold. - Label final_entry_count; - - // The final size of this compilation unit's strings. - Label final_string_size; - }; - - // The strings for our STABS entries. - StringAssembler *string_assembler_; - - // The size of the 'value' field of stabs entries in this section. - size_t value_size_; - - // The number of entries in this compilation unit so far. - size_t entry_count_; - - // Header labels for this compilation unit, if we've started one but not - // finished it. - CUHeader *cu_header_; -}; - -class MockStabsReaderHandler: public StabsHandler { - public: - MOCK_METHOD3(StartCompilationUnit, - bool(const char *, uint64_t, const char *)); - MOCK_METHOD1(EndCompilationUnit, bool(uint64_t)); - MOCK_METHOD2(StartFunction, bool(const string &, uint64_t)); - MOCK_METHOD1(EndFunction, bool(uint64_t)); - MOCK_METHOD3(Line, bool(uint64_t, const char *, int)); - MOCK_METHOD2(Extern, bool(const string &, uint64_t)); - void Warning(const char *format, ...) { MockWarning(format); } - MOCK_METHOD1(MockWarning, void(const char *)); -}; - -struct StabsFixture { - StabsFixture() : stabs(&strings), unitized(true) { } - - // Create a StabsReader to parse the mock stabs data in stabs and - // strings, and pass the parsed information to mock_handler. Use the - // endianness and value size of stabs to parse the data. If all goes - // well, return the result of calling the reader's Process member - // function. Otherwise, return false. - bool ApplyHandlerToMockStabsData() { - string stabs_contents, stabstr_contents; - if (!stabs.GetContents(&stabs_contents) || - !strings.GetContents(&stabstr_contents)) - return false; - - // Run the parser on the test input, passing whatever we find to HANDLER. - StabsReader reader( - reinterpret_cast(stabs_contents.data()), - stabs_contents.size(), - reinterpret_cast(stabstr_contents.data()), - stabstr_contents.size(), - stabs.endianness() == kBigEndian, stabs.value_size(), unitized, - &mock_handler); - return reader.Process(); - } - - StringAssembler strings; - StabsAssembler stabs; - bool unitized; - MockStabsReaderHandler mock_handler; -}; - -class Stabs: public StabsFixture, public Test { }; - -TEST_F(Stabs, MockStabsInput) { - stabs.set_endianness(kLittleEndian); - stabs.set_value_size(4); - stabs - .Stab(N_SO, 149, 40232, 0x18a2a72bU, "builddir/") - .Stab(N_FUN, 83, 50010, 0x91a5353fU, - "not the SO with source file name we expected ") - .Stab(N_SO, 165, 24791, 0xfe69d23cU, "") - .Stab(N_SO, 184, 34178, 0xca4d883aU, "builddir1/") - .Stab(N_SO, 83, 40859, 0xd2fe5df3U, "file1.c") - .Stab(N_LSYM, 147, 39565, 0x60d4bb8aU, "not the FUN we're looking for") - .Stab(N_FUN, 120, 50271, 0xa049f4b1U, "fun1") - .Stab(N_BINCL, 150, 15694, 0xef65c659U, - "something to ignore in a FUN body") - .Stab(N_SLINE, 147, 4967, 0xd904b3f, "") - .Stab(N_SOL, 177, 56135, 0xbd97b1dcU, "header.h") - .Stab(N_SLINE, 130, 24610, 0x90f145b, "") - .Stab(N_FUN, 45, 32441, 0xbf27cf93U, - "fun2:some stabs type info here:to trim from the name") - .Stab(N_SLINE, 138, 39002, 0x8148b87, "") - .Stab(N_SOL, 60, 49318, 0x1d06e025U, "file1.c") - .Stab(N_SLINE, 29, 52163, 0x6eebbb7, "") - .Stab(N_SO, 167, 4647, 0xd04b7448U, "") - .Stab(N_LSYM, 58, 37837, 0xe6b14d37U, "") - .Stab(N_SO, 152, 7810, 0x11759f10U, "file3.c") - .Stab(N_SO, 218, 12447, 0x11cfe4b5U, ""); - - { - InSequence s; - - EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("file1.c"), 0xd2fe5df3U, - StrEq("builddir1/"))) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, StartFunction(StrEq("fun1"), 0xa049f4b1U)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - Line(0xa049f4b1U + 0xd904b3f, StrEq("file1.c"), 4967)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - Line(0xa049f4b1U + 0x90f145b, StrEq("header.h"), 24610)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndFunction(0xbf27cf93U)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, StartFunction(StrEq("fun2"), 0xbf27cf93U)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - Line(0xbf27cf93U + 0x8148b87, StrEq("header.h"), 39002)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - Line(0xbf27cf93U + 0x6eebbb7, StrEq("file1.c"), 52163)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndFunction(0xd04b7448U)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndCompilationUnit(0xd04b7448U)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, StartCompilationUnit(StrEq("file3.c"), - 0x11759f10U, NULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndCompilationUnit(0x11cfe4b5U)) - .WillOnce(Return(true)); - } - - ASSERT_TRUE(ApplyHandlerToMockStabsData()); -} - -TEST_F(Stabs, AbruptCU) { - stabs.set_endianness(kBigEndian); - stabs.set_value_size(4); - stabs.Stab(N_SO, 177, 23446, 0xbf10d5e4, "file2-1.c"); - - { - InSequence s; - - EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("file2-1.c"), 0xbf10d5e4, NULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndCompilationUnit(0)) - .WillOnce(Return(true)); - } - - ASSERT_TRUE(ApplyHandlerToMockStabsData()); -} - -TEST_F(Stabs, AbruptFunction) { - stabs.set_endianness(kLittleEndian); - stabs.set_value_size(8); - stabs - .Stab(N_SO, 218, 26631, 0xb83ddf10U, "file3-1.c") - .Stab(N_FUN, 113, 24765, 0xbbd4a145U, "fun3_1"); - - { - InSequence s; - - EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("file3-1.c"), 0xb83ddf10U, NULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, StartFunction(StrEq("fun3_1"), 0xbbd4a145U)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndFunction(0)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndCompilationUnit(0)) - .WillOnce(Return(true)); - } - - ASSERT_TRUE(ApplyHandlerToMockStabsData()); -} - -TEST_F(Stabs, NoCU) { - stabs.set_endianness(kBigEndian); - stabs.set_value_size(8); - stabs.Stab(N_SO, 161, 25673, 0x8f676e7bU, "build-directory/"); - - EXPECT_CALL(mock_handler, StartCompilationUnit(_, _, _)) - .Times(0); - EXPECT_CALL(mock_handler, StartFunction(_, _)) - .Times(0); - - ASSERT_TRUE(ApplyHandlerToMockStabsData()); -} - -TEST_F(Stabs, NoCUEnd) { - stabs.set_endianness(kBigEndian); - stabs.set_value_size(8); - stabs - .Stab(N_SO, 116, 58280, 0x2f7493c9U, "file5-1.c") - .Stab(N_SO, 224, 23057, 0xf9f1d50fU, "file5-2.c"); - - { - InSequence s; - - EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("file5-1.c"), 0x2f7493c9U, NULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndCompilationUnit(0)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("file5-2.c"), 0xf9f1d50fU, NULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndCompilationUnit(0)) - .WillOnce(Return(true)); - } - - ASSERT_TRUE(ApplyHandlerToMockStabsData()); -} - -// On systems that store STABS in sections, string offsets are relative to -// the beginning of that compilation unit's strings, marked with N_UNDF -// symbols; see the comments for StabsReader::StabsReader. -TEST_F(Stabs, Unitized) { - stabs.set_endianness(kBigEndian); - stabs.set_value_size(4); - stabs - .StartCU("antimony") - .Stab(N_SO, 49, 26043, 0x7e259f1aU, "antimony") - .Stab(N_FUN, 101, 63253, 0x7fbcccaeU, "arsenic") - .Stab(N_SO, 124, 37175, 0x80b0014cU, "") - .EndCU() - .StartCU("aluminum") - .Stab(N_SO, 72, 23084, 0x86756839U, "aluminum") - .Stab(N_FUN, 59, 3305, 0xa8e120b0U, "selenium") - .Stab(N_SO, 178, 56949, 0xbffff983U, "") - .EndCU(); - - { - InSequence s; - EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("antimony"), 0x7e259f1aU, NULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, StartFunction(Eq("arsenic"), 0x7fbcccaeU)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndFunction(0x80b0014cU)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndCompilationUnit(0x80b0014cU)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("aluminum"), 0x86756839U, NULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, StartFunction(Eq("selenium"), 0xa8e120b0U)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndFunction(0xbffff983U)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndCompilationUnit(0xbffff983U)) - .WillOnce(Return(true)); - } - - ASSERT_TRUE(ApplyHandlerToMockStabsData()); -} - -// On systems that store STABS entries in the real symbol table, the N_UNDF -// entries have no special meaning, and shouldn't mess up the string -// indices. -TEST_F(Stabs, NonUnitized) { - stabs.set_endianness(kLittleEndian); - stabs.set_value_size(4); - unitized = false; - stabs - .Stab(N_UNDF, 21, 11551, 0x9bad2b2e, "") - .Stab(N_UNDF, 21, 11551, 0x9bad2b2e, "") - .Stab(N_SO, 71, 45139, 0x11a97352, "Tanzania") - .Stab(N_SO, 221, 41976, 0x21a97352, ""); - - { - InSequence s; - EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("Tanzania"), - 0x11a97352, NULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndCompilationUnit(0x21a97352)) - .WillOnce(Return(true)); - } - - ASSERT_TRUE(ApplyHandlerToMockStabsData()); -} - -TEST_F(Stabs, FunctionEnd) { - stabs.set_endianness(kLittleEndian); - stabs.set_value_size(8); - stabs - .Stab(N_SO, 102, 62362, 0x52a830d644cd6942ULL, "compilation unit") - // This function is terminated by the start of the next function. - .Stab(N_FUN, 216, 38405, 0xbb5ab70ecdd23bfeULL, "function 1") - // This function is terminated by an explicit end-of-function stab, - // whose value is a size in bytes. - .Stab(N_FUN, 240, 10973, 0xc954de9b8fb3e5e2ULL, "function 2") - .Stab(N_FUN, 14, 36749, 0xc1ab, "") - // This function is terminated by the end of the compilation unit. - .Stab(N_FUN, 143, 64514, 0xdff98c9a35386e1fULL, "function 3") - .Stab(N_SO, 164, 60142, 0xfdacb856e78bbf57ULL, ""); - - { - InSequence s; - EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("compilation unit"), - 0x52a830d644cd6942ULL, NULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - StartFunction(Eq("function 1"), 0xbb5ab70ecdd23bfeULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndFunction(0xc954de9b8fb3e5e2ULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - StartFunction(Eq("function 2"), 0xc954de9b8fb3e5e2ULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndFunction(0xc954de9b8fb3e5e2ULL + 0xc1ab)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - StartFunction(Eq("function 3"), 0xdff98c9a35386e1fULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndFunction(0xfdacb856e78bbf57ULL)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndCompilationUnit(0xfdacb856e78bbf57ULL)) - .WillOnce(Return(true)); - } - - ASSERT_TRUE(ApplyHandlerToMockStabsData()); -} - -// On Mac OS X, SLINE records can appear before the FUN stab to which they -// belong, and their values are absolute addresses, not offsets. -TEST_F(Stabs, LeadingLine) { - stabs.set_endianness(kBigEndian); - stabs.set_value_size(4); - stabs - .Stab(N_SO, 179, 27357, 0x8adabc15, "build directory/") - .Stab(N_SO, 52, 53058, 0x4c7e3bf4, "compilation unit") - .Stab(N_SOL, 165, 12086, 0x6a797ca3, "source file name") - .Stab(N_SLINE, 229, 20015, 0x4cb3d7e0, "") - .Stab(N_SLINE, 89, 43802, 0x4cba8b88, "") - .Stab(N_FUN, 251, 51639, 0xce1b98fa, "rutabaga") - .Stab(N_FUN, 218, 16113, 0x5798, "") - .Stab(N_SO, 52, 53058, 0xd4af4415, ""); - - { - InSequence s; - EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("compilation unit"), - 0x4c7e3bf4, StrEq("build directory/"))) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - StartFunction(Eq("rutabaga"), 0xce1b98fa)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - Line(0x4cb3d7e0, StrEq("source file name"), 20015)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - Line(0x4cba8b88, StrEq("source file name"), 43802)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndFunction(0xce1b98fa + 0x5798)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, EndCompilationUnit(0xd4af4415)) - .WillOnce(Return(true)); - } - - ASSERT_TRUE(ApplyHandlerToMockStabsData()); -} - - -#if defined(HAVE_MACH_O_NLIST_H) -// These tests have no meaning on non-Mach-O-based systems, as -// only Mach-O uses N_SECT to represent public symbols. -TEST_F(Stabs, OnePublicSymbol) { - stabs.set_endianness(kLittleEndian); - stabs.set_value_size(4); - - const uint32_t kExpectedAddress = 0x9000; - const string kExpectedFunctionName("public_function"); - stabs - .Stab(N_SECT, 1, 0, kExpectedAddress, kExpectedFunctionName); - - { - InSequence s; - EXPECT_CALL(mock_handler, - Extern(StrEq(kExpectedFunctionName), - kExpectedAddress)) - .WillOnce(Return(true)); - } - ASSERT_TRUE(ApplyHandlerToMockStabsData()); -} - -TEST_F(Stabs, TwoPublicSymbols) { - stabs.set_endianness(kLittleEndian); - stabs.set_value_size(4); - - const uint32_t kExpectedAddress1 = 0xB0B0B0B0; - const string kExpectedFunctionName1("public_function"); - const uint32_t kExpectedAddress2 = 0xF0F0F0F0; - const string kExpectedFunctionName2("something else"); - stabs - .Stab(N_SECT, 1, 0, kExpectedAddress1, kExpectedFunctionName1) - .Stab(N_SECT, 1, 0, kExpectedAddress2, kExpectedFunctionName2); - - { - InSequence s; - EXPECT_CALL(mock_handler, - Extern(StrEq(kExpectedFunctionName1), - kExpectedAddress1)) - .WillOnce(Return(true)); - EXPECT_CALL(mock_handler, - Extern(StrEq(kExpectedFunctionName2), - kExpectedAddress2)) - .WillOnce(Return(true)); - } - ASSERT_TRUE(ApplyHandlerToMockStabsData()); -} - -#endif - -} // anonymous namespace diff --git a/breakpad/common/stabs_to_module.cc b/breakpad/common/stabs_to_module.cc deleted file mode 100644 index e59aebdba..000000000 --- a/breakpad/common/stabs_to_module.cc +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// dump_stabs.cc --- implement the StabsToModule class. - -#include -#include -#include -#include - -#include - -#include "common/stabs_to_module.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -// Demangle using abi call. -// Older GCC may not support it. -static string Demangle(const string &mangled) { - int status = 0; - char *demangled = abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status); - if (status == 0 && demangled != NULL) { - string str(demangled); - free(demangled); - return str; - } - return string(mangled); -} - -StabsToModule::~StabsToModule() { - // Free any functions we've accumulated but not added to the module. - for (vector::const_iterator func_it = functions_.begin(); - func_it != functions_.end(); func_it++) - delete *func_it; - // Free any function that we're currently within. - delete current_function_; -} - -bool StabsToModule::StartCompilationUnit(const char *name, uint64_t address, - const char *build_directory) { - assert(!in_compilation_unit_); - in_compilation_unit_ = true; - current_source_file_name_ = name; - current_source_file_ = module_->FindFile(name); - comp_unit_base_address_ = address; - boundaries_.push_back(static_cast(address)); - return true; -} - -bool StabsToModule::EndCompilationUnit(uint64_t address) { - assert(in_compilation_unit_); - in_compilation_unit_ = false; - comp_unit_base_address_ = 0; - current_source_file_ = NULL; - current_source_file_name_ = NULL; - if (address) - boundaries_.push_back(static_cast(address)); - return true; -} - -bool StabsToModule::StartFunction(const string &name, - uint64_t address) { - assert(!current_function_); - Module::Function *f = new Module::Function; - f->name = Demangle(name); - f->address = address; - f->size = 0; // We compute this in StabsToModule::Finalize(). - f->parameter_size = 0; // We don't provide this information. - current_function_ = f; - boundaries_.push_back(static_cast(address)); - return true; -} - -bool StabsToModule::EndFunction(uint64_t address) { - assert(current_function_); - // Functions in this compilation unit should have address bigger - // than the compilation unit's starting address. There may be a lot - // of duplicated entries for functions in the STABS data. We will - // count on the Module to remove the duplicates. - if (current_function_->address >= comp_unit_base_address_) - functions_.push_back(current_function_); - else - delete current_function_; - current_function_ = NULL; - if (address) - boundaries_.push_back(static_cast(address)); - return true; -} - -bool StabsToModule::Line(uint64_t address, const char *name, int number) { - assert(current_function_); - assert(current_source_file_); - if (name != current_source_file_name_) { - current_source_file_ = module_->FindFile(name); - current_source_file_name_ = name; - } - Module::Line line; - line.address = address; - line.size = 0; // We compute this in StabsToModule::Finalize(). - line.file = current_source_file_; - line.number = number; - current_function_->lines.push_back(line); - return true; -} - -bool StabsToModule::Extern(const string &name, uint64_t address) { - Module::Extern *ext = new Module::Extern; - // Older libstdc++ demangle implementations can crash on unexpected - // input, so be careful about what gets passed in. - if (name.compare(0, 3, "__Z") == 0) { - ext->name = Demangle(name.substr(1)); - } else if (name[0] == '_') { - ext->name = name.substr(1); - } else { - ext->name = name; - } - ext->address = address; - module_->AddExtern(ext); - return true; -} - -void StabsToModule::Warning(const char *format, ...) { - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); -} - -void StabsToModule::Finalize() { - // Sort our boundary list, so we can search it quickly. - sort(boundaries_.begin(), boundaries_.end()); - // Sort all functions by address, just for neatness. - sort(functions_.begin(), functions_.end(), - Module::Function::CompareByAddress); - - for (vector::const_iterator func_it = functions_.begin(); - func_it != functions_.end(); - func_it++) { - Module::Function *f = *func_it; - // Compute the function f's size. - vector::const_iterator boundary - = std::upper_bound(boundaries_.begin(), boundaries_.end(), f->address); - if (boundary != boundaries_.end()) - f->size = *boundary - f->address; - else - // If this is the last function in the module, and the STABS - // reader was unable to give us its ending address, then assign - // it a bogus, very large value. This will happen at most once - // per module: since we've added all functions' addresses to the - // boundary table, only one can be the last. - f->size = kFallbackSize; - - // Compute sizes for each of the function f's lines --- if it has any. - if (!f->lines.empty()) { - stable_sort(f->lines.begin(), f->lines.end(), - Module::Line::CompareByAddress); - vector::iterator last_line = f->lines.end() - 1; - for (vector::iterator line_it = f->lines.begin(); - line_it != last_line; line_it++) - line_it[0].size = line_it[1].address - line_it[0].address; - // Compute the size of the last line from f's end address. - last_line->size = (f->address + f->size) - last_line->address; - } - } - // Now that everything has a size, add our functions to the module, and - // dispose of our private list. - module_->AddFunctions(functions_.begin(), functions_.end()); - functions_.clear(); -} - -} // namespace google_breakpad diff --git a/breakpad/common/stabs_to_module.h b/breakpad/common/stabs_to_module.h deleted file mode 100644 index 5e04fa792..000000000 --- a/breakpad/common/stabs_to_module.h +++ /dev/null @@ -1,143 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// dump_stabs.h: Define the StabsToModule class, which receives -// STABS debugging information from a parser and adds it to a Breakpad -// symbol file. - -#ifndef BREAKPAD_COMMON_STABS_TO_MODULE_H_ -#define BREAKPAD_COMMON_STABS_TO_MODULE_H_ - -#include - -#include -#include - -#include "common/module.h" -#include "common/stabs_reader.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -using std::vector; - -// A StabsToModule is a handler that receives parsed STABS debugging -// information from a StabsReader, and uses that to populate -// a Module. (All classes are in the google_breakpad namespace.) A -// Module represents the contents of a Breakpad symbol file, and knows -// how to write itself out as such. A StabsToModule thus acts as -// the bridge between STABS and Breakpad data. -// When processing Darwin Mach-O files, this also receives public linker -// symbols, like those found in system libraries. -class StabsToModule: public google_breakpad::StabsHandler { - public: - // Receive parsed debugging information from a StabsReader, and - // store it all in MODULE. - StabsToModule(Module *module) : - module_(module), - in_compilation_unit_(false), - comp_unit_base_address_(0), - current_function_(NULL), - current_source_file_(NULL), - current_source_file_name_(NULL) { } - ~StabsToModule(); - - // The standard StabsHandler virtual member functions. - bool StartCompilationUnit(const char *name, uint64_t address, - const char *build_directory); - bool EndCompilationUnit(uint64_t address); - bool StartFunction(const string &name, uint64_t address); - bool EndFunction(uint64_t address); - bool Line(uint64_t address, const char *name, int number); - bool Extern(const string &name, uint64_t address); - void Warning(const char *format, ...); - - // Do any final processing necessary to make module_ contain all the - // data provided by the STABS reader. - // - // Because STABS does not provide reliable size information for - // functions and lines, we need to make a pass over the data after - // processing all the STABS to compute those sizes. We take care of - // that here. - void Finalize(); - - private: - - // An arbitrary, but very large, size to use for functions whose - // size we can't compute properly. - static const uint64_t kFallbackSize = 0x10000000; - - // The module we're contributing debugging info to. - Module *module_; - - // The functions we've generated so far. We don't add these to - // module_ as we parse them. Instead, we wait until we've computed - // their ending address, and their lines' ending addresses. - // - // We could just stick them in module_ from the outset, but if - // module_ already contains data gathered from other debugging - // formats, that would complicate the size computation. - vector functions_; - - // Boundary addresses. STABS doesn't necessarily supply sizes for - // functions and lines, so we need to compute them ourselves by - // finding the next object. - vector boundaries_; - - // True if we are currently within a compilation unit: we have gotten a - // StartCompilationUnit call, but no matching EndCompilationUnit call - // yet. We use this for sanity checks. - bool in_compilation_unit_; - - // The base address of the current compilation unit. We use this to - // recognize functions we should omit from the symbol file. (If you - // know the details of why we omit these, please patch this - // comment.) - Module::Address comp_unit_base_address_; - - // The function we're currently contributing lines to. - Module::Function *current_function_; - - // The last Module::File we got a line number in. - Module::File *current_source_file_; - - // The pointer in the .stabstr section of the name that - // current_source_file_ is built from. This allows us to quickly - // recognize when the current line is in the same file as the - // previous one (which it usually is). - const char *current_source_file_name_; -}; - -} // namespace google_breakpad - -#endif // BREAKPAD_COMMON_STABS_TO_MODULE_H_ diff --git a/breakpad/common/stabs_to_module_unittest.cc b/breakpad/common/stabs_to_module_unittest.cc deleted file mode 100644 index d445d1d64..000000000 --- a/breakpad/common/stabs_to_module_unittest.cc +++ /dev/null @@ -1,258 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// dump_stabs_unittest.cc: Unit tests for StabsToModule. - -#include - -#include "breakpad_googletest_includes.h" -#include "common/stabs_to_module.h" - -using google_breakpad::Module; -using google_breakpad::StabsToModule; -using std::vector; - -TEST(StabsToModule, SimpleCU) { - Module m("name", "os", "arch", "id"); - StabsToModule h(&m); - - // Feed in a simple compilation unit that defines a function with - // one line. - EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0x9f4d1271e50db93bLL, - "build-directory")); - EXPECT_TRUE(h.StartFunction("function", 0xfde4abbed390c394LL)); - EXPECT_TRUE(h.Line(0xfde4abbed390c394LL, "source-file-name", 174823314)); - EXPECT_TRUE(h.EndFunction(0xfde4abbed390c3a4LL)); - EXPECT_TRUE(h.EndCompilationUnit(0xfee4abbed390c3a4LL)); - h.Finalize(); - - // Now check to see what has been added to the Module. - Module::File *file = m.FindExistingFile("source-file-name"); - ASSERT_TRUE(file != NULL); - - vector functions; - m.GetFunctions(&functions, functions.end()); - ASSERT_EQ((size_t) 1, functions.size()); - Module::Function *function = functions[0]; - EXPECT_STREQ("function", function->name.c_str()); - EXPECT_EQ(0xfde4abbed390c394LL, function->address); - EXPECT_EQ(0x10U, function->size); - EXPECT_EQ(0U, function->parameter_size); - ASSERT_EQ((size_t) 1, function->lines.size()); - Module::Line *line = &function->lines[0]; - EXPECT_EQ(0xfde4abbed390c394LL, line->address); - EXPECT_EQ(0x10U, line->size); // derived from EndFunction - EXPECT_TRUE(line->file == file); - EXPECT_EQ(174823314, line->number); -} - -#ifdef __GNUC__ -// Function name mangling can vary by compiler, so only run mangled-name -// tests on GCC for simplicity's sake. -TEST(StabsToModule, Externs) { - Module m("name", "os", "arch", "id"); - StabsToModule h(&m); - - // Feed in a few Extern symbols. - EXPECT_TRUE(h.Extern("_foo", 0xffff)); - EXPECT_TRUE(h.Extern("__Z21dyldGlobalLockAcquirev", 0xaaaa)); - EXPECT_TRUE(h.Extern("_MorphTableGetNextMorphChain", 0x1111)); - h.Finalize(); - - // Now check to see what has been added to the Module. - vector externs; - m.GetExterns(&externs, externs.end()); - ASSERT_EQ((size_t) 3, externs.size()); - Module::Extern *extern1 = externs[0]; - EXPECT_STREQ("MorphTableGetNextMorphChain", extern1->name.c_str()); - EXPECT_EQ((Module::Address)0x1111, extern1->address); - Module::Extern *extern2 = externs[1]; - EXPECT_STREQ("dyldGlobalLockAcquire()", extern2->name.c_str()); - EXPECT_EQ((Module::Address)0xaaaa, extern2->address); - Module::Extern *extern3 = externs[2]; - EXPECT_STREQ("foo", extern3->name.c_str()); - EXPECT_EQ((Module::Address)0xffff, extern3->address); -} -#endif // __GNUC__ - -TEST(StabsToModule, DuplicateFunctionNames) { - Module m("name", "os", "arch", "id"); - StabsToModule h(&m); - - // Compilation unit with one function, mangled name. - EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0xf2cfda36ecf7f46cLL, - "build-directory")); - EXPECT_TRUE(h.StartFunction("funcfoo", - 0xf2cfda36ecf7f46dLL)); - EXPECT_TRUE(h.EndFunction(0)); - EXPECT_TRUE(h.StartFunction("funcfoo", - 0xf2cfda36ecf7f46dLL)); - EXPECT_TRUE(h.EndFunction(0)); - EXPECT_TRUE(h.EndCompilationUnit(0)); - - h.Finalize(); - - // Now check to see what has been added to the Module. - Module::File *file = m.FindExistingFile("compilation-unit"); - ASSERT_TRUE(file != NULL); - - vector functions; - m.GetFunctions(&functions, functions.end()); - ASSERT_EQ(1U, functions.size()); - - Module::Function *function = functions[0]; - EXPECT_EQ(0xf2cfda36ecf7f46dLL, function->address); - EXPECT_LT(0U, function->size); // should have used dummy size - EXPECT_EQ(0U, function->parameter_size); - ASSERT_EQ(0U, function->lines.size()); -} - -TEST(InferSizes, LineSize) { - Module m("name", "os", "arch", "id"); - StabsToModule h(&m); - - // Feed in a simple compilation unit that defines a function with - // one line. - EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0xb4513962eff94e92LL, - "build-directory")); - EXPECT_TRUE(h.StartFunction("function", 0xb4513962eff94e92LL)); - EXPECT_TRUE(h.Line(0xb4513962eff94e92LL, "source-file-name-1", 77396614)); - EXPECT_TRUE(h.Line(0xb4513963eff94e92LL, "source-file-name-2", 87660088)); - EXPECT_TRUE(h.EndFunction(0)); // unknown function end address - EXPECT_TRUE(h.EndCompilationUnit(0)); // unknown CU end address - EXPECT_TRUE(h.StartCompilationUnit("compilation-unit-2", 0xb4523963eff94e92LL, - "build-directory-2")); // next boundary - EXPECT_TRUE(h.EndCompilationUnit(0)); - h.Finalize(); - - // Now check to see what has been added to the Module. - Module::File *file1 = m.FindExistingFile("source-file-name-1"); - ASSERT_TRUE(file1 != NULL); - Module::File *file2 = m.FindExistingFile("source-file-name-2"); - ASSERT_TRUE(file2 != NULL); - - vector functions; - m.GetFunctions(&functions, functions.end()); - ASSERT_EQ((size_t) 1, functions.size()); - - Module::Function *function = functions[0]; - EXPECT_STREQ("function", function->name.c_str()); - EXPECT_EQ(0xb4513962eff94e92LL, function->address); - EXPECT_EQ(0x1000100000000ULL, function->size); // inferred from CU end - EXPECT_EQ(0U, function->parameter_size); - ASSERT_EQ((size_t) 2, function->lines.size()); - - Module::Line *line1 = &function->lines[0]; - EXPECT_EQ(0xb4513962eff94e92LL, line1->address); - EXPECT_EQ(0x100000000ULL, line1->size); // derived from EndFunction - EXPECT_TRUE(line1->file == file1); - EXPECT_EQ(77396614, line1->number); - - Module::Line *line2 = &function->lines[1]; - EXPECT_EQ(0xb4513963eff94e92LL, line2->address); - EXPECT_EQ(0x1000000000000ULL, line2->size); // derived from EndFunction - EXPECT_TRUE(line2->file == file2); - EXPECT_EQ(87660088, line2->number); -} - -#ifdef __GNUC__ -// Function name mangling can vary by compiler, so only run mangled-name -// tests on GCC for simplicity's sake. -TEST(FunctionNames, Mangled) { - Module m("name", "os", "arch", "id"); - StabsToModule h(&m); - - // Compilation unit with one function, mangled name. - EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0xf2cfda63cef7f46cLL, - "build-directory")); - EXPECT_TRUE(h.StartFunction("_ZNSt6vectorIySaIyEE9push_backERKy", - 0xf2cfda63cef7f46dLL)); - EXPECT_TRUE(h.EndFunction(0)); - EXPECT_TRUE(h.EndCompilationUnit(0)); - - h.Finalize(); - - // Now check to see what has been added to the Module. - Module::File *file = m.FindExistingFile("compilation-unit"); - ASSERT_TRUE(file != NULL); - - vector functions; - m.GetFunctions(&functions, functions.end()); - ASSERT_EQ(1U, functions.size()); - - Module::Function *function = functions[0]; - // This is GCC-specific, but we shouldn't be seeing STABS data anywhere - // but Linux. - EXPECT_STREQ("std::vector >::" - "push_back(unsigned long long const&)", - function->name.c_str()); - EXPECT_EQ(0xf2cfda63cef7f46dLL, function->address); - EXPECT_LT(0U, function->size); // should have used dummy size - EXPECT_EQ(0U, function->parameter_size); - ASSERT_EQ(0U, function->lines.size()); -} -#endif // __GNUC__ - -// The GNU toolchain can omit functions that are not used; however, -// when it does so, it doesn't clean up the debugging information that -// refers to them. In STABS, this results in compilation units whose -// SO addresses are zero. -TEST(Omitted, Function) { - Module m("name", "os", "arch", "id"); - StabsToModule h(&m); - - // The StartCompilationUnit and EndCompilationUnit calls may both have an - // address of zero if the compilation unit has had sections removed. - EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0, "build-directory")); - EXPECT_TRUE(h.StartFunction("function", 0x2a133596)); - EXPECT_TRUE(h.EndFunction(0)); - EXPECT_TRUE(h.EndCompilationUnit(0)); -} - -// TODO --- if we actually cared about STABS. Even without these we've -// got full coverage of non-failure source lines in dump_stabs.cc. - -// Line size from next line -// Line size from function end -// Line size from next function start -// line size from cu end -// line size from next cu start -// fallback size is something plausible - -// function size from function end -// function size from next function start -// function size from cu end -// function size from next cu start -// fallback size is something plausible - -// omitting functions outside the compilation unit's address range -// zero-line, one-line, many-line functions diff --git a/breakpad/common/string_conversion.cc b/breakpad/common/string_conversion.cc deleted file mode 100644 index 9b06e86b4..000000000 --- a/breakpad/common/string_conversion.cc +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include - -#include "common/convert_UTF.h" -#include "common/scoped_ptr.h" -#include "common/string_conversion.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -using std::vector; - -void UTF8ToUTF16(const char *in, vector *out) { - size_t source_length = strlen(in); - const UTF8 *source_ptr = reinterpret_cast(in); - const UTF8 *source_end_ptr = source_ptr + source_length; - // Erase the contents and zero fill to the expected size - out->clear(); - out->insert(out->begin(), source_length, 0); - uint16_t *target_ptr = &(*out)[0]; - uint16_t *target_end_ptr = target_ptr + out->capacity() * sizeof(uint16_t); - ConversionResult result = ConvertUTF8toUTF16(&source_ptr, source_end_ptr, - &target_ptr, target_end_ptr, - strictConversion); - - // Resize to be the size of the # of converted characters + NULL - out->resize(result == conversionOK ? target_ptr - &(*out)[0] + 1: 0); -} - -int UTF8ToUTF16Char(const char *in, int in_length, uint16_t out[2]) { - const UTF8 *source_ptr = reinterpret_cast(in); - const UTF8 *source_end_ptr = source_ptr + sizeof(char); - uint16_t *target_ptr = out; - uint16_t *target_end_ptr = target_ptr + 2 * sizeof(uint16_t); - out[0] = out[1] = 0; - - // Process one character at a time - while (1) { - ConversionResult result = ConvertUTF8toUTF16(&source_ptr, source_end_ptr, - &target_ptr, target_end_ptr, - strictConversion); - - if (result == conversionOK) - return static_cast(source_ptr - reinterpret_cast(in)); - - // Add another character to the input stream and try again - source_ptr = reinterpret_cast(in); - ++source_end_ptr; - - if (source_end_ptr > reinterpret_cast(in) + in_length) - break; - } - - return 0; -} - -void UTF32ToUTF16(const wchar_t *in, vector *out) { - size_t source_length = wcslen(in); - const UTF32 *source_ptr = reinterpret_cast(in); - const UTF32 *source_end_ptr = source_ptr + source_length; - // Erase the contents and zero fill to the expected size - out->clear(); - out->insert(out->begin(), source_length, 0); - uint16_t *target_ptr = &(*out)[0]; - uint16_t *target_end_ptr = target_ptr + out->capacity() * sizeof(uint16_t); - ConversionResult result = ConvertUTF32toUTF16(&source_ptr, source_end_ptr, - &target_ptr, target_end_ptr, - strictConversion); - - // Resize to be the size of the # of converted characters + NULL - out->resize(result == conversionOK ? target_ptr - &(*out)[0] + 1: 0); -} - -void UTF32ToUTF16Char(wchar_t in, uint16_t out[2]) { - const UTF32 *source_ptr = reinterpret_cast(&in); - const UTF32 *source_end_ptr = source_ptr + 1; - uint16_t *target_ptr = out; - uint16_t *target_end_ptr = target_ptr + 2 * sizeof(uint16_t); - out[0] = out[1] = 0; - ConversionResult result = ConvertUTF32toUTF16(&source_ptr, source_end_ptr, - &target_ptr, target_end_ptr, - strictConversion); - - if (result != conversionOK) { - out[0] = out[1] = 0; - } -} - -static inline uint16_t Swap(uint16_t value) { - return (value >> 8) | static_cast(value << 8); -} - -string UTF16ToUTF8(const vector &in, bool swap) { - const UTF16 *source_ptr = &in[0]; - scoped_ptr source_buffer; - - // If we're to swap, we need to make a local copy and swap each byte pair - if (swap) { - int idx = 0; - source_buffer.reset(new uint16_t[in.size()]); - UTF16 *source_buffer_ptr = source_buffer.get(); - for (vector::const_iterator it = in.begin(); - it != in.end(); ++it, ++idx) - source_buffer_ptr[idx] = Swap(*it); - - source_ptr = source_buffer.get(); - } - - // The maximum expansion would be 4x the size of the input string. - const UTF16 *source_end_ptr = source_ptr + in.size(); - size_t target_capacity = in.size() * 4; - scoped_array target_buffer(new UTF8[target_capacity]); - UTF8 *target_ptr = target_buffer.get(); - UTF8 *target_end_ptr = target_ptr + target_capacity; - ConversionResult result = ConvertUTF16toUTF8(&source_ptr, source_end_ptr, - &target_ptr, target_end_ptr, - strictConversion); - - if (result == conversionOK) { - const char *targetPtr = reinterpret_cast(target_buffer.get()); - return targetPtr; - } - - return ""; -} - -} // namespace google_breakpad diff --git a/breakpad/common/string_conversion.h b/breakpad/common/string_conversion.h deleted file mode 100644 index b9ba96a2e..000000000 --- a/breakpad/common/string_conversion.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// string_conversion.h: Conversion between different UTF-8/16/32 encodings. - -#ifndef COMMON_STRING_CONVERSION_H__ -#define COMMON_STRING_CONVERSION_H__ - -#include -#include - -#include "common/using_std_string.h" -#include "google_breakpad/common/breakpad_types.h" - -namespace google_breakpad { - -using std::vector; - -// Convert |in| to UTF-16 into |out|. Use platform byte ordering. If the -// conversion failed, |out| will be zero length. -void UTF8ToUTF16(const char *in, vector *out); - -// Convert at least one character (up to a maximum of |in_length|) from |in| -// to UTF-16 into |out|. Return the number of characters consumed from |in|. -// Any unused characters in |out| will be initialized to 0. No memory will -// be allocated by this routine. -int UTF8ToUTF16Char(const char *in, int in_length, uint16_t out[2]); - -// Convert |in| to UTF-16 into |out|. Use platform byte ordering. If the -// conversion failed, |out| will be zero length. -void UTF32ToUTF16(const wchar_t *in, vector *out); - -// Convert |in| to UTF-16 into |out|. Any unused characters in |out| will be -// initialized to 0. No memory will be allocated by this routine. -void UTF32ToUTF16Char(wchar_t in, uint16_t out[2]); - -// Convert |in| to UTF-8. If |swap| is true, swap bytes before converting. -string UTF16ToUTF8(const vector &in, bool swap); - -} // namespace google_breakpad - -#endif // COMMON_STRING_CONVERSION_H__ diff --git a/breakpad/common/symbol_data.h b/breakpad/common/symbol_data.h deleted file mode 100644 index 2cf15a855..000000000 --- a/breakpad/common/symbol_data.h +++ /dev/null @@ -1,42 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef COMMON_SYMBOL_DATA_H_ -#define COMMON_SYMBOL_DATA_H_ - -// Control what data is used from the symbol file. -enum SymbolData { - ALL_SYMBOL_DATA, - NO_CFI, - ONLY_CFI -}; - -#endif // COMMON_SYMBOL_DATA_H_ diff --git a/breakpad/common/test_assembler.cc b/breakpad/common/test_assembler.cc deleted file mode 100644 index 1e783b45c..000000000 --- a/breakpad/common/test_assembler.cc +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// test_assembler.cc: Implementation of google_breakpad::TestAssembler. -// See test_assembler.h for details. - -#include "common/test_assembler.h" - -#include -#include - -#include - -namespace google_breakpad { -namespace test_assembler { - -using std::back_insert_iterator; - -Label::Label() : value_(new Binding()) { } -Label::Label(uint64_t value) : value_(new Binding(value)) { } -Label::Label(const Label &label) { - value_ = label.value_; - value_->Acquire(); -} -Label::~Label() { - if (value_->Release()) delete value_; -} - -Label &Label::operator=(uint64_t value) { - value_->Set(NULL, value); - return *this; -} - -Label &Label::operator=(const Label &label) { - value_->Set(label.value_, 0); - return *this; -} - -Label Label::operator+(uint64_t addend) const { - Label l; - l.value_->Set(this->value_, addend); - return l; -} - -Label Label::operator-(uint64_t subtrahend) const { - Label l; - l.value_->Set(this->value_, -subtrahend); - return l; -} - -// When NDEBUG is #defined, assert doesn't evaluate its argument. This -// means you can't simply use assert to check the return value of a -// function with necessary side effects. -// -// ALWAYS_EVALUATE_AND_ASSERT(x) evaluates x regardless of whether -// NDEBUG is #defined; when NDEBUG is not #defined, it further asserts -// that x is true. -#ifdef NDEBUG -#define ALWAYS_EVALUATE_AND_ASSERT(x) x -#else -#define ALWAYS_EVALUATE_AND_ASSERT(x) assert(x) -#endif - -uint64_t Label::operator-(const Label &label) const { - uint64_t offset; - ALWAYS_EVALUATE_AND_ASSERT(IsKnownOffsetFrom(label, &offset)); - return offset; -} - -uint64_t Label::Value() const { - uint64_t v = 0; - ALWAYS_EVALUATE_AND_ASSERT(IsKnownConstant(&v)); - return v; -}; - -bool Label::IsKnownConstant(uint64_t *value_p) const { - Binding *base; - uint64_t addend; - value_->Get(&base, &addend); - if (base != NULL) return false; - if (value_p) *value_p = addend; - return true; -} - -bool Label::IsKnownOffsetFrom(const Label &label, uint64_t *offset_p) const -{ - Binding *label_base, *this_base; - uint64_t label_addend, this_addend; - label.value_->Get(&label_base, &label_addend); - value_->Get(&this_base, &this_addend); - // If this and label are related, Get will find their final - // common ancestor, regardless of how indirect the relation is. This - // comparison also handles the constant vs. constant case. - if (this_base != label_base) return false; - if (offset_p) *offset_p = this_addend - label_addend; - return true; -} - -Label::Binding::Binding() : base_(this), addend_(), reference_count_(1) { } - -Label::Binding::Binding(uint64_t addend) - : base_(NULL), addend_(addend), reference_count_(1) { } - -Label::Binding::~Binding() { - assert(reference_count_ == 0); - if (base_ && base_ != this && base_->Release()) - delete base_; -} - -void Label::Binding::Set(Binding *binding, uint64_t addend) { - if (!base_ && !binding) { - // We're equating two constants. This could be okay. - assert(addend_ == addend); - } else if (!base_) { - // We are a known constant, but BINDING may not be, so turn the - // tables and try to set BINDING's value instead. - binding->Set(NULL, addend_ - addend); - } else { - if (binding) { - // Find binding's final value. Since the final value is always either - // completely unconstrained or a constant, never a reference to - // another variable (otherwise, it wouldn't be final), this - // guarantees we won't create cycles here, even for code like this: - // l = m, m = n, n = l; - uint64_t binding_addend; - binding->Get(&binding, &binding_addend); - addend += binding_addend; - } - - // It seems likely that setting a binding to itself is a bug - // (although I can imagine this might turn out to be helpful to - // permit). - assert(binding != this); - - if (base_ != this) { - // Set the other bindings on our chain as well. Note that this - // is sufficient even though binding relationships form trees: - // All binding operations traverse their chains to the end, and - // all bindings related to us share some tail of our chain, so - // they will see the changes we make here. - base_->Set(binding, addend - addend_); - // We're not going to use base_ any more. - if (base_->Release()) delete base_; - } - - // Adopt BINDING as our base. Note that it should be correct to - // acquire here, after the release above, even though the usual - // reference-counting rules call for acquiring first, and then - // releasing: the self-reference assertion above should have - // complained if BINDING were 'this' or anywhere along our chain, - // so we didn't release BINDING. - if (binding) binding->Acquire(); - base_ = binding; - addend_ = addend; - } -} - -void Label::Binding::Get(Binding **base, uint64_t *addend) { - if (base_ && base_ != this) { - // Recurse to find the end of our reference chain (the root of our - // tree), and then rewrite every binding along the chain to refer - // to it directly, adjusting addends appropriately. (This is why - // this member function isn't this-const.) - Binding *final_base; - uint64_t final_addend; - base_->Get(&final_base, &final_addend); - if (final_base) final_base->Acquire(); - if (base_->Release()) delete base_; - base_ = final_base; - addend_ += final_addend; - } - *base = base_; - *addend = addend_; -} - -template -static inline void InsertEndian(test_assembler::Endianness endianness, - size_t size, uint64_t number, Inserter dest) { - assert(size > 0); - if (endianness == kLittleEndian) { - for (size_t i = 0; i < size; i++) { - *dest++ = (char) (number & 0xff); - number >>= 8; - } - } else { - assert(endianness == kBigEndian); - // The loop condition is odd, but it's correct for size_t. - for (size_t i = size - 1; i < size; i--) - *dest++ = (char) ((number >> (i * 8)) & 0xff); - } -} - -Section &Section::Append(Endianness endianness, size_t size, uint64_t number) { - InsertEndian(endianness, size, number, - back_insert_iterator(contents_)); - return *this; -} - -Section &Section::Append(Endianness endianness, size_t size, - const Label &label) { - // If this label's value is known, there's no reason to waste an - // entry in references_ on it. - uint64_t value; - if (label.IsKnownConstant(&value)) - return Append(endianness, size, value); - - // This will get caught when the references are resolved, but it's - // nicer to find out earlier. - assert(endianness != kUnsetEndian); - - references_.push_back(Reference(contents_.size(), endianness, size, label)); - contents_.append(size, 0); - return *this; -} - -#define ENDIANNESS_L kLittleEndian -#define ENDIANNESS_B kBigEndian -#define ENDIANNESS(e) ENDIANNESS_ ## e - -#define DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \ - Section &Section::e ## bits(uint ## bits ## _t v) { \ - InsertEndian(ENDIANNESS(e), bits / 8, v, \ - back_insert_iterator(contents_)); \ - return *this; \ - } - -#define DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits) \ - Section &Section::e ## bits(const Label &v) { \ - return Append(ENDIANNESS(e), bits / 8, v); \ - } - -// Define L16, B32, and friends. -#define DEFINE_SHORT_APPEND_ENDIAN(e, bits) \ - DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \ - DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits) - -DEFINE_SHORT_APPEND_LABEL_ENDIAN(L, 8); -DEFINE_SHORT_APPEND_LABEL_ENDIAN(B, 8); -DEFINE_SHORT_APPEND_ENDIAN(L, 16); -DEFINE_SHORT_APPEND_ENDIAN(L, 32); -DEFINE_SHORT_APPEND_ENDIAN(L, 64); -DEFINE_SHORT_APPEND_ENDIAN(B, 16); -DEFINE_SHORT_APPEND_ENDIAN(B, 32); -DEFINE_SHORT_APPEND_ENDIAN(B, 64); - -#define DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \ - Section &Section::D ## bits(uint ## bits ## _t v) { \ - InsertEndian(endianness_, bits / 8, v, \ - back_insert_iterator(contents_)); \ - return *this; \ - } -#define DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits) \ - Section &Section::D ## bits(const Label &v) { \ - return Append(endianness_, bits / 8, v); \ - } -#define DEFINE_SHORT_APPEND_DEFAULT(bits) \ - DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \ - DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits) - -DEFINE_SHORT_APPEND_LABEL_DEFAULT(8) -DEFINE_SHORT_APPEND_DEFAULT(16); -DEFINE_SHORT_APPEND_DEFAULT(32); -DEFINE_SHORT_APPEND_DEFAULT(64); - -Section &Section::Append(const Section §ion) { - size_t base = contents_.size(); - contents_.append(section.contents_); - for (vector::const_iterator it = section.references_.begin(); - it != section.references_.end(); it++) - references_.push_back(Reference(base + it->offset, it->endianness, - it->size, it->label)); - return *this; -} - -Section &Section::LEB128(long long value) { - while (value < -0x40 || 0x3f < value) { - contents_ += (value & 0x7f) | 0x80; - if (value < 0) - value = (value >> 7) | ~(((unsigned long long) -1) >> 7); - else - value = (value >> 7); - } - contents_ += value & 0x7f; - return *this; -} - -Section &Section::ULEB128(uint64_t value) { - while (value > 0x7f) { - contents_ += (value & 0x7f) | 0x80; - value = (value >> 7); - } - contents_ += value; - return *this; -} - -Section &Section::Align(size_t alignment, uint8_t pad_byte) { - // ALIGNMENT must be a power of two. - assert(((alignment - 1) & alignment) == 0); - size_t new_size = (contents_.size() + alignment - 1) & ~(alignment - 1); - contents_.append(new_size - contents_.size(), pad_byte); - assert((contents_.size() & (alignment - 1)) == 0); - return *this; -} - -void Section::Clear() { - contents_.clear(); - references_.clear(); -} - -bool Section::GetContents(string *contents) { - // For each label reference, find the label's value, and patch it into - // the section's contents. - for (size_t i = 0; i < references_.size(); i++) { - Reference &r = references_[i]; - uint64_t value; - if (!r.label.IsKnownConstant(&value)) { - fprintf(stderr, "Undefined label #%zu at offset 0x%zx\n", i, r.offset); - return false; - } - assert(r.offset < contents_.size()); - assert(contents_.size() - r.offset >= r.size); - InsertEndian(r.endianness, r.size, value, contents_.begin() + r.offset); - } - contents->clear(); - std::swap(contents_, *contents); - references_.clear(); - return true; -} - -} // namespace test_assembler -} // namespace google_breakpad diff --git a/breakpad/common/test_assembler.h b/breakpad/common/test_assembler.h deleted file mode 100644 index 373dbebac..000000000 --- a/breakpad/common/test_assembler.h +++ /dev/null @@ -1,484 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// test-assembler.h: interface to class for building complex binary streams. - -// To test the Breakpad symbol dumper and processor thoroughly, for -// all combinations of host system and minidump processor -// architecture, we need to be able to easily generate complex test -// data like debugging information and minidump files. -// -// For example, if we want our unit tests to provide full code -// coverage for stack walking, it may be difficult to persuade the -// compiler to generate every possible sort of stack walking -// information that we want to support; there are probably DWARF CFI -// opcodes that GCC never emits. Similarly, if we want to test our -// error handling, we will need to generate damaged minidumps or -// debugging information that (we hope) the client or compiler will -// never produce on its own. -// -// google_breakpad::TestAssembler provides a predictable and -// (relatively) simple way to generate complex formatted data streams -// like minidumps and CFI. Furthermore, because TestAssembler is -// portable, developers without access to (say) Visual Studio or a -// SPARC assembler can still work on test data for those targets. - -#ifndef PROCESSOR_TEST_ASSEMBLER_H_ -#define PROCESSOR_TEST_ASSEMBLER_H_ - -#include -#include -#include - -#include "common/using_std_string.h" -#include "google_breakpad/common/breakpad_types.h" - -namespace google_breakpad { - -using std::list; -using std::vector; - -namespace test_assembler { - -// A Label represents a value not yet known that we need to store in a -// section. As long as all the labels a section refers to are defined -// by the time we retrieve its contents as bytes, we can use undefined -// labels freely in that section's construction. -// -// A label can be in one of three states: -// - undefined, -// - defined as the sum of some other label and a constant, or -// - a constant. -// -// A label's value never changes, but it can accumulate constraints. -// Adding labels and integers is permitted, and yields a label. -// Subtracting a constant from a label is permitted, and also yields a -// label. Subtracting two labels that have some relationship to each -// other is permitted, and yields a constant. -// -// For example: -// -// Label a; // a's value is undefined -// Label b; // b's value is undefined -// { -// Label c = a + 4; // okay, even though a's value is unknown -// b = c + 4; // also okay; b is now a+8 -// } -// Label d = b - 2; // okay; d == a+6, even though c is gone -// d.Value(); // error: d's value is not yet known -// d - a; // is 6, even though their values are not known -// a = 12; // now b == 20, and d == 18 -// d.Value(); // 18: no longer an error -// b.Value(); // 20 -// d = 10; // error: d is already defined. -// -// Label objects' lifetimes are unconstrained: notice that, in the -// above example, even though a and b are only related through c, and -// c goes out of scope, the assignment to a sets b's value as well. In -// particular, it's not necessary to ensure that a Label lives beyond -// Sections that refer to it. -class Label { - public: - Label(); // An undefined label. - Label(uint64_t value); // A label with a fixed value - Label(const Label &value); // A label equal to another. - ~Label(); - - // Return this label's value; it must be known. - // - // Providing this as a cast operator is nifty, but the conversions - // happen in unexpected places. In particular, ISO C++ says that - // Label + size_t becomes ambigious, because it can't decide whether - // to convert the Label to a uint64_t and then to a size_t, or use - // the overloaded operator that returns a new label, even though the - // former could fail if the label is not yet defined and the latter won't. - uint64_t Value() const; - - Label &operator=(uint64_t value); - Label &operator=(const Label &value); - Label operator+(uint64_t addend) const; - Label operator-(uint64_t subtrahend) const; - uint64_t operator-(const Label &subtrahend) const; - - // We could also provide == and != that work on undefined, but - // related, labels. - - // Return true if this label's value is known. If VALUE_P is given, - // set *VALUE_P to the known value if returning true. - bool IsKnownConstant(uint64_t *value_p = NULL) const; - - // Return true if the offset from LABEL to this label is known. If - // OFFSET_P is given, set *OFFSET_P to the offset when returning true. - // - // You can think of l.KnownOffsetFrom(m, &d) as being like 'd = l-m', - // except that it also returns a value indicating whether the - // subtraction is possible given what we currently know of l and m. - // It can be possible even if we don't know l and m's values. For - // example: - // - // Label l, m; - // m = l + 10; - // l.IsKnownConstant(); // false - // m.IsKnownConstant(); // false - // uint64_t d; - // l.IsKnownOffsetFrom(m, &d); // true, and sets d to -10. - // l-m // -10 - // m-l // 10 - // m.Value() // error: m's value is not known - bool IsKnownOffsetFrom(const Label &label, uint64_t *offset_p = NULL) const; - - private: - // A label's value, or if that is not yet known, how the value is - // related to other labels' values. A binding may be: - // - a known constant, - // - constrained to be equal to some other binding plus a constant, or - // - unconstrained, and free to take on any value. - // - // Many labels may point to a single binding, and each binding may - // refer to another, so bindings and labels form trees whose leaves - // are labels, whose interior nodes (and roots) are bindings, and - // where links point from children to parents. Bindings are - // reference counted, allowing labels to be lightweight, copyable, - // assignable, placed in containers, and so on. - class Binding { - public: - Binding(); - Binding(uint64_t addend); - ~Binding(); - - // Increment our reference count. - void Acquire() { reference_count_++; }; - // Decrement our reference count, and return true if it is zero. - bool Release() { return --reference_count_ == 0; } - - // Set this binding to be equal to BINDING + ADDEND. If BINDING is - // NULL, then set this binding to the known constant ADDEND. - // Update every binding on this binding's chain to point directly - // to BINDING, or to be a constant, with addends adjusted - // appropriately. - void Set(Binding *binding, uint64_t value); - - // Return what we know about the value of this binding. - // - If this binding's value is a known constant, set BASE to - // NULL, and set ADDEND to its value. - // - If this binding is not a known constant but related to other - // bindings, set BASE to the binding at the end of the relation - // chain (which will always be unconstrained), and set ADDEND to the - // value to add to that binding's value to get this binding's - // value. - // - If this binding is unconstrained, set BASE to this, and leave - // ADDEND unchanged. - void Get(Binding **base, uint64_t *addend); - - private: - // There are three cases: - // - // - A binding representing a known constant value has base_ NULL, - // and addend_ equal to the value. - // - // - A binding representing a completely unconstrained value has - // base_ pointing to this; addend_ is unused. - // - // - A binding whose value is related to some other binding's - // value has base_ pointing to that other binding, and addend_ - // set to the amount to add to that binding's value to get this - // binding's value. We only represent relationships of the form - // x = y+c. - // - // Thus, the bind_ links form a chain terminating in either a - // known constant value or a completely unconstrained value. Most - // operations on bindings do path compression: they change every - // binding on the chain to point directly to the final value, - // adjusting addends as appropriate. - Binding *base_; - uint64_t addend_; - - // The number of Labels and Bindings pointing to this binding. - // (When a binding points to itself, indicating a completely - // unconstrained binding, that doesn't count as a reference.) - int reference_count_; - }; - - // This label's value. - Binding *value_; -}; - -inline Label operator+(uint64_t a, const Label &l) { return l + a; } -// Note that int-Label isn't defined, as negating a Label is not an -// operation we support. - -// Conventions for representing larger numbers as sequences of bytes. -enum Endianness { - kBigEndian, // Big-endian: the most significant byte comes first. - kLittleEndian, // Little-endian: the least significant byte comes first. - kUnsetEndian, // used internally -}; - -// A section is a sequence of bytes, constructed by appending bytes -// to the end. Sections have a convenient and flexible set of member -// functions for appending data in various formats: big-endian and -// little-endian signed and unsigned values of different sizes; -// LEB128 and ULEB128 values (see below), and raw blocks of bytes. -// -// If you need to append a value to a section that is not convenient -// to compute immediately, you can create a label, append the -// label's value to the section, and then set the label's value -// later, when it's convenient to do so. Once a label's value is -// known, the section class takes care of updating all previously -// appended references to it. -// -// Once all the labels to which a section refers have had their -// values determined, you can get a copy of the section's contents -// as a string. -// -// Note that there is no specified "start of section" label. This is -// because there are typically several different meanings for "the -// start of a section": the offset of the section within an object -// file, the address in memory at which the section's content appear, -// and so on. It's up to the code that uses the Section class to -// keep track of these explicitly, as they depend on the application. -class Section { - public: - Section(Endianness endianness = kUnsetEndian) - : endianness_(endianness) { }; - - // A base class destructor should be either public and virtual, - // or protected and nonvirtual. - virtual ~Section() { }; - - // Set the default endianness of this section to ENDIANNESS. This - // sets the behavior of the D appending functions. If the - // assembler's default endianness was set, this is the - void set_endianness(Endianness endianness) { - endianness_ = endianness; - } - - // Return the default endianness of this section. - Endianness endianness() const { return endianness_; } - - // Append the SIZE bytes at DATA or the contents of STRING to the - // end of this section. Return a reference to this section. - Section &Append(const uint8_t *data, size_t size) { - contents_.append(reinterpret_cast(data), size); - return *this; - }; - Section &Append(const string &data) { - contents_.append(data); - return *this; - }; - - // Append SIZE copies of BYTE to the end of this section. Return a - // reference to this section. - Section &Append(size_t size, uint8_t byte) { - contents_.append(size, (char) byte); - return *this; - } - - // Append NUMBER to this section. ENDIANNESS is the endianness to - // use to write the number. SIZE is the length of the number in - // bytes. Return a reference to this section. - Section &Append(Endianness endianness, size_t size, uint64_t number); - Section &Append(Endianness endianness, size_t size, const Label &label); - - // Append SECTION to the end of this section. The labels SECTION - // refers to need not be defined yet. - // - // Note that this has no effect on any Labels' values, or on - // SECTION. If placing SECTION within 'this' provides new - // constraints on existing labels' values, then it's up to the - // caller to fiddle with those labels as needed. - Section &Append(const Section §ion); - - // Append the contents of DATA as a series of bytes terminated by - // a NULL character. - Section &AppendCString(const string &data) { - Append(data); - contents_ += '\0'; - return *this; - } - - // Append at most SIZE bytes from DATA; if DATA is less than SIZE bytes - // long, pad with '\0' characters. - Section &AppendCString(const string &data, size_t size) { - contents_.append(data, 0, size); - if (data.size() < size) - Append(size - data.size(), 0); - return *this; - } - - // Append VALUE or LABEL to this section, with the given bit width and - // endianness. Return a reference to this section. - // - // The names of these functions have the form : - // is either 'L' (little-endian, least significant byte first), - // 'B' (big-endian, most significant byte first), or - // 'D' (default, the section's default endianness) - // is 8, 16, 32, or 64. - // - // Since endianness doesn't matter for a single byte, all the - // =8 functions are equivalent. - // - // These can be used to write both signed and unsigned values, as - // the compiler will properly sign-extend a signed value before - // passing it to the function, at which point the function's - // behavior is the same either way. - Section &L8(uint8_t value) { contents_ += value; return *this; } - Section &B8(uint8_t value) { contents_ += value; return *this; } - Section &D8(uint8_t value) { contents_ += value; return *this; } - Section &L16(uint16_t), &L32(uint32_t), &L64(uint64_t), - &B16(uint16_t), &B32(uint32_t), &B64(uint64_t), - &D16(uint16_t), &D32(uint32_t), &D64(uint64_t); - Section &L8(const Label &label), &L16(const Label &label), - &L32(const Label &label), &L64(const Label &label), - &B8(const Label &label), &B16(const Label &label), - &B32(const Label &label), &B64(const Label &label), - &D8(const Label &label), &D16(const Label &label), - &D32(const Label &label), &D64(const Label &label); - - // Append VALUE in a signed LEB128 (Little-Endian Base 128) form. - // - // The signed LEB128 representation of an integer N is a variable - // number of bytes: - // - // - If N is between -0x40 and 0x3f, then its signed LEB128 - // representation is a single byte whose value is N. - // - // - Otherwise, its signed LEB128 representation is (N & 0x7f) | - // 0x80, followed by the signed LEB128 representation of N / 128, - // rounded towards negative infinity. - // - // In other words, we break VALUE into groups of seven bits, put - // them in little-endian order, and then write them as eight-bit - // bytes with the high bit on all but the last. - // - // Note that VALUE cannot be a Label (we would have to implement - // relaxation). - Section &LEB128(long long value); - - // Append VALUE in unsigned LEB128 (Little-Endian Base 128) form. - // - // The unsigned LEB128 representation of an integer N is a variable - // number of bytes: - // - // - If N is between 0 and 0x7f, then its unsigned LEB128 - // representation is a single byte whose value is N. - // - // - Otherwise, its unsigned LEB128 representation is (N & 0x7f) | - // 0x80, followed by the unsigned LEB128 representation of N / - // 128, rounded towards negative infinity. - // - // Note that VALUE cannot be a Label (we would have to implement - // relaxation). - Section &ULEB128(uint64_t value); - - // Jump to the next location aligned on an ALIGNMENT-byte boundary, - // relative to the start of the section. Fill the gap with PAD_BYTE. - // ALIGNMENT must be a power of two. Return a reference to this - // section. - Section &Align(size_t alignment, uint8_t pad_byte = 0); - - // Clear the contents of this section. - void Clear(); - - // Return the current size of the section. - size_t Size() const { return contents_.size(); } - - // Return a label representing the start of the section. - // - // It is up to the user whether this label represents the section's - // position in an object file, the section's address in memory, or - // what have you; some applications may need both, in which case - // this simple-minded interface won't be enough. This class only - // provides a single start label, for use with the Here and Mark - // member functions. - // - // Ideally, we'd provide this in a subclass that actually knows more - // about the application at hand and can provide an appropriate - // collection of start labels. But then the appending member - // functions like Append and D32 would return a reference to the - // base class, not the derived class, and the chaining won't work. - // Since the only value here is in pretty notation, that's a fatal - // flaw. - Label start() const { return start_; } - - // Return a label representing the point at which the next Appended - // item will appear in the section, relative to start(). - Label Here() const { return start_ + Size(); } - - // Set *LABEL to Here, and return a reference to this section. - Section &Mark(Label *label) { *label = Here(); return *this; } - - // If there are no undefined label references left in this - // section, set CONTENTS to the contents of this section, as a - // string, and clear this section. Return true on success, or false - // if there were still undefined labels. - bool GetContents(string *contents); - - private: - // Used internally. A reference to a label's value. - struct Reference { - Reference(size_t set_offset, Endianness set_endianness, size_t set_size, - const Label &set_label) - : offset(set_offset), endianness(set_endianness), size(set_size), - label(set_label) { } - - // The offset of the reference within the section. - size_t offset; - - // The endianness of the reference. - Endianness endianness; - - // The size of the reference. - size_t size; - - // The label to which this is a reference. - Label label; - }; - - // The default endianness of this section. - Endianness endianness_; - - // The contents of the section. - string contents_; - - // References to labels within those contents. - vector references_; - - // A label referring to the beginning of the section. - Label start_; -}; - -} // namespace test_assembler -} // namespace google_breakpad - -#endif // PROCESSOR_TEST_ASSEMBLER_H_ diff --git a/breakpad/common/test_assembler_unittest.cc b/breakpad/common/test_assembler_unittest.cc deleted file mode 100644 index 94b5a5ce5..000000000 --- a/breakpad/common/test_assembler_unittest.cc +++ /dev/null @@ -1,1662 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy - -// test_assembler_unittest.cc: Unit tests for google_breakpad::TestAssembler. - -#include -#include - -#include "breakpad_googletest_includes.h" -#include "common/test_assembler.h" -#include "common/using_std_string.h" - -using google_breakpad::test_assembler::Label; -using google_breakpad::test_assembler::Section; -using google_breakpad::test_assembler::kBigEndian; -using google_breakpad::test_assembler::kLittleEndian; -using testing::Test; - -TEST(ConstructLabel, Simple) { - Label l; -} - -TEST(ConstructLabel, Undefined) { - Label l; - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(ConstructLabelDeathTest, Undefined) { - Label l; - ASSERT_DEATH(l.Value(), "IsKnownConstant\\(&v\\)"); -} - -TEST(ConstructLabel, Constant) { - Label l(0x060b9f974eaf301eULL); - uint64_t v; - EXPECT_TRUE(l.IsKnownConstant(&v)); - EXPECT_EQ(v, 0x060b9f974eaf301eULL); - EXPECT_EQ(l.Value(), 0x060b9f974eaf301eULL); -} - -TEST(ConstructLabel, Copy) { - Label l; - Label m(l); - uint64_t v; - EXPECT_TRUE(l.IsKnownOffsetFrom(m, &v)); - EXPECT_EQ(0U, v); -} - -// The left-hand-side of a label assignment can be either -// unconstrained, related, or known. The right-hand-side can be any of -// those, or an integer. -TEST(Assignment, UnconstrainedToUnconstrained) { - Label l, m; - l = m; - EXPECT_EQ(0U, l-m); - EXPECT_TRUE(l.IsKnownOffsetFrom(m)); - uint64_t d; - EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d)); - EXPECT_EQ(0U, d); - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(Assignment, UnconstrainedToRelated) { - Label l, m, n; - l = n; - l = m; - EXPECT_EQ(0U, l-m); - EXPECT_TRUE(l.IsKnownOffsetFrom(m)); - uint64_t d; - EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d)); - EXPECT_EQ(0U, d); - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(Assignment, UnconstrainedToKnown) { - Label l, m; - l = 0x8fd16e55b20a39c1ULL; - l = m; - EXPECT_EQ(0U, l-m); - EXPECT_TRUE(l.IsKnownOffsetFrom(m)); - uint64_t d; - EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d)); - EXPECT_EQ(0U, d); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x8fd16e55b20a39c1ULL, m.Value()); -} - -TEST(Assignment, RelatedToUnconstrained) { - Label l, m, n; - m = n; - l = m; - EXPECT_EQ(0U, l-n); - EXPECT_TRUE(l.IsKnownOffsetFrom(n)); - uint64_t d; - EXPECT_TRUE(l.IsKnownOffsetFrom(n, &d)); - EXPECT_EQ(0U, d); - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(Assignment, RelatedToRelated) { - Label l, m, n, o; - l = n; - m = o; - l = m; - EXPECT_EQ(0U, n-o); - EXPECT_TRUE(n.IsKnownOffsetFrom(o)); - uint64_t d; - EXPECT_TRUE(n.IsKnownOffsetFrom(o, &d)); - EXPECT_EQ(0U, d); - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(Assignment, RelatedToKnown) { - Label l, m, n; - m = n; - l = 0xd2011f8c82ad56f2ULL; - l = m; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0xd2011f8c82ad56f2ULL, l.Value()); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0xd2011f8c82ad56f2ULL, m.Value()); - EXPECT_TRUE(n.IsKnownConstant()); - EXPECT_EQ(0xd2011f8c82ad56f2ULL, n.Value()); -} - -TEST(Assignment, KnownToUnconstrained) { - Label l, m; - m = 0x50b024c0d6073887ULL; - l = m; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0x50b024c0d6073887ULL, l.Value()); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x50b024c0d6073887ULL, m.Value()); -} - -TEST(Assignment, KnownToRelated) { - Label l, m, n; - l = n; - m = 0x5348883655c727e5ULL; - l = m; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0x5348883655c727e5ULL, l.Value()); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x5348883655c727e5ULL, m.Value()); - EXPECT_TRUE(n.IsKnownConstant()); - EXPECT_EQ(0x5348883655c727e5ULL, n.Value()); -} - -TEST(Assignment, KnownToKnown) { - Label l, m; - l = 0x36c209c20987564eULL; - m = 0x36c209c20987564eULL; - l = m; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0x36c209c20987564eULL, l.Value()); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x36c209c20987564eULL, m.Value()); -} - -TEST(Assignment, ConstantToUnconstrained) { - Label l; - l = 0xc02495f4d7f5a957ULL; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0xc02495f4d7f5a957ULL, l.Value()); -} - -TEST(Assignment, ConstantToRelated) { - Label l, m; - l = m; - l = 0x4577901cf275488dULL; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0x4577901cf275488dULL, l.Value()); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x4577901cf275488dULL, m.Value()); -} - -TEST(Assignment, ConstantToKnown) { - Label l; - l = 0xec0b9c369b7e8ea7ULL; - l = 0xec0b9c369b7e8ea7ULL; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0xec0b9c369b7e8ea7ULL, l.Value()); -} - -TEST(AssignmentDeathTest, Self) { - Label l; - ASSERT_DEATH(l = l, "binding != this"); -} - -TEST(AssignmentDeathTest, IndirectCycle) { - Label l, m, n; - l = m; - m = n; - ASSERT_DEATH(n = l, "binding != this"); -} - -TEST(AssignmentDeathTest, Cycle) { - Label l, m, n, o; - l = m; - m = n; - o = n; - ASSERT_DEATH(o = l, "binding != this"); -} - -TEST(Addition, LabelConstant) { - Label l, m; - m = l + 0x5248d93e8bbe9497ULL; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - uint64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(0x5248d93e8bbe9497ULL, d); - EXPECT_FALSE(m.IsKnownConstant()); -} - -TEST(Addition, ConstantLabel) { - Label l, m; - m = 0xf51e94e00d6e3c84ULL + l; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - uint64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(0xf51e94e00d6e3c84ULL, d); - EXPECT_FALSE(m.IsKnownConstant()); -} - -TEST(Addition, KnownLabelConstant) { - Label l, m; - l = 0x16286307042ce0d8ULL; - m = l + 0x3fdddd91306719d7ULL; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - uint64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(0x3fdddd91306719d7ULL, d); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x16286307042ce0d8ULL + 0x3fdddd91306719d7ULL, m.Value()); -} - -TEST(Addition, ConstantKnownLabel) { - Label l, m; - l = 0x50f62d0cdd1031deULL; - m = 0x1b13462d8577c538ULL + l; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - uint64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(0x1b13462d8577c538ULL, d); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x50f62d0cdd1031deULL + 0x1b13462d8577c538ULL, m.Value()); -} - -TEST(Subtraction, LabelConstant) { - Label l, m; - m = l - 0x0620884d21d3138eULL; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - uint64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(-0x0620884d21d3138eULL, d); - EXPECT_FALSE(m.IsKnownConstant()); -} - -TEST(Subtraction, KnownLabelConstant) { - Label l, m; - l = 0x6237fbaf9ef7929eULL; - m = l - 0x317730995d2ab6eeULL; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - uint64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(-0x317730995d2ab6eeULL, d); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x6237fbaf9ef7929eULL - 0x317730995d2ab6eeULL, m.Value()); -} - -TEST(SubtractionDeathTest, LabelLabel) { - Label l, m; - ASSERT_DEATH(l - m, "IsKnownOffsetFrom\\(label, &offset\\)"); -} - -TEST(Subtraction, LabelLabel) { - Label l, m; - l = m + 0x7fa77ec63e28a17aULL; - EXPECT_EQ(0x7fa77ec63e28a17aULL, l - m); - EXPECT_EQ(-0x7fa77ec63e28a17aULL, m - l); -} - -TEST(IsKnownConstant, Undefined) { - Label l; - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(IsKnownConstant, RelatedLabel) { - Label l, m; - l = m; - EXPECT_FALSE(l.IsKnownConstant()); - EXPECT_FALSE(m.IsKnownConstant()); -} - -TEST(IsKnownConstant, Constant) { - Label l; - l = 0xf374b1bdd6a22576ULL; - EXPECT_TRUE(l.IsKnownConstant()); -} - -TEST(IsKnownOffsetFrom, Unrelated) { - Label l, m; - EXPECT_FALSE(l.IsKnownOffsetFrom(m)); -} - -TEST(IsKnownOffsetFrom, Related) { - Label l, m; - l = m; - EXPECT_TRUE(l.IsKnownOffsetFrom(m)); -} - -// Test the construction of chains of related labels, and the -// propagation of values through them. -// -// Although the relations between labels are supposed to behave -// symmetrically --- that is, 'a = b' should put a and b in -// indistinguishable states --- there's a distinction made internally -// between the target (a) and the source (b). -// -// So there are five test axes to cover: -// -// - Do we construct the chain with assignment ("Assign") or with constructors -// ("Construct")? -// -// - Do we set the value of the label at the start of the chain -// ("Start") or the label at the end ("End")? -// -// - Are we testing the propagation of a relationship between variable -// values ("Relation"), or the propagation of a known constant value -// ("Value")? -// -// - Do we set the value before building the chain ("Before") or after -// the chain has been built ("After")? -// -// - Do we add new relationships to the end of the existing chain -// ("Forward") or to the beginning ("Backward")? -// -// Of course, "Construct" and "Backward" can't be combined, which -// eliminates eight combinations, and "Construct", "End", and "Before" -// can't be combined, which eliminates two more, so there are are 22 -// combinations, not 32. - -TEST(LabelChain, AssignStartRelationBeforeForward) { - Label a, b, c, d; - Label x; - a = x; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, AssignStartRelationBeforeBackward) { - Label a, b, c, d; - Label x; - a = x; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, AssignStartRelationAfterForward) { - Label a, b, c, d; - Label x; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - a = x; - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, AssignStartRelationAfterBackward) { - Label a, b, c, d; - Label x; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - a = x; - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, AssignStartValueBeforeForward) { - Label a, b, c, d; - a = 0xa131200190546ac2ULL; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - EXPECT_EQ(0xa131200190546ac2ULL + 0x111U, d.Value()); - EXPECT_EQ(0xa131200190546ac2ULL + 0x11U, c.Value()); - EXPECT_EQ(0xa131200190546ac2ULL + 0x1U, b.Value()); - EXPECT_EQ(0xa131200190546ac2ULL + 0U, a.Value()); -} - -TEST(LabelChain, AssignStartValueBeforeBackward) { - Label a, b, c, d; - a = 0x8da17e1670ad4fa2ULL; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x111U, d.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x11U, c.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x1U, b.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0U, a.Value()); -} - -TEST(LabelChain, AssignStartValueAfterForward) { - Label a, b, c, d; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - a = 0x99b8f51bafd41adaULL; - EXPECT_EQ(0x99b8f51bafd41adaULL + 0x111U, d.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL + 0x11U, c.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL + 0x1U, b.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL + 0U, a.Value()); -} - -TEST(LabelChain, AssignStartValueAfterBackward) { - Label a, b, c, d; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - a = 0xc86ca1d97ab5df6eULL; - EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x111U, d.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x11U, c.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x1U, b.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0U, a.Value()); -} - -TEST(LabelChain, AssignEndRelationBeforeForward) { - Label a, b, c, d; - Label x; - x = d; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - EXPECT_EQ(-(uint64_t)0x111U, a-x); - EXPECT_EQ(-(uint64_t)0x110U, b-x); - EXPECT_EQ(-(uint64_t)0x100U, c-x); - EXPECT_EQ(-(uint64_t)0U, d-x); -} - -TEST(LabelChain, AssignEndRelationBeforeBackward) { - Label a, b, c, d; - Label x; - x = d; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - EXPECT_EQ(-(uint64_t)0x111U, a-x); - EXPECT_EQ(-(uint64_t)0x110U, b-x); - EXPECT_EQ(-(uint64_t)0x100U, c-x); - EXPECT_EQ(-(uint64_t)0U, d-x); -} - -TEST(LabelChain, AssignEndRelationAfterForward) { - Label a, b, c, d; - Label x; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - x = d; - EXPECT_EQ(-(uint64_t)0x111U, a-x); - EXPECT_EQ(-(uint64_t)0x110U, b-x); - EXPECT_EQ(-(uint64_t)0x100U, c-x); - EXPECT_EQ(-(uint64_t)0x000U, d-x); -} - -TEST(LabelChain, AssignEndRelationAfterBackward) { - Label a, b, c, d; - Label x; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - x = d; - EXPECT_EQ(-(uint64_t)0x111U, a-x); - EXPECT_EQ(-(uint64_t)0x110U, b-x); - EXPECT_EQ(-(uint64_t)0x100U, c-x); - EXPECT_EQ(-(uint64_t)0x000U, d-x); -} - -TEST(LabelChain, AssignEndValueBeforeForward) { - Label a, b, c, d; - d = 0xa131200190546ac2ULL; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - EXPECT_EQ(0xa131200190546ac2ULL - 0x111, a.Value()); - EXPECT_EQ(0xa131200190546ac2ULL - 0x110, b.Value()); - EXPECT_EQ(0xa131200190546ac2ULL - 0x100, c.Value()); - EXPECT_EQ(0xa131200190546ac2ULL - 0x000, d.Value()); -} - -TEST(LabelChain, AssignEndValueBeforeBackward) { - Label a, b, c, d; - d = 0x8da17e1670ad4fa2ULL; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x111, a.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x110, b.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x100, c.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x000, d.Value()); -} - -TEST(LabelChain, AssignEndValueAfterForward) { - Label a, b, c, d; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - d = 0x99b8f51bafd41adaULL; - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x111, a.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x110, b.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x100, c.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x000, d.Value()); -} - -TEST(LabelChain, AssignEndValueAfterBackward) { - Label a, b, c, d; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - d = 0xc86ca1d97ab5df6eULL; - EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x111, a.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x110, b.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x100, c.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x000, d.Value()); -} - -TEST(LabelChain, ConstructStartRelationBeforeForward) { - Label x; - Label a(x); - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, ConstructStartRelationAfterForward) { - Label x; - Label a; - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - a = x; - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, ConstructStartValueBeforeForward) { - Label a(0x5d234d177d01ccc8ULL); - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x111U, d.Value()); - EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x011U, c.Value()); - EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x001U, b.Value()); - EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x000U, a.Value()); -} - -TEST(LabelChain, ConstructStartValueAfterForward) { - Label a; - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - a = 0xded85d54586e84fcULL; - EXPECT_EQ(0xded85d54586e84fcULL + 0x111U, d.Value()); - EXPECT_EQ(0xded85d54586e84fcULL + 0x011U, c.Value()); - EXPECT_EQ(0xded85d54586e84fcULL + 0x001U, b.Value()); - EXPECT_EQ(0xded85d54586e84fcULL + 0x000U, a.Value()); -} - -TEST(LabelChain, ConstructEndRelationAfterForward) { - Label x; - Label a; - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - x = d; - EXPECT_EQ(-(uint64_t)0x111U, a-x); - EXPECT_EQ(-(uint64_t)0x110U, b-x); - EXPECT_EQ(-(uint64_t)0x100U, c-x); - EXPECT_EQ(-(uint64_t)0x000U, d-x); -} - -TEST(LabelChain, ConstructEndValueAfterForward) { - Label a; - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - d = 0x99b8f51bafd41adaULL; - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x111, a.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x110, b.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x100, c.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x000, d.Value()); -} - -TEST(LabelTree, KnownValue) { - Label l, m, n, o, p; - l = m; - m = n; - o = p; - p = n; - l = 0x536b5de3d468a1b5ULL; - EXPECT_EQ(0x536b5de3d468a1b5ULL, o.Value()); -} - -TEST(LabelTree, Related) { - Label l, m, n, o, p; - l = m - 1; - m = n - 10; - o = p + 100; - p = n + 1000; - EXPECT_EQ(1111U, o - l); -} - -TEST(EquationDeathTest, EqualConstants) { - Label m = 0x0d3962f280f07d24ULL; - Label n = 0x0d3962f280f07d24ULL; - m = n; // no death expected -} - -TEST(EquationDeathTest, EqualIndirectConstants) { - Label m = 0xa347f1e5238fe6a1ULL; - Label n; - Label o = n; - n = 0xa347f1e5238fe6a1ULL; - n = m; // no death expected -} - -TEST(EquationDeathTest, ConstantClash) { - Label m = 0xd4cc0f4f630ec741ULL; - Label n = 0x934cd2d8254fc3eaULL; - ASSERT_DEATH(m = n, "addend_ == addend"); -} - -TEST(EquationDeathTest, IndirectConstantClash) { - Label m = 0xd4cc0f4f630ec741ULL; - Label n, o; - n = o; - o = 0xcfbe3b83ac49ce86ULL; - ASSERT_DEATH(m = n, "addend_ == addend"); -} - -// Assigning to a related label may free the next Binding on its -// chain. This test always passes; it is interesting to memory -// checkers and coverage analysis. -TEST(LabelReferenceCount, AssignmentFree) { - Label l; - { - Label m; - l = m; - } - // This should free m's Binding. - l = 0xca8bae92f0376d4fULL; - ASSERT_EQ(0xca8bae92f0376d4fULL, l.Value()); -} - -// Finding the value of a label may free the Binding it refers to. This test -// always passes; it is interesting to memory checkers and coverage analysis. -TEST(LabelReferenceCount, FindValueFree) { - Label l; - { - Label m, n; - l = m; - m = n; - n = 0x7a0b0c576672daafULL; - // At this point, l's Binding refers to m's Binding, which refers - // to n's binding. - } - // Now, l is the only reference keeping the three Bindings alive. - // Resolving its value should free l's and m's original bindings. - ASSERT_EQ(0x7a0b0c576672daafULL, l.Value()); -} - -TEST(ConstructSection, Simple) { - Section s; -} - -TEST(ConstructSection, WithEndian) { - Section s(kBigEndian); -} - -// A fixture class for TestAssembler::Section tests. -class SectionFixture { - public: - Section section; - string contents; - static const uint8_t data[]; - static const size_t data_size; -}; - -const uint8_t SectionFixture::data[] = { - 0x87, 0x4f, 0x43, 0x67, 0x30, 0xd0, 0xd4, 0x0e -}; - -#define I0() -#define I1(a) { a } -#define I2(a,b) { a,b } -#define I3(a,b,c) { a,b,c } -#define I4(a,b,c,d) { a,b,c,d } -#define I5(a,b,c,d,e) { a,b,c,d,e } -#define I6(a,b,c,d,e,f) { a,b,c,d,e,f } -#define I7(a,b,c,d,e,f,g) { a,b,c,d,e,f,g } -#define I8(a,b,c,d,e,f,g,h) { a,b,c,d,e,f,g,h } -#define I9(a,b,c,d,e,f,g,h,i) { a,b,c,d,e,f,g,h,i } -#define ASSERT_BYTES(s, b) \ - do \ - { \ - static const uint8_t expected_bytes[] = b; \ - ASSERT_EQ(sizeof(expected_bytes), s.size()); \ - ASSERT_TRUE(memcmp(s.data(), (const char *) expected_bytes, \ - sizeof(expected_bytes)) == 0); \ - } \ - while(0) - -class Append: public SectionFixture, public Test { }; - -TEST_F(Append, Bytes) { - section.Append(data, sizeof(data)); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_EQ(sizeof(data), contents.size()); - EXPECT_TRUE(0 == memcmp(contents.data(), (const char *) data, sizeof(data))); -} - -TEST_F(Append, BytesTwice) { - section.Append(data, sizeof(data)); - section.Append(data, sizeof(data)); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_EQ(2 * sizeof(data), contents.size()); - ASSERT_TRUE(0 == memcmp(contents.data(), (const char *) data, sizeof(data))); - ASSERT_TRUE(0 == memcmp(contents.data() + sizeof(data), - (const char *) data, sizeof(data))); -} - -TEST_F(Append, String) { - string s1 = "howdy "; - string s2 = "there"; - section.Append(s1); - section.Append(s2); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_STREQ(contents.c_str(), "howdy there"); -} - -TEST_F(Append, CString) { - section.AppendCString("howdy"); - section.AppendCString(""); - section.AppendCString("there"); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_EQ(string("howdy\0\0there\0", 13), contents); -} - -TEST_F(Append, CStringSize) { - section.AppendCString("howdy", 3); - section.AppendCString("there", 5); - section.AppendCString("fred", 6); - section.AppendCString("natalie", 0); - section.AppendCString("", 10); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_EQ(string("howtherefred\0\0\0\0\0\0\0\0\0\0\0\0", 24), contents); -} - -TEST_F(Append, RepeatedBytes) { - section.Append((size_t) 10, '*'); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_STREQ(contents.c_str(), "**********"); -} - -TEST_F(Append, GeneralLE1) { - section.Append(kLittleEndian, 1, 42); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I1(42)); -} - -TEST_F(Append, GeneralLE2) { - section.Append(kLittleEndian, 2, 0x15a1); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0xa1, 0x15)); -} - -TEST_F(Append, GeneralLE3) { - section.Append(kLittleEndian, 3, 0x59ae8d); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x8d, 0xae, 0x59)); -} - -TEST_F(Append, GeneralLE4) { - section.Append(kLittleEndian, 4, 0x51603c56); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I4(0x56, 0x3c, 0x60, 0x51)); -} - -TEST_F(Append, GeneralLE5) { - section.Append(kLittleEndian, 5, 0x385e2803b4ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0xb4, 0x03, 0x28, 0x5e, 0x38)); -} - -TEST_F(Append, GeneralLE6) { - section.Append(kLittleEndian, 6, 0xc7db9534dd1fULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I6(0x1f, 0xdd, 0x34, 0x95, 0xdb, 0xc7)); -} - -TEST_F(Append, GeneralLE7) { - section.Append(kLittleEndian, 7, 0x1445c9f1b843e6ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I7(0xe6, 0x43, 0xb8, 0xf1, 0xc9, 0x45, 0x14)); -} - -TEST_F(Append, GeneralLE8) { - section.Append(kLittleEndian, 8, 0xaf48019dfe5c01e5ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I8(0xe5, 0x01, 0x5c, 0xfe, 0x9d, 0x01, 0x48, 0xaf)); -} - -TEST_F(Append, GeneralBE1) { - section.Append(kBigEndian, 1, 0xd0ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I1(0xd0)); -} - -TEST_F(Append, GeneralBE2) { - section.Append(kBigEndian, 2, 0x2e7eULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2e, 0x7e)); -} - -TEST_F(Append, GeneralBE3) { - section.Append(kBigEndian, 3, 0x37dad6ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x37, 0xda, 0xd6)); -} - -TEST_F(Append, GeneralBE4) { - section.Append(kBigEndian, 4, 0x715935c7ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I4(0x71, 0x59, 0x35, 0xc7)); -} - -TEST_F(Append, GeneralBE5) { - section.Append(kBigEndian, 5, 0x42baeb02b7ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x42, 0xba, 0xeb, 0x02, 0xb7)); -} - -TEST_F(Append, GeneralBE6) { - section.Append(kBigEndian, 6, 0xf1cdf10e7b18ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I6(0xf1, 0xcd, 0xf1, 0x0e, 0x7b, 0x18)); -} - -TEST_F(Append, GeneralBE7) { - section.Append(kBigEndian, 7, 0xf50a724f0b0d20ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I7(0xf5, 0x0a, 0x72, 0x4f, 0x0b, 0x0d, 0x20)); -} - -TEST_F(Append, GeneralBE8) { - section.Append(kBigEndian, 8, 0xa6b2cb5e98dc9c16ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I8(0xa6, 0xb2, 0xcb, 0x5e, 0x98, 0xdc, 0x9c, 0x16)); -} - -TEST_F(Append, GeneralLE1Label) { - Label l; - section.Append(kLittleEndian, 1, l); - l = 42; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I1(42)); -} - -TEST_F(Append, GeneralLE2Label) { - Label l; - section.Append(kLittleEndian, 2, l); - l = 0x15a1; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0xa1, 0x15)); -} - -TEST_F(Append, GeneralLE3Label) { - Label l; - section.Append(kLittleEndian, 3, l); - l = 0x59ae8d; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x8d, 0xae, 0x59)); -} - -TEST_F(Append, GeneralLE4Label) { - Label l; - section.Append(kLittleEndian, 4, l); - l = 0x51603c56; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I4(0x56, 0x3c, 0x60, 0x51)); -} - -TEST_F(Append, GeneralLE5Label) { - Label l; - section.Append(kLittleEndian, 5, l); - l = 0x385e2803b4ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0xb4, 0x03, 0x28, 0x5e, 0x38)); -} - -TEST_F(Append, GeneralLE6Label) { - Label l; - section.Append(kLittleEndian, 6, l); - l = 0xc7db9534dd1fULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I6(0x1f, 0xdd, 0x34, 0x95, 0xdb, 0xc7)); -} - -TEST_F(Append, GeneralLE7Label) { - Label l; - section.Append(kLittleEndian, 7, l); - l = 0x1445c9f1b843e6ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I7(0xe6, 0x43, 0xb8, 0xf1, 0xc9, 0x45, 0x14)); -} - -TEST_F(Append, GeneralLE8Label) { - Label l; - section.Append(kLittleEndian, 8, l); - l = 0xaf48019dfe5c01e5ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I8(0xe5, 0x01, 0x5c, 0xfe, 0x9d, 0x01, 0x48, 0xaf)); -} - -TEST_F(Append, GeneralBE1Label) { - Label l; - section.Append(kBigEndian, 1, l); - l = 0xd0ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I1(0xd0)); -} - -TEST_F(Append, GeneralBE2Label) { - Label l; - section.Append(kBigEndian, 2, l); - l = 0x2e7eULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2e, 0x7e)); -} - -TEST_F(Append, GeneralBE3Label) { - Label l; - section.Append(kBigEndian, 3, l); - l = 0x37dad6ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x37, 0xda, 0xd6)); -} - -TEST_F(Append, GeneralBE4Label) { - Label l; - section.Append(kBigEndian, 4, l); - l = 0x715935c7ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I4(0x71, 0x59, 0x35, 0xc7)); -} - -TEST_F(Append, GeneralBE5Label) { - Label l; - section.Append(kBigEndian, 5, l); - l = 0x42baeb02b7ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x42, 0xba, 0xeb, 0x02, 0xb7)); -} - -TEST_F(Append, GeneralBE6Label) { - Label l; - section.Append(kBigEndian, 6, l); - l = 0xf1cdf10e7b18ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I6(0xf1, 0xcd, 0xf1, 0x0e, 0x7b, 0x18)); -} - -TEST_F(Append, GeneralBE7Label) { - Label l; - section.Append(kBigEndian, 7, l); - l = 0xf50a724f0b0d20ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I7(0xf5, 0x0a, 0x72, 0x4f, 0x0b, 0x0d, 0x20)); -} - -TEST_F(Append, GeneralBE8Label) { - Label l; - section.Append(kBigEndian, 8, l); - l = 0xa6b2cb5e98dc9c16ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I8(0xa6, 0xb2, 0xcb, 0x5e, 0x98, 0xdc, 0x9c, 0x16)); -} - -TEST_F(Append, B8) { - section.Append(1, 0x2a); - section.B8(0xd3U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0xd3)); -} - -TEST_F(Append, B8Label) { - Label l; - section.Append(1, 0x2a); - section.B8(l); - l = 0x4bU; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0x4b)); -} - -TEST_F(Append, B16) { - section.Append(1, 0x2a); - section.B16(0x472aU); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x47, 0x2a)); -} - -TEST_F(Append, B16Label) { - Label l; - section.Append(1, 0x2a); - section.B16(l); - l = 0x55e8U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x55, 0xe8)); -} - -TEST_F(Append, B32) { - section.Append(1, 0x2a); - section.B32(0xbd412cbcU); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0xbd, 0x41, 0x2c, 0xbc)); -} - -TEST_F(Append, B32Label) { - Label l; - section.Append(1, 0x2a); - section.B32(l); - l = 0x208e37d5U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0x20, 0x8e, 0x37, 0xd5)); -} - -TEST_F(Append, B64) { - section.Append(1, 0x2a); - section.B64(0x3402a013111e68adULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0x34, 0x02, 0xa0, 0x13, 0x11, 0x1e, 0x68, 0xad)); -} - -TEST_F(Append, B64Label) { - Label l; - section.Append(1, 0x2a); - section.B64(l); - l = 0x355dbfbb4ac6d57fULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0x35, 0x5d, 0xbf, 0xbb, 0x4a, 0xc6, 0xd5, 0x7f)); -} - -TEST_F(Append, L8) { - section.Append(1, 0x2a); - section.L8(0x26U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0x26)); -} - -TEST_F(Append, L8Label) { - Label l; - section.Append(1, 0x2a); - section.L8(l); - l = 0xa8U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0xa8)); -} - -TEST_F(Append, L16) { - section.Append(1, 0x2a); - section.L16(0xca6dU); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x6d, 0xca)); -} - -TEST_F(Append, L16Label) { - Label l; - section.Append(1, 0x2a); - section.L16(l); - l = 0xd21fU; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x1f, 0xd2)); -} - -TEST_F(Append, L32) { - section.Append(1, 0x2a); - section.L32(0x558f6181U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0x81, 0x61, 0x8f, 0x55)); -} - -TEST_F(Append, L32Label) { - Label l; - section.Append(1, 0x2a); - section.L32(l); - l = 0x4b810f82U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0x82, 0x0f, 0x81, 0x4b)); -} - -TEST_F(Append, L64) { - section.Append(1, 0x2a); - section.L64(0x564384f7579515bfULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0xbf, 0x15, 0x95, 0x57, 0xf7, 0x84, 0x43, 0x56)); -} - -TEST_F(Append, L64Label) { - Label l; - section.Append(1, 0x2a); - section.L64(l); - l = 0x424b1d020667c8dbULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0xdb, 0xc8, 0x67, 0x06, 0x02, 0x1d, 0x4b, 0x42)); -} - -TEST_F(Append, D8Big) { - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D8(0xe6U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0xe6)); -} - -TEST_F(Append, D8BigLabel) { - Label l; - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D8(l); - l = 0xeeU; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0xee)); -} - -TEST_F(Append, D16Big) { - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D16(0x83b1U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x83, 0xb1)); -} - -TEST_F(Append, D16BigLabel) { - Label l; - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D16(l); - l = 0x5b55U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x5b, 0x55)); -} - -TEST_F(Append, D32Big) { - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D32(0xd0b0e431U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0xd0, 0xb0, 0xe4, 0x31)); -} - -TEST_F(Append, D32BigLabel) { - Label l; - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D32(l); - l = 0x312fb340U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0x31, 0x2f, 0xb3, 0x40)); -} - -TEST_F(Append, D64Big) { - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D64(0xb109843500dbcb16ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0xb1, 0x09, 0x84, 0x35, 0x00, 0xdb, 0xcb, 0x16)); -} - -TEST_F(Append, D64BigLabel) { - Label l; - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D64(l); - l = 0x9a0d61b70f671fd7ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0x9a, 0x0d, 0x61, 0xb7, 0x0f, 0x67, 0x1f, 0xd7)); -} - -TEST_F(Append, D8Little) { - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D8(0x42U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0x42)); -} - -TEST_F(Append, D8LittleLabel) { - Label l; - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D8(l); - l = 0x05U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0x05)); -} - -TEST_F(Append, D16Little) { - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D16(0xc5c5U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0xc5, 0xc5)); -} - -TEST_F(Append, D16LittleLabel) { - Label l; - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D16(l); - l = 0xb620U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x20, 0xb6)); -} - -TEST_F(Append, D32Little) { - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D32(0x1a87d0feU); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0xfe, 0xd0, 0x87, 0x1a)); -} - -TEST_F(Append, D32LittleLabel) { - Label l; - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D32(l); - l = 0xb8012d6bU; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0x6b, 0x2d, 0x01, 0xb8)); -} - -TEST_F(Append, D64Little) { - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D64(0x42de75c61375a1deULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0xde, 0xa1, 0x75, 0x13, 0xc6, 0x75, 0xde, 0x42)); -} - -TEST_F(Append, D64LittleLabel) { - Label l; - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D64(l); - l = 0x8b3bececf3fb5312ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0x12, 0x53, 0xfb, 0xf3, 0xec, 0xec, 0x3b, 0x8b)); -} - -TEST_F(Append, Variety) { - Label a, b, c, d, e, f, g, h; - section.Append(kBigEndian, 1, a) - .Append(kLittleEndian, 8, h) - .Append(kBigEndian, 1, 0x8bULL) - .Append(kLittleEndian, 8, 0x0ea56540448f4439ULL) - .Append(kBigEndian, 2, b) - .Append(kLittleEndian, 7, g) - .Append(kBigEndian, 2, 0xcf15ULL) - .Append(kLittleEndian, 7, 0x29694f04c5724aULL) - .Append(kBigEndian, 3, c) - .Append(kLittleEndian, 6, f) - .Append(kBigEndian, 3, 0x8c3ffdULL) - .Append(kLittleEndian, 6, 0x6f11ba80187aULL) - .Append(kBigEndian, 4, d) - .Append(kLittleEndian, 5, e) - .Append(kBigEndian, 4, 0x2fda2472ULL) - .Append(kLittleEndian, 5, 0x0aa02d423fULL) - .Append(kBigEndian, 5, e) - .Append(kLittleEndian, 4, d) - .Append(kBigEndian, 5, 0x53ba432138ULL) - .Append(kLittleEndian, 4, 0xf139ae60ULL) - .Append(kBigEndian, 6, f) - .Append(kLittleEndian, 3, c) - .Append(kBigEndian, 6, 0x168e436af716ULL) - .Append(kLittleEndian, 3, 0x3ef189ULL) - .Append(kBigEndian, 7, g) - .Append(kLittleEndian, 2, b) - .Append(kBigEndian, 7, 0xacd4ef233e47d9ULL) - .Append(kLittleEndian, 2, 0x5311ULL) - .Append(kBigEndian, 8, h) - .Append(kLittleEndian, 1, a) - .Append(kBigEndian, 8, 0x4668d5f1c93637a1ULL) - .Append(kLittleEndian, 1, 0x65ULL); - a = 0x79ac9bd8aa256b35ULL; - b = 0x22d13097ef86c91cULL; - c = 0xf204968b0a05862fULL; - d = 0x163177f15a0eb4ecULL; - e = 0xbd1b0f1d977f2246ULL; - f = 0x2b0842eee83c6461ULL; - g = 0x92f4b928a4bf875eULL; - h = 0x61a199a8f7286ba6ULL; - ASSERT_EQ(8 * 18U, section.Size()); - ASSERT_TRUE(section.GetContents(&contents)); - - static const uint8_t expected[] = { - 0x35, 0xa6, 0x6b, 0x28, 0xf7, 0xa8, 0x99, 0xa1, 0x61, - 0x8b, 0x39, 0x44, 0x8f, 0x44, 0x40, 0x65, 0xa5, 0x0e, - 0xc9, 0x1c, 0x5e, 0x87, 0xbf, 0xa4, 0x28, 0xb9, 0xf4, - 0xcf, 0x15, 0x4a, 0x72, 0xc5, 0x04, 0x4f, 0x69, 0x29, - 0x05, 0x86, 0x2f, 0x61, 0x64, 0x3c, 0xe8, 0xee, 0x42, - 0x8c, 0x3f, 0xfd, 0x7a, 0x18, 0x80, 0xba, 0x11, 0x6f, - 0x5a, 0x0e, 0xb4, 0xec, 0x46, 0x22, 0x7f, 0x97, 0x1d, - 0x2f, 0xda, 0x24, 0x72, 0x3f, 0x42, 0x2d, 0xa0, 0x0a, - 0x1d, 0x97, 0x7f, 0x22, 0x46, 0xec, 0xb4, 0x0e, 0x5a, - 0x53, 0xba, 0x43, 0x21, 0x38, 0x60, 0xae, 0x39, 0xf1, - 0x42, 0xee, 0xe8, 0x3c, 0x64, 0x61, 0x2f, 0x86, 0x05, - 0x16, 0x8e, 0x43, 0x6a, 0xf7, 0x16, 0x89, 0xf1, 0x3e, - 0xf4, 0xb9, 0x28, 0xa4, 0xbf, 0x87, 0x5e, 0x1c, 0xc9, - 0xac, 0xd4, 0xef, 0x23, 0x3e, 0x47, 0xd9, 0x11, 0x53, - 0x61, 0xa1, 0x99, 0xa8, 0xf7, 0x28, 0x6b, 0xa6, 0x35, - 0x46, 0x68, 0xd5, 0xf1, 0xc9, 0x36, 0x37, 0xa1, 0x65, - }; - - ASSERT_TRUE(0 == memcmp(contents.data(), expected, sizeof(expected))); -} - -TEST_F(Append, Section) { - section.Append("murder"); - { - Section middle; - middle.Append(" she"); - section.Append(middle); - } - section.Append(" wrote"); - EXPECT_EQ(16U, section.Size()); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_STREQ(contents.c_str(), "murder she wrote"); -} - -TEST_F(Append, SectionRefs) { - section.Append("sugar "); - Label l; - { - Section middle; - Label m; - middle.B32(m); - section.Append(middle); - m = 0x66726565; - } - section.Append(" jazz"); - EXPECT_EQ(15U, section.Size()); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_STREQ(contents.c_str(), "sugar free jazz"); -} - -TEST_F(Append, LEB128_0) { - section.LEB128(0); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\0", 1), contents); -} - -TEST_F(Append, LEB128_0x3f) { - section.LEB128(0x3f); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x3f", 1), contents); -} - -TEST_F(Append, LEB128_0x40) { - section.LEB128(0x40); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xc0\x00", 2), contents); -} - -TEST_F(Append, LEB128_0x7f) { - section.LEB128(0x7f); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x00", 2), contents); -} - -TEST_F(Append, LEB128_0x80) { - section.LEB128(0x80); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x01", 2), contents); -} - -TEST_F(Append, LEB128_0xff) { - section.LEB128(0xff); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x01", 2), contents); -} - -TEST_F(Append, LEB128_0x1fff) { - section.LEB128(0x1fff); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x3f", 2), contents); -} - -TEST_F(Append, LEB128_0x2000) { - section.LEB128(0x2000); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\xc0\x00", 3), contents); -} - -TEST_F(Append, LEB128_n1) { - section.LEB128(-1); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x7f", 1), contents); -} - -TEST_F(Append, LEB128_n0x40) { - section.LEB128(-0x40); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x40", 1), contents); -} - -TEST_F(Append, LEB128_n0x41) { - section.LEB128(-0x41); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xbf\x7f", 2), contents); -} - -TEST_F(Append, LEB128_n0x7f) { - section.LEB128(-0x7f); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x81\x7f", 2), contents); -} - -TEST_F(Append, LEB128_n0x80) { - section.LEB128(-0x80); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x7f", 2), contents); -} - -TEST_F(Append, LEB128_n0x2000) { - section.LEB128(-0x2000); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x40", 2), contents); -} - -TEST_F(Append, LEB128_n0x2001) { - section.LEB128(-0x2001); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\xbf\x7f", 3), contents); -} - -TEST_F(Append,ULEB128_0) { - section.ULEB128(0); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\0", 1), contents); -} - -TEST_F(Append,ULEB128_1) { - section.ULEB128(1); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x01", 1), contents); -} - -TEST_F(Append,ULEB128_0x3f) { - section.ULEB128(0x3f); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x3f", 1), contents); -} - -TEST_F(Append,ULEB128_0x40) { - section.ULEB128(0x40); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x40", 1), contents); -} - -TEST_F(Append,ULEB128_0x7f) { - section.ULEB128(0x7f); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x7f", 1), contents); -} - -TEST_F(Append,ULEB128_0x80) { - section.ULEB128(0x80); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x01", 2), contents); -} - -TEST_F(Append,ULEB128_0xff) { - section.ULEB128(0xff); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x01", 2), contents); -} - -TEST_F(Append,ULEB128_0x100) { - section.ULEB128(0x100); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x02", 2), contents); -} - -TEST_F(Append,ULEB128_0x1fff) { - section.ULEB128(0x1fff); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x3f", 2), contents); -} - -TEST_F(Append,ULEB128_0x2000) { - section.ULEB128(0x2000); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x40", 2), contents); -} - -TEST_F(Append,ULEB128_0x3fff) { - section.ULEB128(0x3fff); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x7f", 2), contents); -} - -TEST_F(Append,ULEB128_0x4000) { - section.ULEB128(0x4000); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x80\x01", 3), contents); -} - -TEST_F(Append,ULEB128_12857) { - section.ULEB128(12857); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xb9\x64", 2), contents); -} - -TEST_F(Append, LEBChain) { - section.LEB128(-0x80).ULEB128(12857).Append("*"); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x7f\xb9\x64*", 5), contents); -} - - -class GetContents: public SectionFixture, public Test { }; - -TEST_F(GetContents, Undefined) { - Label l; - section.Append(kLittleEndian, 8, l); - ASSERT_FALSE(section.GetContents(&contents)); -} - -TEST_F(GetContents, ClearsContents) { - section.Append((size_t) 10, '*'); - EXPECT_EQ(10U, section.Size()); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(0U, section.Size()); -} - -TEST_F(GetContents, ClearsReferences) { - Label l; - section.Append(kBigEndian, 1, l); - l = 42; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I1(42)); - ASSERT_TRUE(section.GetContents(&contents)); // should not die -} - -class Miscellanea: public SectionFixture, public Test { }; - -TEST_F(Miscellanea, Clear) { - section.Append("howdy"); - Label l; - section.L32(l); - EXPECT_EQ(9U, section.Size()); - section.Clear(); - EXPECT_EQ(0U, section.Size()); - l = 0x8d231bf0U; - ASSERT_TRUE(section.GetContents(&contents)); // should not die -} - -TEST_F(Miscellanea, Align) { - section.Append("*"); - EXPECT_EQ(1U, section.Size()); - section.Align(4).Append("*"); - EXPECT_EQ(5U, section.Size()); - section.Append("*").Align(2); - EXPECT_EQ(6U, section.Size()); -} - -TEST_F(Miscellanea, AlignPad) { - section.Append("*"); - EXPECT_EQ(1U, section.Size()); - section.Align(4, ' ').Append("*"); - EXPECT_EQ(5U, section.Size()); - section.Append("*").Align(2, ' '); - EXPECT_EQ(6U, section.Size()); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_EQ(string("* **"), contents); -} - -TEST_F(Miscellanea, StartHereMark) { - Label m; - section.Append(42, ' ').Mark(&m).Append(13, '+'); - EXPECT_EQ(42U, m - section.start()); - EXPECT_EQ(42U + 13U, section.Here() - section.start()); - EXPECT_FALSE(section.start().IsKnownConstant()); - EXPECT_FALSE(m.IsKnownConstant()); - EXPECT_FALSE(section.Here().IsKnownConstant()); -} - -TEST_F(Miscellanea, Endianness) { - section.set_endianness(kBigEndian); - EXPECT_EQ(kBigEndian, section.endianness()); - section.set_endianness(kLittleEndian); - EXPECT_EQ(kLittleEndian, section.endianness()); -} diff --git a/breakpad/common/using_std_string.h b/breakpad/common/using_std_string.h deleted file mode 100644 index 13c1da59c..000000000 --- a/breakpad/common/using_std_string.h +++ /dev/null @@ -1,65 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2012, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Ivan Penkov - -// using_std_string.h: Allows building this code in environments where -// global string (::string) exists. -// -// The problem: -// ------------- -// Let's say you want to build this code in an environment where a global -// string type is defined (i.e. ::string). Now, let's suppose that ::string -// is different that std::string and you'd like to have the option to easily -// choose between the two string types. Ideally you'd like to control which -// string type is chosen by simply #defining an identifier. -// -// The solution: -// ------------- -// #define HAS_GLOBAL_STRING somewhere in a global header file and then -// globally replace std::string with string. Then include this header -// file everywhere where string is used. If you want to revert back to -// using std::string, simply remove the #define (HAS_GLOBAL_STRING). - -#ifndef THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_ -#define THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_ - -#ifdef HAS_GLOBAL_STRING - typedef ::string google_breakpad_string; -#else - using std::string; - typedef std::string google_breakpad_string; -#endif - -// Inicates that type google_breakpad_string is defined -#define HAS_GOOGLE_BREAKPAD_STRING - -#endif // THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_ diff --git a/breakpad/common/windows/dia_util.cc b/breakpad/common/windows/dia_util.cc deleted file mode 100644 index 5322997d8..000000000 --- a/breakpad/common/windows/dia_util.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "common/windows/dia_util.h" - -#include - -namespace google_breakpad { - -bool FindDebugStream(const wchar_t* name, - IDiaSession* session, - IDiaEnumDebugStreamData** debug_stream) { - CComPtr enum_debug_streams; - if (FAILED(session->getEnumDebugStreams(&enum_debug_streams))) { - fprintf(stderr, "IDiaSession::getEnumDebugStreams failed\n"); - return false; - } - - CComPtr temp_debug_stream; - ULONG fetched = 0; - while (SUCCEEDED(enum_debug_streams->Next(1, &temp_debug_stream, &fetched)) && - fetched == 1) { - CComBSTR stream_name; - if (FAILED(temp_debug_stream->get_name(&stream_name))) { - fprintf(stderr, "IDiaEnumDebugStreamData::get_name failed\n"); - return false; - } - - // Found the stream? - if (wcsncmp((LPWSTR)stream_name, name, stream_name.Length()) == 0) { - *debug_stream = temp_debug_stream.Detach(); - return true; - } - - temp_debug_stream.Release(); - } - - // No table was found. - return false; -} - -bool FindTable(REFIID iid, IDiaSession* session, void** table) { - // Get the table enumerator. - CComPtr enum_tables; - if (FAILED(session->getEnumTables(&enum_tables))) { - fprintf(stderr, "IDiaSession::getEnumTables failed\n"); - return false; - } - - // Iterate through the tables. - CComPtr temp_table; - ULONG fetched = 0; - while (SUCCEEDED(enum_tables->Next(1, &temp_table, &fetched)) && - fetched == 1) { - void* temp = NULL; - if (SUCCEEDED(temp_table->QueryInterface(iid, &temp))) { - *table = temp; - return true; - } - temp_table.Release(); - } - - // The table was not found. - return false; -} - -} // namespace google_breakpad diff --git a/breakpad/common/windows/dia_util.h b/breakpad/common/windows/dia_util.h deleted file mode 100644 index 3c0926095..000000000 --- a/breakpad/common/windows/dia_util.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Utilities for loading debug streams and tables from a PDB file. - -#include -#include - -namespace google_breakpad { - -// Find the debug stream of the given |name| in the given |session|. Returns -// true on success, false on error of if the stream does not exist. On success -// the stream will be returned via |debug_stream|. -bool FindDebugStream(const wchar_t* name, - IDiaSession* session, - IDiaEnumDebugStreamData** debug_stream); - -// Finds the first table implementing the COM interface with ID |iid| in the -// given |session|. Returns true on success, false on error or if no such -// table is found. On success the table will be returned via |table|. -bool FindTable(REFIID iid, IDiaSession* session, void** table); - -// A templated version of FindTable. Finds the first table implementing type -// |InterfaceType| in the given |session|. Returns true on success, false on -// error or if no such table is found. On success the table will be returned via -// |table|. -template -bool FindTable(IDiaSession* session, InterfaceType** table) { - return FindTable(__uuidof(InterfaceType), - session, - reinterpret_cast(table)); -} - -} // namespace google_breakpad diff --git a/breakpad/common/windows/omap.cc b/breakpad/common/windows/omap.cc deleted file mode 100644 index 39e4722b3..000000000 --- a/breakpad/common/windows/omap.cc +++ /dev/null @@ -1,694 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This contains a suite of tools for transforming symbol information when -// when that information has been extracted from a PDB containing OMAP -// information. - -// OMAP information is a lightweight description of a mapping between two -// address spaces. It consists of two streams, each of them a vector 2-tuples. -// The OMAPTO stream contains tuples of the form -// -// (RVA in transformed image, RVA in original image) -// -// while the OMAPFROM stream contains tuples of the form -// -// (RVA in original image, RVA in transformed image) -// -// The entries in each vector are sorted by the first value of the tuple, and -// the lengths associated with a mapping are implicit as the distance between -// two successive addresses in the vector. - -// Consider a trivial 10-byte function described by the following symbol: -// -// Function: RVA 0x00001000, length 10, "foo" -// -// Now consider the same function, but with 5-bytes of instrumentation injected -// at offset 5. The OMAP streams describing this would look like: -// -// OMAPTO : [ [0x00001000, 0x00001000], -// [0x00001005, 0xFFFFFFFF], -// [0x0000100a, 0x00001005] ] -// OMAPFROM: [ [0x00001000, 0x00001000], -// [0x00001005, 0x0000100a] ] -// -// In this case the injected code has been marked as not originating in the -// source image, and thus it will have no symbol information at all. However, -// the injected code may also be associated with an original address range; -// for example, when prepending instrumentation to a basic block the -// instrumentation can be labelled as originating from the same source BB such -// that symbol resolution will still find the appropriate source code line -// number. In this case the OMAP stream would look like: -// -// OMAPTO : [ [0x00001000, 0x00001000], -// [0x00001005, 0x00001005], -// [0x0000100a, 0x00001005] ] -// OMAPFROM: [ [0x00001000, 0x00001000], -// [0x00001005, 0x0000100a] ] -// -// Suppose we asked DIA to lookup the symbol at location 0x0000100a of the -// instrumented image. It would first run this through the OMAPTO table and -// translate that address to 0x00001005. It would then lookup the symbol -// at that address and return the symbol for the function "foo". This is the -// correct result. -// -// However, if we query DIA for the length and address of the symbol it will -// tell us that it has length 10 and is at RVA 0x00001000. The location is -// correct, but the length doesn't take into account the 5-bytes of injected -// code. Symbol resolution works (starting from an instrumented address, -// mapping to an original address, and looking up a symbol), but the symbol -// metadata is incorrect. -// -// If we dump the symbols using DIA they will have their addresses -// appropriately transformed and reflect positions in the instrumented image. -// However, if we try to do a lookup using those symbols resolution can fail. -// For example, the address 0x0000100a will not map to the symbol for "foo", -// because DIA tells us it is at location 0x00001000 (correct) with length -// 10 (incorrect). The problem is one of order of operations: in this case -// we're attempting symbol resolution by looking up an instrumented address -// in the table of translated symbols. -// -// One way to handle this is to dump the OMAP information as part of the -// breakpad symbols. This requires the rest of the toolchain to be aware of -// OMAP information and to use it when present prior to performing lookup. The -// other option is to properly transform the symbols (updating length as well as -// position) so that resolution will work as expected for translated addresses. -// This is transparent to the rest of the toolchain. - -#include "common/windows/omap.h" - -#include - -#include -#include -#include - -#include "common/windows/dia_util.h" - -namespace google_breakpad { - -namespace { - -static const wchar_t kOmapToDebugStreamName[] = L"OMAPTO"; -static const wchar_t kOmapFromDebugStreamName[] = L"OMAPFROM"; - -// Dependending on where this is used in breakpad we sometimes get min/max from -// windef, and other times from algorithm. To get around this we simply -// define our own min/max functions. -template -const T& Min(const T& t1, const T& t2) { return t1 < t2 ? t1 : t2; } -template -const T& Max(const T& t1, const T& t2) { return t1 > t2 ? t1 : t2; } - -// It makes things more readable to have two different OMAP types. We cast -// normal OMAPs into these. They must be the same size as the OMAP structure -// for this to work, hence the static asserts. -struct OmapOrigToTran { - DWORD rva_original; - DWORD rva_transformed; -}; -struct OmapTranToOrig { - DWORD rva_transformed; - DWORD rva_original; -}; -static_assert(sizeof(OmapOrigToTran) == sizeof(OMAP), - "OmapOrigToTran must have same size as OMAP."); -static_assert(sizeof(OmapTranToOrig) == sizeof(OMAP), - "OmapTranToOrig must have same size as OMAP."); -typedef std::vector OmapFromTable; -typedef std::vector OmapToTable; - -// Used for sorting and searching through a Mapping. -bool MappedRangeOriginalLess(const MappedRange& lhs, const MappedRange& rhs) { - if (lhs.rva_original < rhs.rva_original) - return true; - if (lhs.rva_original > rhs.rva_original) - return false; - return lhs.length < rhs.length; -} -bool MappedRangeMappedLess(const MappedRange& lhs, const MappedRange& rhs) { - if (lhs.rva_transformed < rhs.rva_transformed) - return true; - if (lhs.rva_transformed > rhs.rva_transformed) - return false; - return lhs.length < rhs.length; -} - -// Used for searching through the EndpointIndexMap. -bool EndpointIndexLess(const EndpointIndex& ei1, const EndpointIndex& ei2) { - return ei1.endpoint < ei2.endpoint; -} - -// Finds the debug stream with the given |name| in the given |session|, and -// populates |table| with its contents. Casts the data directly into OMAP -// structs. -bool FindAndLoadOmapTable(const wchar_t* name, - IDiaSession* session, - OmapTable* table) { - assert(name != NULL); - assert(session != NULL); - assert(table != NULL); - - CComPtr stream; - if (!FindDebugStream(name, session, &stream)) - return false; - assert(stream.p != NULL); - - LONG count = 0; - if (FAILED(stream->get_Count(&count))) { - fprintf(stderr, "IDiaEnumDebugStreamData::get_Count failed for stream " - "\"%ws\"\n", name); - return false; - } - - // Get the length of the stream in bytes. - DWORD bytes_read = 0; - ULONG count_read = 0; - if (FAILED(stream->Next(count, 0, &bytes_read, NULL, &count_read))) { - fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading " - "length of stream \"%ws\"\n", name); - return false; - } - - // Ensure it's consistent with the OMAP data type. - DWORD bytes_expected = count * sizeof(OmapTable::value_type); - if (count * sizeof(OmapTable::value_type) != bytes_read) { - fprintf(stderr, "DIA debug stream \"%ws\" has an unexpected length", name); - return false; - } - - // Read the table. - table->resize(count); - bytes_read = 0; - count_read = 0; - if (FAILED(stream->Next(count, bytes_expected, &bytes_read, - reinterpret_cast(&table->at(0)), - &count_read))) { - fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading " - "data from stream \"%ws\"\n"); - return false; - } - - return true; -} - -// This determines the original image length by looking through the segment -// table. -bool GetOriginalImageLength(IDiaSession* session, DWORD* image_length) { - assert(session != NULL); - assert(image_length != NULL); - - CComPtr enum_segments; - if (!FindTable(session, &enum_segments)) - return false; - assert(enum_segments.p != NULL); - - DWORD temp_image_length = 0; - CComPtr segment; - ULONG fetched = 0; - while (SUCCEEDED(enum_segments->Next(1, &segment, &fetched)) && - fetched == 1) { - assert(segment.p != NULL); - - DWORD rva = 0; - DWORD length = 0; - DWORD frame = 0; - if (FAILED(segment->get_relativeVirtualAddress(&rva)) || - FAILED(segment->get_length(&length)) || - FAILED(segment->get_frame(&frame))) { - fprintf(stderr, "Failed to get basic properties for IDiaSegment\n"); - return false; - } - - if (frame > 0) { - DWORD segment_end = rva + length; - if (segment_end > temp_image_length) - temp_image_length = segment_end; - } - segment.Release(); - } - - *image_length = temp_image_length; - return true; -} - -// Detects regions of the original image that have been removed in the -// transformed image, and sets the 'removed' property on all mapped ranges -// immediately preceding a gap. The mapped ranges must be sorted by -// 'rva_original'. -void FillInRemovedLengths(Mapping* mapping) { - assert(mapping != NULL); - - // Find and fill gaps. We do this with two sweeps. We first sweep forward - // looking for gaps. When we identify a gap we then sweep forward with a - // second scan and set the 'removed' property for any intervals that - // immediately precede the gap. - // - // Gaps are typically between two successive intervals, but not always: - // - // Range 1: --------------- - // Range 2: ------- - // Range 3: ------------- - // Gap : ****** - // - // In the above example the gap is between range 1 and range 3. A forward - // sweep finds the gap, and a second forward sweep identifies that range 1 - // immediately precedes the gap and sets its 'removed' property. - - size_t fill = 0; - DWORD rva_front = 0; - for (size_t find = 0; find < mapping->size(); ++find) { -#ifndef NDEBUG - // We expect the mapped ranges to be sorted by 'rva_original'. - if (find > 0) { - assert(mapping->at(find - 1).rva_original <= - mapping->at(find).rva_original); - } -#endif - - if (rva_front < mapping->at(find).rva_original) { - // We've found a gap. Fill it in by setting the 'removed' property for - // any affected intervals. - DWORD removed = mapping->at(find).rva_original - rva_front; - for (; fill < find; ++fill) { - if (mapping->at(fill).rva_original + mapping->at(fill).length != - rva_front) { - continue; - } - - // This interval ends right where the gap starts. It needs to have its - // 'removed' information filled in. - mapping->at(fill).removed = removed; - } - } - - // Advance the front that indicates the covered portion of the image. - rva_front = mapping->at(find).rva_original + mapping->at(find).length; - } -} - -// Builds a unified view of the mapping between the original and transformed -// image space by merging OMAPTO and OMAPFROM data. -void BuildMapping(const OmapData& omap_data, Mapping* mapping) { - assert(mapping != NULL); - - mapping->clear(); - - if (omap_data.omap_from.empty() || omap_data.omap_to.empty()) - return; - - // The names 'omap_to' and 'omap_from' are awfully confusing, so we make - // ourselves more explicit here. This cast is only safe because the underlying - // types have the exact same size. - const OmapToTable& tran2orig = - reinterpret_cast(omap_data.omap_to); - const OmapFromTable& orig2tran = reinterpret_cast( - omap_data.omap_from); - - // Handle the range of data at the beginning of the image. This is not usually - // specified by the OMAP data. - if (tran2orig[0].rva_transformed > 0 && orig2tran[0].rva_original > 0) { - DWORD header_transformed = tran2orig[0].rva_transformed; - DWORD header_original = orig2tran[0].rva_original; - DWORD header = Min(header_transformed, header_original); - - MappedRange mr = {}; - mr.length = header; - mr.injected = header_transformed - header; - mr.removed = header_original - header; - mapping->push_back(mr); - } - - // Convert the implied lengths to explicit lengths, and infer which content - // has been injected into the transformed image. Injected content is inferred - // as regions of the transformed address space that does not map back to - // known valid content in the original image. - for (size_t i = 0; i < tran2orig.size(); ++i) { - const OmapTranToOrig& o1 = tran2orig[i]; - - // This maps to content that is outside the original image, thus it - // describes injected content. We can skip this entry. - if (o1.rva_original >= omap_data.length_original) - continue; - - // Calculate the length of the current OMAP entry. This is implicit as the - // distance between successive |rva| values, capped at the end of the - // original image. - DWORD length = 0; - if (i + 1 < tran2orig.size()) { - const OmapTranToOrig& o2 = tran2orig[i + 1]; - - // We expect the table to be sorted by rva_transformed. - assert(o1.rva_transformed <= o2.rva_transformed); - - length = o2.rva_transformed - o1.rva_transformed; - if (o1.rva_original + length > omap_data.length_original) { - length = omap_data.length_original - o1.rva_original; - } - } else { - length = omap_data.length_original - o1.rva_original; - } - - // Zero-length entries don't describe anything and can be ignored. - if (length == 0) - continue; - - // Any gaps in the transformed address-space are due to injected content. - if (!mapping->empty()) { - MappedRange& prev_mr = mapping->back(); - prev_mr.injected += o1.rva_transformed - - (prev_mr.rva_transformed + prev_mr.length); - } - - MappedRange mr = {}; - mr.rva_original = o1.rva_original; - mr.rva_transformed = o1.rva_transformed; - mr.length = length; - mapping->push_back(mr); - } - - // Sort based on the original image addresses. - std::sort(mapping->begin(), mapping->end(), MappedRangeOriginalLess); - - // Fill in the 'removed' lengths by looking for gaps in the coverage of the - // original address space. - FillInRemovedLengths(mapping); - - return; -} - -void BuildEndpointIndexMap(ImageMap* image_map) { - assert(image_map != NULL); - - if (image_map->mapping.size() == 0) - return; - - const Mapping& mapping = image_map->mapping; - EndpointIndexMap& eim = image_map->endpoint_index_map; - - // Get the unique set of interval endpoints. - std::set endpoints; - for (size_t i = 0; i < mapping.size(); ++i) { - endpoints.insert(mapping[i].rva_original); - endpoints.insert(mapping[i].rva_original + - mapping[i].length + - mapping[i].removed); - } - - // Use the endpoints to initialize the secondary search structure for the - // mapping. - eim.resize(endpoints.size()); - std::set::const_iterator it = endpoints.begin(); - for (size_t i = 0; it != endpoints.end(); ++it, ++i) { - eim[i].endpoint = *it; - eim[i].index = mapping.size(); - } - - // For each endpoint we want the smallest index of any interval containing - // it. We iterate over the intervals and update the indices associated with - // each interval endpoint contained in the current interval. In the general - // case of an arbitrary set of intervals this is O(n^2), but the structure of - // OMAP data makes this O(n). - for (size_t i = 0; i < mapping.size(); ++i) { - EndpointIndex ei1 = { mapping[i].rva_original, 0 }; - EndpointIndexMap::iterator it1 = std::lower_bound( - eim.begin(), eim.end(), ei1, EndpointIndexLess); - - EndpointIndex ei2 = { mapping[i].rva_original + mapping[i].length + - mapping[i].removed, 0 }; - EndpointIndexMap::iterator it2 = std::lower_bound( - eim.begin(), eim.end(), ei2, EndpointIndexLess); - - for (; it1 != it2; ++it1) - it1->index = Min(i, it1->index); - } -} - -// Clips the given mapped range. -void ClipMappedRangeOriginal(const AddressRange& clip_range, - MappedRange* mapped_range) { - assert(mapped_range != NULL); - - // The clipping range is entirely outside of the mapped range. - if (clip_range.end() <= mapped_range->rva_original || - mapped_range->rva_original + mapped_range->length + - mapped_range->removed <= clip_range.rva) { - mapped_range->length = 0; - mapped_range->injected = 0; - mapped_range->removed = 0; - return; - } - - // Clip the left side. - if (mapped_range->rva_original < clip_range.rva) { - DWORD clip_left = clip_range.rva - mapped_range->rva_original; - mapped_range->rva_original += clip_left; - mapped_range->rva_transformed += clip_left; - - if (clip_left > mapped_range->length) { - // The left clipping boundary entirely erases the content section of the - // range. - DWORD trim = clip_left - mapped_range->length; - mapped_range->length = 0; - mapped_range->injected -= Min(trim, mapped_range->injected); - // We know that trim <= mapped_range->remove. - mapped_range->removed -= trim; - } else { - // The left clipping boundary removes some, but not all, of the content. - // As such it leaves the removed/injected component intact. - mapped_range->length -= clip_left; - } - } - - // Clip the right side. - DWORD end_original = mapped_range->rva_original + mapped_range->length; - if (clip_range.end() < end_original) { - // The right clipping boundary lands in the 'content' section of the range, - // entirely clearing the injected/removed portion. - DWORD clip_right = end_original - clip_range.end(); - mapped_range->length -= clip_right; - mapped_range->injected = 0; - mapped_range->removed = 0; - return; - } else { - // The right clipping boundary is outside of the content, but may affect - // the removed/injected portion of the range. - DWORD end_removed = end_original + mapped_range->removed; - if (clip_range.end() < end_removed) - mapped_range->removed = clip_range.end() - end_original; - - DWORD end_injected = end_original + mapped_range->injected; - if (clip_range.end() < end_injected) - mapped_range->injected = clip_range.end() - end_original; - } - - return; -} - -} // namespace - -int AddressRange::Compare(const AddressRange& rhs) const { - if (end() <= rhs.rva) - return -1; - if (rhs.end() <= rva) - return 1; - return 0; -} - -bool GetOmapDataAndDisableTranslation(IDiaSession* session, - OmapData* omap_data) { - assert(session != NULL); - assert(omap_data != NULL); - - CComPtr address_map; - if (FAILED(session->QueryInterface(&address_map))) { - fprintf(stderr, "IDiaSession::QueryInterface(IDiaAddressMap) failed\n"); - return false; - } - assert(address_map.p != NULL); - - BOOL omap_enabled = FALSE; - if (FAILED(address_map->get_addressMapEnabled(&omap_enabled))) { - fprintf(stderr, "IDiaAddressMap::get_addressMapEnabled failed\n"); - return false; - } - - if (!omap_enabled) { - // We indicate the non-presence of OMAP data by returning empty tables. - omap_data->omap_from.clear(); - omap_data->omap_to.clear(); - omap_data->length_original = 0; - return true; - } - - // OMAP data is present. Disable translation. - if (FAILED(address_map->put_addressMapEnabled(FALSE))) { - fprintf(stderr, "IDiaAddressMap::put_addressMapEnabled failed\n"); - return false; - } - - // Read the OMAP streams. - if (!FindAndLoadOmapTable(kOmapFromDebugStreamName, - session, - &omap_data->omap_from)) { - return false; - } - if (!FindAndLoadOmapTable(kOmapToDebugStreamName, - session, - &omap_data->omap_to)) { - return false; - } - - // Get the lengths of the address spaces. - if (!GetOriginalImageLength(session, &omap_data->length_original)) - return false; - - return true; -} - -void BuildImageMap(const OmapData& omap_data, ImageMap* image_map) { - assert(image_map != NULL); - - BuildMapping(omap_data, &image_map->mapping); - BuildEndpointIndexMap(image_map); -} - -void MapAddressRange(const ImageMap& image_map, - const AddressRange& original_range, - AddressRangeVector* mapped_ranges) { - assert(mapped_ranges != NULL); - - const Mapping& map = image_map.mapping; - - // Handle the trivial case of an empty image_map. This means that there is - // no transformation to be applied, and we can simply return the original - // range. - if (map.empty()) { - mapped_ranges->push_back(original_range); - return; - } - - // If we get a query of length 0 we need to handle it by using a non-zero - // query length. - AddressRange query_range(original_range); - if (query_range.length == 0) - query_range.length = 1; - - // Find the range of intervals that can potentially intersect our query range. - size_t imin = 0; - size_t imax = 0; - { - // The index of the earliest possible range that can affect is us done by - // searching through the secondary indexing structure. - const EndpointIndexMap& eim = image_map.endpoint_index_map; - EndpointIndex q1 = { query_range.rva, 0 }; - EndpointIndexMap::const_iterator it1 = std::lower_bound( - eim.begin(), eim.end(), q1, EndpointIndexLess); - if (it1 == eim.end()) { - imin = map.size(); - } else { - // Backup to find the interval that contains our query point. - if (it1 != eim.begin() && query_range.rva < it1->endpoint) - --it1; - imin = it1->index; - } - - // The first range that can't possibly intersect us is found by searching - // through the image map directly as it is already sorted by interval start - // point. - MappedRange q2 = { query_range.end(), 0 }; - Mapping::const_iterator it2 = std::lower_bound( - map.begin(), map.end(), q2, MappedRangeOriginalLess); - imax = it2 - map.begin(); - } - - // Find all intervals that intersect the query range. - Mapping temp_map; - for (size_t i = imin; i < imax; ++i) { - MappedRange mr = map[i]; - ClipMappedRangeOriginal(query_range, &mr); - if (mr.length + mr.injected > 0) - temp_map.push_back(mr); - } - - // If there are no intersecting ranges then the query range has been removed - // from the image in question. - if (temp_map.empty()) - return; - - // Sort based on transformed addresses. - std::sort(temp_map.begin(), temp_map.end(), MappedRangeMappedLess); - - // Zero-length queries can't actually be merged. We simply output the set of - // unique RVAs that correspond to the query RVA. - if (original_range.length == 0) { - mapped_ranges->push_back(AddressRange(temp_map[0].rva_transformed, 0)); - for (size_t i = 1; i < temp_map.size(); ++i) { - if (temp_map[i].rva_transformed > mapped_ranges->back().rva) - mapped_ranges->push_back(AddressRange(temp_map[i].rva_transformed, 0)); - } - return; - } - - // Merge any ranges that are consecutive in the mapped image. We merge over - // injected content if it makes ranges contiguous, but we ignore any injected - // content at the tail end of a range. This allows us to detect symbols that - // have been lengthened by injecting content in the middle. However, it - // misses the case where content has been injected at the head or the tail. - // The problem is that it doesn't know whether to attribute it to the - // preceding or following symbol. It is up to the author of the transform to - // output explicit OMAP info in these cases to ensure full coverage of the - // transformed address space. - DWORD rva_begin = temp_map[0].rva_transformed; - DWORD rva_cur_content = rva_begin + temp_map[0].length; - DWORD rva_cur_injected = rva_cur_content + temp_map[0].injected; - for (size_t i = 1; i < temp_map.size(); ++i) { - if (rva_cur_injected < temp_map[i].rva_transformed) { - // This marks the end of a continuous range in the image. Output the - // current range and start a new one. - if (rva_begin < rva_cur_content) { - mapped_ranges->push_back( - AddressRange(rva_begin, rva_cur_content - rva_begin)); - } - rva_begin = temp_map[i].rva_transformed; - } - - rva_cur_content = temp_map[i].rva_transformed + temp_map[i].length; - rva_cur_injected = rva_cur_content + temp_map[i].injected; - } - - // Output the range in progress. - if (rva_begin < rva_cur_content) { - mapped_ranges->push_back( - AddressRange(rva_begin, rva_cur_content - rva_begin)); - } - - return; -} - -} // namespace google_breakpad diff --git a/breakpad/common/windows/omap.h b/breakpad/common/windows/omap.h deleted file mode 100644 index 1e023d117..000000000 --- a/breakpad/common/windows/omap.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Provides an API for mapping symbols through OMAP information, if a PDB file -// is augmented with it. This allows breakpad to work with addresses in -// transformed images by transforming the symbols themselves, rather than -// transforming addresses prior to querying symbols (the way it is typically -// done by Windows-native tools, including the DIA). - -#ifndef COMMON_WINDOWS_OMAP_H__ -#define COMMON_WINDOWS_OMAP_H__ - -#include "common/windows/omap_internal.h" - -namespace google_breakpad { - -// If the given session contains OMAP data this extracts it, populating -// |omap_data|, and then disabling automatic translation for the session. -// OMAP data is present in the PDB if |omap_data| is not empty. This returns -// true on success, false otherwise. -bool GetOmapDataAndDisableTranslation(IDiaSession* dia_session, - OmapData* omap_data); - -// Given raw OMAP data builds an ImageMap. This can be used to query individual -// image ranges using MapAddressRange. -// |omap_data|| is the OMAP data extracted from the PDB. -// |image_map| will be populated with a description of the image mapping. If -// |omap_data| is empty then this will also be empty. -void BuildImageMap(const OmapData& omap_data, ImageMap* image_map); - -// Given an address range in the original image space determines how exactly it -// has been tranformed. -// |omap_data| is the OMAP data extracted from the PDB, which must not be -// empty. -// |original_range| is the address range in the original image being queried. -// |mapped_ranges| will be populated with a full description of the mapping. -// They may be disjoint in the transformed image so a vector is needed to -// fully represent the mapping. This will be appended to if it is not -// empty. If |omap_data| is empty then |mapped_ranges| will simply be -// populated with a copy of |original_range| (the identity transform). -void MapAddressRange(const ImageMap& image_map, - const AddressRange& original_range, - AddressRangeVector* mapped_ranges); - -} // namespace google_breakpad - -#endif // COMMON_WINDOWS_OMAP_H__ diff --git a/breakpad/common/windows/omap_internal.h b/breakpad/common/windows/omap_internal.h deleted file mode 100644 index 6c37d7f87..000000000 --- a/breakpad/common/windows/omap_internal.h +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Declares internal implementation details for functionality in omap.h and -// omap.cc. - -#ifndef COMMON_WINDOWS_OMAP_INTERNAL_H__ -#define COMMON_WINDOWS_OMAP_INTERNAL_H__ - -#include -#include - -#include - -namespace google_breakpad { - -// The OMAP struct is defined by debughlp.h, which doesn't play nicely with -// imagehlp.h. We simply redefine it. -struct OMAP { - DWORD rva; - DWORD rvaTo; -}; -static_assert(sizeof(OMAP) == 8, "Wrong size for OMAP structure."); -typedef std::vector OmapTable; - -// This contains the OMAP data extracted from an image. -struct OmapData { - // The table of OMAP entries describing the transformation from the - // original image to the transformed image. - OmapTable omap_from; - // The table of OMAP entries describing the transformation from the - // instrumented image to the original image. - OmapTable omap_to; - // The length of the original untransformed image. - DWORD length_original; - - OmapData() : length_original(0) { } -}; - -// This represents a range of addresses in an image. -struct AddressRange { - DWORD rva; - DWORD length; - - AddressRange() : rva(0), length(0) { } - AddressRange(DWORD rva, DWORD length) : rva(rva), length(length) { } - - // Returns the end address of this range. - DWORD end() const { return rva + length; } - - // Addreses only compare as less-than or greater-than if they are not - // overlapping. Otherwise, they compare equal. - int Compare(const AddressRange& rhs) const; - bool operator<(const AddressRange& rhs) const { return Compare(rhs) == -1; } - bool operator>(const AddressRange& rhs) const { return Compare(rhs) == 1; } - - // Equality operators compare exact values. - bool operator==(const AddressRange& rhs) const { - return rva == rhs.rva && length == rhs.length; - } - bool operator!=(const AddressRange& rhs) const { return !((*this) == rhs); } -}; - -typedef std::vector AddressRangeVector; - -// This represents an address range in an original image, and its corresponding -// range in the transformed image. -struct MappedRange { - // An address in the original image. - DWORD rva_original; - // The corresponding addresses in the transformed image. - DWORD rva_transformed; - // The length of the address range. - DWORD length; - // It is possible for code to be injected into a transformed image, for which - // there is no corresponding code in the original image. If this range of - // transformed image is immediately followed by such injected code we maintain - // a record of its length here. - DWORD injected; - // It is possible for code to be removed from the original image. This happens - // for things like padding between blocks. There is no actual content lost, - // but the spacing between items may be lost. This keeps track of any removed - // content immediately following the |original| range. - DWORD removed; -}; -// A vector of mapped ranges is used as a more useful representation of -// OMAP data. -typedef std::vector Mapping; - -// Used as a secondary search structure accompanying a Mapping. -struct EndpointIndex { - DWORD endpoint; - size_t index; -}; -typedef std::vector EndpointIndexMap; - -// An ImageMap is vector of mapped ranges, plus a secondary index into it for -// doing interval searches. (An interval tree would also work, but is overkill -// because we don't need insertion and deletion.) -struct ImageMap { - // This is a description of the mapping between original and transformed - // image, sorted by addresses in the original image. - Mapping mapping; - // For all interval endpoints in |mapping| this stores the minimum index of - // an interval in |mapping| that contains the endpoint. Useful for doing - // interval intersection queries. - EndpointIndexMap endpoint_index_map; -}; - -} // namespace google_breakpad - -#endif // COMMON_WINDOWS_OMAP_INTERNAL_H__ diff --git a/breakpad/common/windows/omap_unittest.cc b/breakpad/common/windows/omap_unittest.cc deleted file mode 100644 index c1a2c512e..000000000 --- a/breakpad/common/windows/omap_unittest.cc +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Unittests for OMAP related functions. - -#include "common/windows/omap.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -namespace google_breakpad { - -// Equality operators for ContainerEq. These must be outside of the anonymous -// namespace in order for them to be found. -bool operator==(const MappedRange& mr1, const MappedRange& mr2) { - return mr1.rva_original == mr2.rva_original && - mr1.rva_transformed == mr2.rva_transformed && - mr1.length == mr2.length && - mr1.injected == mr2.injected && - mr1.removed == mr2.removed; -} -bool operator==(const EndpointIndex& ei1, const EndpointIndex& ei2) { - return ei1.endpoint == ei2.endpoint && ei1.index == ei2.index; -} - -// Pretty printers for more meaningful error messages. Also need to be outside -// the anonymous namespace. -std::ostream& operator<<(std::ostream& os, const MappedRange& mr) { - os << "MappedRange(rva_original=" << mr.rva_original - << ", rva_transformed=" << mr.rva_transformed - << ", length=" << mr.length - << ", injected=" << mr.injected - << ", removed=" << mr.removed << ")"; - return os; -} -std::ostream& operator<<(std::ostream& os, const EndpointIndex& ei) { - os << "EndpointIndex(endpoint=" << ei.endpoint - << ", index=" << ei.index << ")"; - return os; -} -std::ostream& operator<<(std::ostream& os, const AddressRange& ar) { - os << "AddressRange(rva=" << ar.rva << ", length=" << ar.length << ")"; - return os; -} - -namespace { - -OMAP CreateOmap(DWORD rva, DWORD rvaTo) { - OMAP o = { rva, rvaTo }; - return o; -} - -MappedRange CreateMappedRange(DWORD rva_original, - DWORD rva_transformed, - DWORD length, - DWORD injected, - DWORD removed) { - MappedRange mr = { rva_original, rva_transformed, length, injected, removed }; - return mr; -} - -EndpointIndex CreateEndpointIndex(DWORD endpoint, size_t index) { - EndpointIndex ei = { endpoint, index }; - return ei; -} - -// (C is removed) -// Original : A B C D E F G H -// Transformed: A B D F E * H1 G1 G2 H2 -// (* is injected, G is copied, H is split) -// A is implied. - -// Layout of the original image. -const AddressRange B(100, 15); -const AddressRange C(B.end(), 10); -const AddressRange D(C.end(), 25); -const AddressRange E(D.end(), 10); -const AddressRange F(E.end(), 40); -const AddressRange G(F.end(), 3); -const AddressRange H(G.end(), 7); - -// Layout of the transformed image. -const AddressRange Bt(100, 15); -const AddressRange Dt(Bt.end(), 20); // D is shortened. -const AddressRange Ft(Dt.end(), F.length); -const AddressRange Et(Ft.end(), E.length); -const AddressRange injected(Et.end(), 5); -const AddressRange H1t(injected.end(), 4); // H is split. -const AddressRange G1t(H1t.end(), G.length); // G is copied. -const AddressRange G2t(G1t.end(), G.length); // G is copied. -const AddressRange H2t(G2t.end(), 3); // H is split. - -class BuildImageMapTest : public testing::Test { - public: - static const DWORD kInvalidAddress = 0xFFFFFFFF; - - void InitOmapData() { - omap_data.length_original = H.end(); - - // Build the OMAPTO vector (from transformed to original). - omap_data.omap_to.push_back(CreateOmap(Bt.rva, B.rva)); - omap_data.omap_to.push_back(CreateOmap(Dt.rva, D.rva)); - omap_data.omap_to.push_back(CreateOmap(Ft.rva, F.rva)); - omap_data.omap_to.push_back(CreateOmap(Et.rva, E.rva)); - omap_data.omap_to.push_back(CreateOmap(injected.rva, kInvalidAddress)); - omap_data.omap_to.push_back(CreateOmap(H1t.rva, H.rva)); - omap_data.omap_to.push_back(CreateOmap(G1t.rva, G.rva)); - omap_data.omap_to.push_back(CreateOmap(G2t.rva, G.rva)); - omap_data.omap_to.push_back(CreateOmap(H2t.rva, H.rva + H1t.length)); - omap_data.omap_to.push_back(CreateOmap(H2t.end(), kInvalidAddress)); - - // Build the OMAPFROM vector (from original to transformed). - omap_data.omap_from.push_back(CreateOmap(B.rva, Bt.rva)); - omap_data.omap_from.push_back(CreateOmap(C.rva, kInvalidAddress)); - omap_data.omap_from.push_back(CreateOmap(D.rva, Dt.rva)); - omap_data.omap_from.push_back(CreateOmap(E.rva, Et.rva)); - omap_data.omap_from.push_back(CreateOmap(F.rva, Ft.rva)); - omap_data.omap_from.push_back(CreateOmap(G.rva, G1t.rva)); - omap_data.omap_from.push_back(CreateOmap(H.rva, H1t.rva)); - omap_data.omap_from.push_back(CreateOmap(H.rva + H1t.length, H2t.rva)); - omap_data.omap_from.push_back(CreateOmap(H.end(), kInvalidAddress)); - } - - OmapData omap_data; -}; - -} // namespace - -TEST_F(BuildImageMapTest, EmptyImageMapOnEmptyOmapData) { - ASSERT_EQ(0u, omap_data.omap_from.size()); - ASSERT_EQ(0u, omap_data.omap_to.size()); - ASSERT_EQ(0u, omap_data.length_original); - - ImageMap image_map; - BuildImageMap(omap_data, &image_map); - EXPECT_EQ(0u, image_map.mapping.size()); - EXPECT_EQ(0u, image_map.endpoint_index_map.size()); -} - -TEST_F(BuildImageMapTest, ImageMapIsCorrect) { - InitOmapData(); - ASSERT_LE(0u, omap_data.omap_from.size()); - ASSERT_LE(0u, omap_data.omap_to.size()); - ASSERT_LE(0u, omap_data.length_original); - - ImageMap image_map; - BuildImageMap(omap_data, &image_map); - EXPECT_LE(9u, image_map.mapping.size()); - EXPECT_LE(9u, image_map.endpoint_index_map.size()); - - Mapping mapping; - mapping.push_back(CreateMappedRange(0, 0, B.rva, 0, 0)); - // C is removed, and it originally comes immediately after B. - mapping.push_back(CreateMappedRange(B.rva, Bt.rva, B.length, 0, C.length)); - // D is shortened by a length of 5. - mapping.push_back(CreateMappedRange(D.rva, Dt.rva, Dt.length, 0, 5)); - // The injected content comes immediately after E in the transformed image. - mapping.push_back(CreateMappedRange(E.rva, Et.rva, E.length, injected.length, - 0)); - mapping.push_back(CreateMappedRange(F.rva, Ft.rva, F.length, 0, 0)); - // G is copied so creates two entries. - mapping.push_back(CreateMappedRange(G.rva, G1t.rva, G.length, 0, 0)); - mapping.push_back(CreateMappedRange(G.rva, G2t.rva, G.length, 0, 0)); - // H is split, so create two entries. - mapping.push_back(CreateMappedRange(H.rva, H1t.rva, H1t.length, 0, 0)); - mapping.push_back(CreateMappedRange(H.rva + H1t.length, H2t.rva, H2t.length, - 0, 0)); - EXPECT_THAT(mapping, - testing::ContainerEq(image_map.mapping)); - - EndpointIndexMap endpoint_index_map; - endpoint_index_map.push_back(CreateEndpointIndex(0, 0)); - endpoint_index_map.push_back(CreateEndpointIndex(B.rva, 1)); - endpoint_index_map.push_back(CreateEndpointIndex(D.rva, 2)); - endpoint_index_map.push_back(CreateEndpointIndex(E.rva, 3)); - endpoint_index_map.push_back(CreateEndpointIndex(F.rva, 4)); - // G is duplicated so 2 ranges map back to it, hence the skip from 5 to 7. - endpoint_index_map.push_back(CreateEndpointIndex(G.rva, 5)); - // H is split so we expect 2 endpoints to show up attributed to it. - endpoint_index_map.push_back(CreateEndpointIndex(H.rva, 7)); - endpoint_index_map.push_back(CreateEndpointIndex(H.rva + H1t.length, 8)); - endpoint_index_map.push_back(CreateEndpointIndex(H.end(), 9)); - EXPECT_THAT(endpoint_index_map, - testing::ContainerEq(image_map.endpoint_index_map)); -} - -namespace { - -class MapAddressRangeTest : public BuildImageMapTest { - public: - typedef BuildImageMapTest Super; - virtual void SetUp() { - Super::SetUp(); - InitOmapData(); - BuildImageMap(omap_data, &image_map); - } - - ImageMap image_map; - - private: - using BuildImageMapTest::InitOmapData; - using BuildImageMapTest::omap_data; -}; - -} // namespace - -TEST_F(MapAddressRangeTest, EmptyImageMapReturnsIdentity) { - ImageMap im; - AddressRangeVector mapped_ranges; - AddressRange ar(0, 1024); - MapAddressRange(im, ar, &mapped_ranges); - EXPECT_EQ(1u, mapped_ranges.size()); - EXPECT_EQ(ar, mapped_ranges[0]); -} - -TEST_F(MapAddressRangeTest, MapOutOfImage) { - AddressRangeVector mapped_ranges; - MapAddressRange(image_map, AddressRange(H.end() + 10, 10), &mapped_ranges); - EXPECT_EQ(0u, mapped_ranges.size()); -} - -TEST_F(MapAddressRangeTest, MapIdentity) { - AddressRangeVector mapped_ranges; - MapAddressRange(image_map, B, &mapped_ranges); - EXPECT_EQ(1u, mapped_ranges.size()); - EXPECT_THAT(mapped_ranges, testing::ElementsAre(B)); -} - -TEST_F(MapAddressRangeTest, MapReorderedContiguous) { - AddressRangeVector mapped_ranges; - - AddressRange DEF(D.rva, F.end() - D.rva); - MapAddressRange(image_map, DEF, &mapped_ranges); - EXPECT_EQ(1u, mapped_ranges.size()); - - AddressRange DFEt(Dt.rva, Et.end() - Dt.rva); - EXPECT_THAT(mapped_ranges, testing::ElementsAre(DFEt)); -} - -TEST_F(MapAddressRangeTest, MapEmptySingle) { - AddressRangeVector mapped_ranges; - MapAddressRange(image_map, AddressRange(D.rva, 0), &mapped_ranges); - EXPECT_EQ(1u, mapped_ranges.size()); - EXPECT_THAT(mapped_ranges, testing::ElementsAre(AddressRange(Dt.rva, 0))); -} - -TEST_F(MapAddressRangeTest, MapEmptyCopied) { - AddressRangeVector mapped_ranges; - MapAddressRange(image_map, AddressRange(G.rva, 0), &mapped_ranges); - EXPECT_EQ(2u, mapped_ranges.size()); - EXPECT_THAT(mapped_ranges, testing::ElementsAre(AddressRange(G1t.rva, 0), - AddressRange(G2t.rva, 0))); -} - -TEST_F(MapAddressRangeTest, MapCopiedContiguous) { - AddressRangeVector mapped_ranges; - MapAddressRange(image_map, G, &mapped_ranges); - EXPECT_EQ(1u, mapped_ranges.size()); - EXPECT_THAT(mapped_ranges, testing::ElementsAre( - AddressRange(G1t.rva, G2t.end() - G1t.rva))); -} - -TEST_F(MapAddressRangeTest, MapSplitDiscontiguous) { - AddressRangeVector mapped_ranges; - MapAddressRange(image_map, H, &mapped_ranges); - EXPECT_EQ(2u, mapped_ranges.size()); - EXPECT_THAT(mapped_ranges, testing::ElementsAre(H1t, H2t)); -} - -TEST_F(MapAddressRangeTest, MapInjected) { - AddressRangeVector mapped_ranges; - - AddressRange EFGH(E.rva, H.end() - E.rva); - MapAddressRange(image_map, EFGH, &mapped_ranges); - EXPECT_EQ(1u, mapped_ranges.size()); - - AddressRange FEHGGHt(Ft.rva, H2t.end() - Ft.rva); - EXPECT_THAT(mapped_ranges, testing::ElementsAre(FEHGGHt)); -} - -TEST_F(MapAddressRangeTest, MapRemovedEntirely) { - AddressRangeVector mapped_ranges; - MapAddressRange(image_map, C, &mapped_ranges); - EXPECT_EQ(0u, mapped_ranges.size()); -} - -TEST_F(MapAddressRangeTest, MapRemovedPartly) { - AddressRangeVector mapped_ranges; - MapAddressRange(image_map, D, &mapped_ranges); - EXPECT_EQ(1u, mapped_ranges.size()); - EXPECT_THAT(mapped_ranges, testing::ElementsAre(Dt)); -} - -TEST_F(MapAddressRangeTest, MapFull) { - AddressRangeVector mapped_ranges; - - AddressRange AH(0, H.end()); - MapAddressRange(image_map, AH, &mapped_ranges); - EXPECT_EQ(1u, mapped_ranges.size()); - - AddressRange AHt(0, H2t.end()); - EXPECT_THAT(mapped_ranges, testing::ElementsAre(AHt)); -} - -} // namespace google_breakpad diff --git a/breakpad/common/windows/pdb_source_line_writer.cc b/breakpad/common/windows/pdb_source_line_writer.cc deleted file mode 100644 index dba2ea764..000000000 --- a/breakpad/common/windows/pdb_source_line_writer.cc +++ /dev/null @@ -1,1066 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "common/windows/pdb_source_line_writer.h" - -#include -#include -#include -#include -#include -#include - -#include "common/windows/dia_util.h" -#include "common/windows/guid_string.h" -#include "common/windows/string_utils-inl.h" - -// This constant may be missing from DbgHelp.h. See the documentation for -// IDiaSymbol::get_undecoratedNameEx. -#ifndef UNDNAME_NO_ECSU -#define UNDNAME_NO_ECSU 0x8000 // Suppresses enum/class/struct/union. -#endif // UNDNAME_NO_ECSU - -namespace google_breakpad { - -namespace { - -using std::vector; - -// A helper class to scope a PLOADED_IMAGE. -class AutoImage { - public: - explicit AutoImage(PLOADED_IMAGE img) : img_(img) {} - ~AutoImage() { - if (img_) - ImageUnload(img_); - } - - operator PLOADED_IMAGE() { return img_; } - PLOADED_IMAGE operator->() { return img_; } - - private: - PLOADED_IMAGE img_; -}; - -} // namespace - -PDBSourceLineWriter::PDBSourceLineWriter() : output_(NULL) { -} - -PDBSourceLineWriter::~PDBSourceLineWriter() { -} - -bool PDBSourceLineWriter::Open(const wstring &file, FileFormat format) { - Close(); - - if (FAILED(CoInitialize(NULL))) { - fprintf(stderr, "CoInitialize failed\n"); - return false; - } - - CComPtr data_source; - if (FAILED(data_source.CoCreateInstance(CLSID_DiaSource))) { - const int kGuidSize = 64; - wchar_t classid[kGuidSize] = {0}; - StringFromGUID2(CLSID_DiaSource, classid, kGuidSize); - // vc80 uses bce36434-2c24-499e-bf49-8bd99b0eeb68. - // vc90 uses 4C41678E-887B-4365-A09E-925D28DB33C2. - fprintf(stderr, "CoCreateInstance CLSID_DiaSource %S failed " - "(msdia*.dll unregistered?)\n", classid); - return false; - } - - switch (format) { - case PDB_FILE: - if (FAILED(data_source->loadDataFromPdb(file.c_str()))) { - fprintf(stderr, "loadDataFromPdb failed for %ws\n", file.c_str()); - return false; - } - break; - case EXE_FILE: - if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) { - fprintf(stderr, "loadDataForExe failed for %ws\n", file.c_str()); - return false; - } - code_file_ = file; - break; - case ANY_FILE: - if (FAILED(data_source->loadDataFromPdb(file.c_str()))) { - if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) { - fprintf(stderr, "loadDataForPdb and loadDataFromExe failed for %ws\n", file.c_str()); - return false; - } - code_file_ = file; - } - break; - default: - fprintf(stderr, "Unknown file format\n"); - return false; - } - - if (FAILED(data_source->openSession(&session_))) { - fprintf(stderr, "openSession failed\n"); - } - - return true; -} - -bool PDBSourceLineWriter::PrintLines(IDiaEnumLineNumbers *lines) { - // The line number format is: - // - CComPtr line; - ULONG count; - - while (SUCCEEDED(lines->Next(1, &line, &count)) && count == 1) { - DWORD rva; - if (FAILED(line->get_relativeVirtualAddress(&rva))) { - fprintf(stderr, "failed to get line rva\n"); - return false; - } - - DWORD length; - if (FAILED(line->get_length(&length))) { - fprintf(stderr, "failed to get line code length\n"); - return false; - } - - DWORD dia_source_id; - if (FAILED(line->get_sourceFileId(&dia_source_id))) { - fprintf(stderr, "failed to get line source file id\n"); - return false; - } - // duplicate file names are coalesced to share one ID - DWORD source_id = GetRealFileID(dia_source_id); - - DWORD line_num; - if (FAILED(line->get_lineNumber(&line_num))) { - fprintf(stderr, "failed to get line number\n"); - return false; - } - - AddressRangeVector ranges; - MapAddressRange(image_map_, AddressRange(rva, length), &ranges); - for (size_t i = 0; i < ranges.size(); ++i) { - fprintf(output_, "%x %x %d %d\n", ranges[i].rva, ranges[i].length, - line_num, source_id); - } - line.Release(); - } - return true; -} - -bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function, - IDiaSymbol *block) { - // The function format is: - // FUNC
- DWORD rva; - if (FAILED(block->get_relativeVirtualAddress(&rva))) { - fprintf(stderr, "couldn't get rva\n"); - return false; - } - - ULONGLONG length; - if (FAILED(block->get_length(&length))) { - fprintf(stderr, "failed to get function length\n"); - return false; - } - - if (length == 0) { - // Silently ignore zero-length functions, which can infrequently pop up. - return true; - } - - CComBSTR name; - int stack_param_size; - if (!GetSymbolFunctionName(function, &name, &stack_param_size)) { - return false; - } - - // If the decorated name didn't give the parameter size, try to - // calculate it. - if (stack_param_size < 0) { - stack_param_size = GetFunctionStackParamSize(function); - } - - AddressRangeVector ranges; - MapAddressRange(image_map_, AddressRange(rva, static_cast(length)), - &ranges); - for (size_t i = 0; i < ranges.size(); ++i) { - fprintf(output_, "FUNC %x %x %x %ws\n", - ranges[i].rva, ranges[i].length, stack_param_size, name); - } - - CComPtr lines; - if (FAILED(session_->findLinesByRVA(rva, DWORD(length), &lines))) { - return false; - } - - if (!PrintLines(lines)) { - return false; - } - return true; -} - -bool PDBSourceLineWriter::PrintSourceFiles() { - CComPtr global; - if (FAILED(session_->get_globalScope(&global))) { - fprintf(stderr, "get_globalScope failed\n"); - return false; - } - - CComPtr compilands; - if (FAILED(global->findChildren(SymTagCompiland, NULL, - nsNone, &compilands))) { - fprintf(stderr, "findChildren failed\n"); - return false; - } - - CComPtr compiland; - ULONG count; - while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) { - CComPtr source_files; - if (FAILED(session_->findFile(compiland, NULL, nsNone, &source_files))) { - return false; - } - CComPtr file; - while (SUCCEEDED(source_files->Next(1, &file, &count)) && count == 1) { - DWORD file_id; - if (FAILED(file->get_uniqueId(&file_id))) { - return false; - } - - CComBSTR file_name; - if (FAILED(file->get_fileName(&file_name))) { - return false; - } - - wstring file_name_string(file_name); - if (!FileIDIsCached(file_name_string)) { - // this is a new file name, cache it and output a FILE line. - CacheFileID(file_name_string, file_id); - fwprintf(output_, L"FILE %d %s\n", file_id, file_name); - } else { - // this file name has already been seen, just save this - // ID for later lookup. - StoreDuplicateFileID(file_name_string, file_id); - } - file.Release(); - } - compiland.Release(); - } - return true; -} - -bool PDBSourceLineWriter::PrintFunctions() { - CComPtr symbols; - if (FAILED(session_->getSymbolsByAddr(&symbols))) { - fprintf(stderr, "failed to get symbol enumerator\n"); - return false; - } - - CComPtr symbol; - if (FAILED(symbols->symbolByAddr(1, 0, &symbol))) { - fprintf(stderr, "failed to enumerate symbols\n"); - return false; - } - - DWORD rva_last = 0; - if (FAILED(symbol->get_relativeVirtualAddress(&rva_last))) { - fprintf(stderr, "failed to get symbol rva\n"); - return false; - } - - ULONG count; - do { - DWORD tag; - if (FAILED(symbol->get_symTag(&tag))) { - fprintf(stderr, "failed to get symbol tag\n"); - return false; - } - - // For a given function, DIA seems to give either a symbol with - // SymTagFunction or SymTagPublicSymbol, but not both. This means - // that PDBSourceLineWriter will output either a FUNC or PUBLIC line, - // but not both. - if (tag == SymTagFunction) { - if (!PrintFunction(symbol, symbol)) { - return false; - } - } else if (tag == SymTagPublicSymbol) { - if (!PrintCodePublicSymbol(symbol)) { - return false; - } - } - symbol.Release(); - } while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1); - - // When building with PGO, the compiler can split functions into - // "hot" and "cold" blocks, and move the "cold" blocks out to separate - // pages, so the function can be noncontiguous. To find these blocks, - // we have to iterate over all the compilands, and then find blocks - // that are children of them. We can then find the lexical parents - // of those blocks and print out an extra FUNC line for blocks - // that are not contained in their parent functions. - CComPtr global; - if (FAILED(session_->get_globalScope(&global))) { - fprintf(stderr, "get_globalScope failed\n"); - return false; - } - - CComPtr compilands; - if (FAILED(global->findChildren(SymTagCompiland, NULL, - nsNone, &compilands))) { - fprintf(stderr, "findChildren failed on the global\n"); - return false; - } - - CComPtr compiland; - while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) { - CComPtr blocks; - if (FAILED(compiland->findChildren(SymTagBlock, NULL, - nsNone, &blocks))) { - fprintf(stderr, "findChildren failed on a compiland\n"); - return false; - } - - CComPtr block; - while (SUCCEEDED(blocks->Next(1, &block, &count)) && count == 1) { - // find this block's lexical parent function - CComPtr parent; - DWORD tag; - if (SUCCEEDED(block->get_lexicalParent(&parent)) && - SUCCEEDED(parent->get_symTag(&tag)) && - tag == SymTagFunction) { - // now get the block's offset and the function's offset and size, - // and determine if the block is outside of the function - DWORD func_rva, block_rva; - ULONGLONG func_length; - if (SUCCEEDED(block->get_relativeVirtualAddress(&block_rva)) && - SUCCEEDED(parent->get_relativeVirtualAddress(&func_rva)) && - SUCCEEDED(parent->get_length(&func_length))) { - if (block_rva < func_rva || block_rva > (func_rva + func_length)) { - if (!PrintFunction(parent, block)) { - return false; - } - } - } - } - parent.Release(); - block.Release(); - } - blocks.Release(); - compiland.Release(); - } - - return true; -} - -bool PDBSourceLineWriter::PrintFrameData() { - // It would be nice if it were possible to output frame data alongside the - // associated function, as is done with line numbers, but the DIA API - // doesn't make it possible to get the frame data in that way. - - CComPtr frame_data_enum; - if (!FindTable(session_, &frame_data_enum)) - return false; - - DWORD last_type = -1; - DWORD last_rva = -1; - DWORD last_code_size = 0; - DWORD last_prolog_size = -1; - - CComPtr frame_data; - ULONG count = 0; - while (SUCCEEDED(frame_data_enum->Next(1, &frame_data, &count)) && - count == 1) { - DWORD type; - if (FAILED(frame_data->get_type(&type))) - return false; - - DWORD rva; - if (FAILED(frame_data->get_relativeVirtualAddress(&rva))) - return false; - - DWORD code_size; - if (FAILED(frame_data->get_lengthBlock(&code_size))) - return false; - - DWORD prolog_size; - if (FAILED(frame_data->get_lengthProlog(&prolog_size))) - return false; - - // parameter_size is the size of parameters passed on the stack. If any - // parameters are not passed on the stack (such as in registers), their - // sizes will not be included in parameter_size. - DWORD parameter_size; - if (FAILED(frame_data->get_lengthParams(¶meter_size))) - return false; - - DWORD saved_register_size; - if (FAILED(frame_data->get_lengthSavedRegisters(&saved_register_size))) - return false; - - DWORD local_size; - if (FAILED(frame_data->get_lengthLocals(&local_size))) - return false; - - // get_maxStack can return S_FALSE, just use 0 in that case. - DWORD max_stack_size = 0; - if (FAILED(frame_data->get_maxStack(&max_stack_size))) - return false; - - // get_programString can return S_FALSE, indicating that there is no - // program string. In that case, check whether %ebp is used. - HRESULT program_string_result; - CComBSTR program_string; - if (FAILED(program_string_result = frame_data->get_program( - &program_string))) { - return false; - } - - // get_allocatesBasePointer can return S_FALSE, treat that as though - // %ebp is not used. - BOOL allocates_base_pointer = FALSE; - if (program_string_result != S_OK) { - if (FAILED(frame_data->get_allocatesBasePointer( - &allocates_base_pointer))) { - return false; - } - } - - // Only print out a line if type, rva, code_size, or prolog_size have - // changed from the last line. It is surprisingly common (especially in - // system library PDBs) for DIA to return a series of identical - // IDiaFrameData objects. For kernel32.pdb from Windows XP SP2 on x86, - // this check reduces the size of the dumped symbol file by a third. - if (type != last_type || rva != last_rva || code_size != last_code_size || - prolog_size != last_prolog_size) { - // The prolog and the code portions of the frame have to be treated - // independently as they may have independently changed in size, or may - // even have been split. - // NOTE: If epilog size is ever non-zero, we have to do something - // similar with it. - - // Figure out where the prolog bytes have landed. - AddressRangeVector prolog_ranges; - if (prolog_size > 0) { - MapAddressRange(image_map_, AddressRange(rva, prolog_size), - &prolog_ranges); - } - - // And figure out where the code bytes have landed. - AddressRangeVector code_ranges; - MapAddressRange(image_map_, - AddressRange(rva + prolog_size, - code_size - prolog_size), - &code_ranges); - - struct FrameInfo { - DWORD rva; - DWORD code_size; - DWORD prolog_size; - }; - std::vector frame_infos; - - // Special case: The prolog and the code bytes remain contiguous. This is - // only done for compactness of the symbol file, and we could actually - // be outputting independent frame info for the prolog and code portions. - if (prolog_ranges.size() == 1 && code_ranges.size() == 1 && - prolog_ranges[0].end() == code_ranges[0].rva) { - FrameInfo fi = { prolog_ranges[0].rva, - prolog_ranges[0].length + code_ranges[0].length, - prolog_ranges[0].length }; - frame_infos.push_back(fi); - } else { - // Otherwise we output the prolog and code frame info independently. - for (size_t i = 0; i < prolog_ranges.size(); ++i) { - FrameInfo fi = { prolog_ranges[i].rva, - prolog_ranges[i].length, - prolog_ranges[i].length }; - frame_infos.push_back(fi); - } - for (size_t i = 0; i < code_ranges.size(); ++i) { - FrameInfo fi = { code_ranges[i].rva, code_ranges[i].length, 0 }; - frame_infos.push_back(fi); - } - } - - for (size_t i = 0; i < frame_infos.size(); ++i) { - const FrameInfo& fi(frame_infos[i]); - fprintf(output_, "STACK WIN %x %x %x %x %x %x %x %x %x %d ", - type, fi.rva, fi.code_size, fi.prolog_size, - 0 /* epilog_size */, parameter_size, saved_register_size, - local_size, max_stack_size, program_string_result == S_OK); - if (program_string_result == S_OK) { - fprintf(output_, "%ws\n", program_string); - } else { - fprintf(output_, "%d\n", allocates_base_pointer); - } - } - - last_type = type; - last_rva = rva; - last_code_size = code_size; - last_prolog_size = prolog_size; - } - - frame_data.Release(); - } - - return true; -} - -bool PDBSourceLineWriter::PrintCodePublicSymbol(IDiaSymbol *symbol) { - BOOL is_code; - if (FAILED(symbol->get_code(&is_code))) { - return false; - } - if (!is_code) { - return true; - } - - DWORD rva; - if (FAILED(symbol->get_relativeVirtualAddress(&rva))) { - return false; - } - - CComBSTR name; - int stack_param_size; - if (!GetSymbolFunctionName(symbol, &name, &stack_param_size)) { - return false; - } - - AddressRangeVector ranges; - MapAddressRange(image_map_, AddressRange(rva, 1), &ranges); - for (size_t i = 0; i < ranges.size(); ++i) { - fprintf(output_, "PUBLIC %x %x %ws\n", ranges[i].rva, - stack_param_size > 0 ? stack_param_size : 0, name); - } - return true; -} - -bool PDBSourceLineWriter::PrintPDBInfo() { - PDBModuleInfo info; - if (!GetModuleInfo(&info)) { - return false; - } - - // Hard-code "windows" for the OS because that's the only thing that makes - // sense for PDB files. (This might not be strictly correct for Windows CE - // support, but we don't care about that at the moment.) - fprintf(output_, "MODULE windows %ws %ws %ws\n", - info.cpu.c_str(), info.debug_identifier.c_str(), - info.debug_file.c_str()); - - return true; -} - -bool PDBSourceLineWriter::PrintPEInfo() { - PEModuleInfo info; - if (!GetPEInfo(&info)) { - return false; - } - - fprintf(output_, "INFO CODE_ID %ws %ws\n", - info.code_identifier.c_str(), - info.code_file.c_str()); - return true; -} - -// wcstol_positive_strict is sort of like wcstol, but much stricter. string -// should be a buffer pointing to a null-terminated string containing only -// decimal digits. If the entire string can be converted to an integer -// without overflowing, and there are no non-digit characters before the -// result is set to the value and this function returns true. Otherwise, -// this function returns false. This is an alternative to the strtol, atoi, -// and scanf families, which are not as strict about input and in some cases -// don't provide a good way for the caller to determine if a conversion was -// successful. -static bool wcstol_positive_strict(wchar_t *string, int *result) { - int value = 0; - for (wchar_t *c = string; *c != '\0'; ++c) { - int last_value = value; - value *= 10; - // Detect overflow. - if (value / 10 != last_value || value < 0) { - return false; - } - if (*c < '0' || *c > '9') { - return false; - } - unsigned int c_value = *c - '0'; - last_value = value; - value += c_value; - // Detect overflow. - if (value < last_value) { - return false; - } - // Forbid leading zeroes unless the string is just "0". - if (value == 0 && *(c+1) != '\0') { - return false; - } - } - *result = value; - return true; -} - -bool PDBSourceLineWriter::FindPEFile() { - CComPtr global; - if (FAILED(session_->get_globalScope(&global))) { - fprintf(stderr, "get_globalScope failed\n"); - return false; - } - - CComBSTR symbols_file; - if (SUCCEEDED(global->get_symbolsFileName(&symbols_file))) { - wstring file(symbols_file); - - // Look for an EXE or DLL file. - const wchar_t *extensions[] = { L"exe", L"dll" }; - for (int i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++) { - size_t dot_pos = file.find_last_of(L"."); - if (dot_pos != wstring::npos) { - file.replace(dot_pos + 1, wstring::npos, extensions[i]); - // Check if this file exists. - if (GetFileAttributesW(file.c_str()) != INVALID_FILE_ATTRIBUTES) { - code_file_ = file; - return true; - } - } - } - } - - return false; -} - -// static -bool PDBSourceLineWriter::GetSymbolFunctionName(IDiaSymbol *function, - BSTR *name, - int *stack_param_size) { - *stack_param_size = -1; - const DWORD undecorate_options = UNDNAME_NO_MS_KEYWORDS | - UNDNAME_NO_FUNCTION_RETURNS | - UNDNAME_NO_ALLOCATION_MODEL | - UNDNAME_NO_ALLOCATION_LANGUAGE | - UNDNAME_NO_THISTYPE | - UNDNAME_NO_ACCESS_SPECIFIERS | - UNDNAME_NO_THROW_SIGNATURES | - UNDNAME_NO_MEMBER_TYPE | - UNDNAME_NO_RETURN_UDT_MODEL | - UNDNAME_NO_ECSU; - - // Use get_undecoratedNameEx to get readable C++ names with arguments. - if (function->get_undecoratedNameEx(undecorate_options, name) != S_OK) { - if (function->get_name(name) != S_OK) { - fprintf(stderr, "failed to get function name\n"); - return false; - } - // If a name comes from get_name because no undecorated form existed, - // it's already formatted properly to be used as output. Don't do any - // additional processing. - // - // MSVC7's DIA seems to not undecorate names in as many cases as MSVC8's. - // This will result in calling get_name for some C++ symbols, so - // all of the parameter and return type information may not be included in - // the name string. - } else { - // C++ uses a bogus "void" argument for functions and methods that don't - // take any parameters. Take it out of the undecorated name because it's - // ugly and unnecessary. - const wchar_t *replace_string = L"(void)"; - const size_t replace_length = wcslen(replace_string); - const wchar_t *replacement_string = L"()"; - size_t length = wcslen(*name); - if (length >= replace_length) { - wchar_t *name_end = *name + length - replace_length; - if (wcscmp(name_end, replace_string) == 0) { - WindowsStringUtils::safe_wcscpy(name_end, replace_length, - replacement_string); - length = wcslen(*name); - } - } - - // Undecorate names used for stdcall and fastcall. These names prefix - // the identifier with '_' (stdcall) or '@' (fastcall) and suffix it - // with '@' followed by the number of bytes of parameters, in decimal. - // If such a name is found, take note of the size and undecorate it. - // Only do this for names that aren't C++, which is determined based on - // whether the undecorated name contains any ':' or '(' characters. - if (!wcschr(*name, ':') && !wcschr(*name, '(') && - (*name[0] == '_' || *name[0] == '@')) { - wchar_t *last_at = wcsrchr(*name + 1, '@'); - if (last_at && wcstol_positive_strict(last_at + 1, stack_param_size)) { - // If this function adheres to the fastcall convention, it accepts up - // to the first 8 bytes of parameters in registers (%ecx and %edx). - // We're only interested in the stack space used for parameters, so - // so subtract 8 and don't let the size go below 0. - if (*name[0] == '@') { - if (*stack_param_size > 8) { - *stack_param_size -= 8; - } else { - *stack_param_size = 0; - } - } - - // Undecorate the name by moving it one character to the left in its - // buffer, and terminating it where the last '@' had been. - WindowsStringUtils::safe_wcsncpy(*name, length, - *name + 1, last_at - *name - 1); - } else if (*name[0] == '_') { - // This symbol's name is encoded according to the cdecl rules. The - // name doesn't end in a '@' character followed by a decimal positive - // integer, so it's not a stdcall name. Strip off the leading - // underscore. - WindowsStringUtils::safe_wcsncpy(*name, length, *name + 1, length); - } - } - } - - return true; -} - -// static -int PDBSourceLineWriter::GetFunctionStackParamSize(IDiaSymbol *function) { - // This implementation is highly x86-specific. - - // Gather the symbols corresponding to data. - CComPtr data_children; - if (FAILED(function->findChildren(SymTagData, NULL, nsNone, - &data_children))) { - return 0; - } - - // lowest_base is the lowest %ebp-relative byte offset used for a parameter. - // highest_end is one greater than the highest offset (i.e. base + length). - // Stack parameters are assumed to be contiguous, because in reality, they - // are. - int lowest_base = INT_MAX; - int highest_end = INT_MIN; - - CComPtr child; - DWORD count; - while (SUCCEEDED(data_children->Next(1, &child, &count)) && count == 1) { - // If any operation fails at this point, just proceed to the next child. - // Use the next_child label instead of continue because child needs to - // be released before it's reused. Declare constructable/destructable - // types early to avoid gotos that cross initializations. - CComPtr child_type; - - // DataIsObjectPtr is only used for |this|. Because |this| can be passed - // as a stack parameter, look for it in addition to traditional - // parameters. - DWORD child_kind; - if (FAILED(child->get_dataKind(&child_kind)) || - (child_kind != DataIsParam && child_kind != DataIsObjectPtr)) { - goto next_child; - } - - // Only concentrate on register-relative parameters. Parameters may also - // be enregistered (passed directly in a register), but those don't - // consume any stack space, so they're not of interest. - DWORD child_location_type; - if (FAILED(child->get_locationType(&child_location_type)) || - child_location_type != LocIsRegRel) { - goto next_child; - } - - // Of register-relative parameters, the only ones that make any sense are - // %ebp- or %esp-relative. Note that MSVC's debugging information always - // gives parameters as %ebp-relative even when a function doesn't use a - // traditional frame pointer and stack parameters are accessed relative to - // %esp, so just look for %ebp-relative parameters. If you wanted to - // access parameters, you'd probably want to treat these %ebp-relative - // offsets as if they were relative to %esp before a function's prolog - // executed. - DWORD child_register; - if (FAILED(child->get_registerId(&child_register)) || - child_register != CV_REG_EBP) { - goto next_child; - } - - LONG child_register_offset; - if (FAILED(child->get_offset(&child_register_offset))) { - goto next_child; - } - - // IDiaSymbol::get_type can succeed but still pass back a NULL value. - if (FAILED(child->get_type(&child_type)) || !child_type) { - goto next_child; - } - - ULONGLONG child_length; - if (FAILED(child_type->get_length(&child_length))) { - goto next_child; - } - - int child_end = child_register_offset + static_cast(child_length); - if (child_register_offset < lowest_base) { - lowest_base = child_register_offset; - } - if (child_end > highest_end) { - highest_end = child_end; - } - -next_child: - child.Release(); - } - - int param_size = 0; - // Make sure lowest_base isn't less than 4, because [%esp+4] is the lowest - // possible address to find a stack parameter before executing a function's - // prolog (see above). Some optimizations cause parameter offsets to be - // lower than 4, but we're not concerned with those because we're only - // looking for parameters contained in addresses higher than where the - // return address is stored. - if (lowest_base < 4) { - lowest_base = 4; - } - if (highest_end > lowest_base) { - // All stack parameters are pushed as at least 4-byte quantities. If the - // last type was narrower than 4 bytes, promote it. This assumes that all - // parameters' offsets are 4-byte-aligned, which is always the case. Only - // worry about the last type, because we're not summing the type sizes, - // just looking at the lowest and highest offsets. - int remainder = highest_end % 4; - if (remainder) { - highest_end += 4 - remainder; - } - - param_size = highest_end - lowest_base; - } - - return param_size; -} - -bool PDBSourceLineWriter::WriteMap(FILE *map_file) { - output_ = map_file; - - // Load the OMAP information, and disable auto-translation of addresses in - // preference of doing it ourselves. - OmapData omap_data; - if (!GetOmapDataAndDisableTranslation(session_, &omap_data)) - return false; - BuildImageMap(omap_data, &image_map_); - - bool ret = PrintPDBInfo(); - // This is not a critical piece of the symbol file. - PrintPEInfo(); - ret = ret && - PrintSourceFiles() && - PrintFunctions() && - PrintFrameData(); - - output_ = NULL; - return ret; -} - -void PDBSourceLineWriter::Close() { - session_.Release(); -} - -bool PDBSourceLineWriter::GetModuleInfo(PDBModuleInfo *info) { - if (!info) { - return false; - } - - info->debug_file.clear(); - info->debug_identifier.clear(); - info->cpu.clear(); - - CComPtr global; - if (FAILED(session_->get_globalScope(&global))) { - return false; - } - - DWORD machine_type; - // get_machineType can return S_FALSE. - if (global->get_machineType(&machine_type) == S_OK) { - // The documentation claims that get_machineType returns a value from - // the CV_CPU_TYPE_e enumeration, but that's not the case. - // Instead, it returns one of the IMAGE_FILE_MACHINE values as - // defined here: - // http://msdn.microsoft.com/en-us/library/ms680313%28VS.85%29.aspx - switch (machine_type) { - case IMAGE_FILE_MACHINE_I386: - info->cpu = L"x86"; - break; - case IMAGE_FILE_MACHINE_AMD64: - info->cpu = L"x86_64"; - break; - default: - info->cpu = L"unknown"; - break; - } - } else { - // Unexpected, but handle gracefully. - info->cpu = L"unknown"; - } - - // DWORD* and int* are not compatible. This is clean and avoids a cast. - DWORD age; - if (FAILED(global->get_age(&age))) { - return false; - } - - bool uses_guid; - if (!UsesGUID(&uses_guid)) { - return false; - } - - if (uses_guid) { - GUID guid; - if (FAILED(global->get_guid(&guid))) { - return false; - } - - // Use the same format that the MS symbol server uses in filesystem - // hierarchies. - wchar_t age_string[9]; - swprintf(age_string, sizeof(age_string) / sizeof(age_string[0]), - L"%x", age); - - // remove when VC++7.1 is no longer supported - age_string[sizeof(age_string) / sizeof(age_string[0]) - 1] = L'\0'; - - info->debug_identifier = GUIDString::GUIDToSymbolServerWString(&guid); - info->debug_identifier.append(age_string); - } else { - DWORD signature; - if (FAILED(global->get_signature(&signature))) { - return false; - } - - // Use the same format that the MS symbol server uses in filesystem - // hierarchies. - wchar_t identifier_string[17]; - swprintf(identifier_string, - sizeof(identifier_string) / sizeof(identifier_string[0]), - L"%08X%x", signature, age); - - // remove when VC++7.1 is no longer supported - identifier_string[sizeof(identifier_string) / - sizeof(identifier_string[0]) - 1] = L'\0'; - - info->debug_identifier = identifier_string; - } - - CComBSTR debug_file_string; - if (FAILED(global->get_symbolsFileName(&debug_file_string))) { - return false; - } - info->debug_file = - WindowsStringUtils::GetBaseName(wstring(debug_file_string)); - - return true; -} - -bool PDBSourceLineWriter::GetPEInfo(PEModuleInfo *info) { - if (!info) { - return false; - } - - if (code_file_.empty() && !FindPEFile()) { - fprintf(stderr, "Couldn't locate EXE or DLL file.\n"); - return false; - } - - // Convert wchar to native charset because ImageLoad only takes - // a PSTR as input. - string code_file; - if (!WindowsStringUtils::safe_wcstombs(code_file_, &code_file)) { - return false; - } - - AutoImage img(ImageLoad((PSTR)code_file.c_str(), NULL)); - if (!img) { - fprintf(stderr, "Failed to open PE file: %s\n", code_file.c_str()); - return false; - } - - info->code_file = WindowsStringUtils::GetBaseName(code_file_); - - // The date and time that the file was created by the linker. - DWORD TimeDateStamp = img->FileHeader->FileHeader.TimeDateStamp; - // The size of the file in bytes, including all headers. - DWORD SizeOfImage = 0; - PIMAGE_OPTIONAL_HEADER64 opt = - &((PIMAGE_NT_HEADERS64)img->FileHeader)->OptionalHeader; - if (opt->Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { - // 64-bit PE file. - SizeOfImage = opt->SizeOfImage; - } - else { - // 32-bit PE file. - SizeOfImage = img->FileHeader->OptionalHeader.SizeOfImage; - } - wchar_t code_identifier[32]; - swprintf(code_identifier, - sizeof(code_identifier) / sizeof(code_identifier[0]), - L"%08X%X", TimeDateStamp, SizeOfImage); - info->code_identifier = code_identifier; - - return true; -} - -bool PDBSourceLineWriter::UsesGUID(bool *uses_guid) { - if (!uses_guid) - return false; - - CComPtr global; - if (FAILED(session_->get_globalScope(&global))) - return false; - - GUID guid; - if (FAILED(global->get_guid(&guid))) - return false; - - DWORD signature; - if (FAILED(global->get_signature(&signature))) - return false; - - // There are two possibilities for guid: either it's a real 128-bit GUID - // as identified in a code module by a new-style CodeView record, or it's - // a 32-bit signature (timestamp) as identified by an old-style record. - // See MDCVInfoPDB70 and MDCVInfoPDB20 in minidump_format.h. - // - // Because DIA doesn't provide a way to directly determine whether a module - // uses a GUID or a 32-bit signature, this code checks whether the first 32 - // bits of guid are the same as the signature, and if the rest of guid is - // zero. If so, then with a pretty high degree of certainty, there's an - // old-style CodeView record in use. This method will only falsely find an - // an old-style CodeView record if a real 128-bit GUID has its first 32 - // bits set the same as the module's signature (timestamp) and the rest of - // the GUID is set to 0. This is highly unlikely. - - GUID signature_guid = {signature}; // 0-initializes other members - *uses_guid = !IsEqualGUID(guid, signature_guid); - return true; -} - -} // namespace google_breakpad diff --git a/breakpad/common/windows/pdb_source_line_writer.h b/breakpad/common/windows/pdb_source_line_writer.h deleted file mode 100644 index be6121c3f..000000000 --- a/breakpad/common/windows/pdb_source_line_writer.h +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// PDBSourceLineWriter uses a pdb file produced by Visual C++ to output -// a line/address map for use with BasicSourceLineResolver. - -#ifndef _PDB_SOURCE_LINE_WRITER_H__ -#define _PDB_SOURCE_LINE_WRITER_H__ - -#include - -#include -#include - -#include "common/windows/omap.h" - -struct IDiaEnumLineNumbers; -struct IDiaSession; -struct IDiaSymbol; - -namespace google_breakpad { - -using std::wstring; -using stdext::hash_map; - -// A structure that carries information that identifies a pdb file. -struct PDBModuleInfo { - public: - // The basename of the pdb file from which information was loaded. - wstring debug_file; - - // The pdb's identifier. For recent pdb files, the identifier consists - // of the pdb's guid, in uppercase hexadecimal form without any dashes - // or separators, followed immediately by the pdb's age, also in - // uppercase hexadecimal form. For older pdb files which have no guid, - // the identifier is the pdb's 32-bit signature value, in zero-padded - // hexadecimal form, followed immediately by the pdb's age, in lowercase - // hexadecimal form. - wstring debug_identifier; - - // A string identifying the cpu that the pdb is associated with. - // Currently, this may be "x86" or "unknown". - wstring cpu; -}; - -// A structure that carries information that identifies a PE file, -// either an EXE or a DLL. -struct PEModuleInfo { - // The basename of the PE file. - wstring code_file; - - // The PE file's code identifier, which consists of its timestamp - // and file size concatenated together into a single hex string. - // (The fields IMAGE_OPTIONAL_HEADER::SizeOfImage and - // IMAGE_FILE_HEADER::TimeDateStamp, as defined in the ImageHlp - // documentation.) This is not well documented, if it's documented - // at all, but it's what symstore does and what DbgHelp supports. - wstring code_identifier; -}; - -class PDBSourceLineWriter { - public: - enum FileFormat { - PDB_FILE, // a .pdb file containing debug symbols - EXE_FILE, // a .exe or .dll file - ANY_FILE // try PDB_FILE and then EXE_FILE - }; - - explicit PDBSourceLineWriter(); - ~PDBSourceLineWriter(); - - // Opens the given file. For executable files, the corresponding pdb - // file must be available; Open will be if it is not. - // If there is already a pdb file open, it is automatically closed. - // Returns true on success. - bool Open(const wstring &file, FileFormat format); - - // Locates the pdb file for the given executable (exe or dll) file, - // and opens it. If there is already a pdb file open, it is automatically - // closed. Returns true on success. - bool OpenExecutable(const wstring &exe_file); - - // Writes a map file from the current pdb file to the given file stream. - // Returns true on success. - bool WriteMap(FILE *map_file); - - // Closes the current pdb file and its associated resources. - void Close(); - - // Retrieves information about the module's debugging file. Returns - // true on success and false on failure. - bool GetModuleInfo(PDBModuleInfo *info); - - // Retrieves information about the module's PE file. Returns - // true on success and false on failure. - bool GetPEInfo(PEModuleInfo *info); - - // Sets uses_guid to true if the opened file uses a new-style CodeView - // record with a 128-bit GUID, or false if the opened file uses an old-style - // CodeView record. When no GUID is available, a 32-bit signature should be - // used to identify the module instead. If the information cannot be - // determined, this method returns false. - bool UsesGUID(bool *uses_guid); - - private: - // Outputs the line/address pairs for each line in the enumerator. - // Returns true on success. - bool PrintLines(IDiaEnumLineNumbers *lines); - - // Outputs a function address and name, followed by its source line list. - // block can be the same object as function, or it can be a reference - // to a code block that is lexically part of this function, but - // resides at a separate address. - // Returns true on success. - bool PrintFunction(IDiaSymbol *function, IDiaSymbol *block); - - // Outputs all functions as described above. Returns true on success. - bool PrintFunctions(); - - // Outputs all of the source files in the session's pdb file. - // Returns true on success. - bool PrintSourceFiles(); - - // Outputs all of the frame information necessary to construct stack - // backtraces in the absence of frame pointers. Returns true on success. - bool PrintFrameData(); - - // Outputs a single public symbol address and name, if the symbol corresponds - // to a code address. Returns true on success. If symbol is does not - // correspond to code, returns true without outputting anything. - bool PrintCodePublicSymbol(IDiaSymbol *symbol); - - // Outputs a line identifying the PDB file that is being dumped, along with - // its uuid and age. - bool PrintPDBInfo(); - - // Outputs a line identifying the PE file corresponding to the PDB - // file that is being dumped, along with its code identifier, - // which consists of its timestamp and file size. - bool PrintPEInfo(); - - // Returns true if this filename has already been seen, - // and an ID is stored for it, or false if it has not. - bool FileIDIsCached(const wstring &file) { - return unique_files_.find(file) != unique_files_.end(); - }; - - // Cache this filename and ID for later reuse. - void CacheFileID(const wstring &file, DWORD id) { - unique_files_[file] = id; - }; - - // Store this ID in the cache as a duplicate for this filename. - void StoreDuplicateFileID(const wstring &file, DWORD id) { - hash_map::iterator iter = unique_files_.find(file); - if (iter != unique_files_.end()) { - // map this id to the previously seen one - file_ids_[id] = iter->second; - } - }; - - // Given a file's unique ID, return the ID that should be used to - // reference it. There may be multiple files with identical filenames - // but different unique IDs. The cache attempts to coalesce these into - // one ID per unique filename. - DWORD GetRealFileID(DWORD id) { - hash_map::iterator iter = file_ids_.find(id); - if (iter == file_ids_.end()) - return id; - return iter->second; - }; - - // Find the PE file corresponding to the loaded PDB file, and - // set the code_file_ member. Returns false on failure. - bool FindPEFile(); - - // Returns the function name for a symbol. If possible, the name is - // undecorated. If the symbol's decorated form indicates the size of - // parameters on the stack, this information is returned in stack_param_size. - // Returns true on success. If the symbol doesn't encode parameter size - // information, stack_param_size is set to -1. - static bool GetSymbolFunctionName(IDiaSymbol *function, BSTR *name, - int *stack_param_size); - - // Returns the number of bytes of stack space used for a function's - // parameters. function must have the tag SymTagFunction. In the event of - // a failure, returns 0, which is also a valid number of bytes. - static int GetFunctionStackParamSize(IDiaSymbol *function); - - // The filename of the PE file corresponding to the currently-open - // pdb file. - wstring code_file_; - - // The session for the currently-open pdb file. - CComPtr session_; - - // The current output file for this WriteMap invocation. - FILE *output_; - - // There may be many duplicate filenames with different IDs. - // This maps from the DIA "unique ID" to a single ID per unique - // filename. - hash_map file_ids_; - // This maps unique filenames to file IDs. - hash_map unique_files_; - - // This is used for calculating post-transform symbol addresses and lengths. - ImageMap image_map_; - - // Disallow copy ctor and operator= - PDBSourceLineWriter(const PDBSourceLineWriter&); - void operator=(const PDBSourceLineWriter&); -}; - -} // namespace google_breakpad - -#endif // _PDB_SOURCE_LINE_WRITER_H__ diff --git a/breakpad/google_breakpad/common/minidump_cpu_arm.h b/breakpad/google_breakpad/common/minidump_cpu_arm.h deleted file mode 100644 index 6a7113833..000000000 --- a/breakpad/google_breakpad/common/minidump_cpu_arm.h +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright (c) 2009, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/* minidump_format.h: A cross-platform reimplementation of minidump-related - * portions of DbgHelp.h from the Windows Platform SDK. - * - * (This is C99 source, please don't corrupt it with C++.) - * - * This file contains the necessary definitions to read minidump files - * produced on ARM. These files may be read on any platform provided - * that the alignments of these structures on the processing system are - * identical to the alignments of these structures on the producing system. - * For this reason, precise-sized types are used. The structures defined - * by this file have been laid out to minimize alignment problems by - * ensuring that all members are aligned on their natural boundaries. - * In some cases, tail-padding may be significant when different ABIs specify - * different tail-padding behaviors. To avoid problems when reading or - * writing affected structures, MD_*_SIZE macros are provided where needed, - * containing the useful size of the structures without padding. - * - * Structures that are defined by Microsoft to contain a zero-length array - * are instead defined here to contain an array with one element, as - * zero-length arrays are forbidden by standard C and C++. In these cases, - * *_minsize constants are provided to be used in place of sizeof. For a - * cleaner interface to these sizes when using C++, see minidump_size.h. - * - * These structures are also sufficient to populate minidump files. - * - * Because precise data type sizes are crucial for this implementation to - * function properly and portably, a set of primitive types with known sizes - * are used as the basis of each structure defined by this file. - * - * Author: Julian Seward - */ - -/* - * ARM support - */ - -#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__ -#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__ - -#define MD_FLOATINGSAVEAREA_ARM_FPR_COUNT 32 -#define MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT 8 - -/* - * Note that these structures *do not* map directly to the CONTEXT - * structure defined in WinNT.h in the Windows Mobile SDK. That structure - * does not accomodate VFPv3, and I'm unsure if it was ever used in the - * wild anyway, as Windows CE only seems to produce "cedumps" which - * are not exactly minidumps. - */ -typedef struct { - uint64_t fpscr; /* FPU status register */ - - /* 32 64-bit floating point registers, d0 .. d31. */ - uint64_t regs[MD_FLOATINGSAVEAREA_ARM_FPR_COUNT]; - - /* Miscellaneous control words */ - uint32_t extra[MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT]; -} MDFloatingSaveAreaARM; - -#define MD_CONTEXT_ARM_GPR_COUNT 16 - -typedef struct { - /* The next field determines the layout of the structure, and which parts - * of it are populated - */ - uint32_t context_flags; - - /* 16 32-bit integer registers, r0 .. r15 - * Note the following fixed uses: - * r13 is the stack pointer - * r14 is the link register - * r15 is the program counter - */ - uint32_t iregs[MD_CONTEXT_ARM_GPR_COUNT]; - - /* CPSR (flags, basically): 32 bits: - bit 31 - N (negative) - bit 30 - Z (zero) - bit 29 - C (carry) - bit 28 - V (overflow) - bit 27 - Q (saturation flag, sticky) - All other fields -- ignore */ - uint32_t cpsr; - - /* The next field is included with MD_CONTEXT_ARM_FLOATING_POINT */ - MDFloatingSaveAreaARM float_save; - -} MDRawContextARM; - -/* Indices into iregs for registers with a dedicated or conventional - * purpose. - */ -enum MDARMRegisterNumbers { - MD_CONTEXT_ARM_REG_IOS_FP = 7, - MD_CONTEXT_ARM_REG_FP = 11, - MD_CONTEXT_ARM_REG_SP = 13, - MD_CONTEXT_ARM_REG_LR = 14, - MD_CONTEXT_ARM_REG_PC = 15 -}; - -/* For (MDRawContextARM).context_flags. These values indicate the type of - * context stored in the structure. */ -/* CONTEXT_ARM from the Windows CE 5.0 SDK. This value isn't correct - * because this bit can be used for flags. Presumably this value was - * never actually used in minidumps, but only in "CEDumps" which - * are a whole parallel minidump file format for Windows CE. - * Therefore, Breakpad defines its own value for ARM CPUs. - */ -#define MD_CONTEXT_ARM_OLD 0x00000040 -/* This value was chosen to avoid likely conflicts with MD_CONTEXT_* - * for other CPUs. */ -#define MD_CONTEXT_ARM 0x40000000 -#define MD_CONTEXT_ARM_INTEGER (MD_CONTEXT_ARM | 0x00000002) -#define MD_CONTEXT_ARM_FLOATING_POINT (MD_CONTEXT_ARM | 0x00000004) - -#define MD_CONTEXT_ARM_FULL (MD_CONTEXT_ARM_INTEGER | \ - MD_CONTEXT_ARM_FLOATING_POINT) - -#define MD_CONTEXT_ARM_ALL (MD_CONTEXT_ARM_INTEGER | \ - MD_CONTEXT_ARM_FLOATING_POINT) - -#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__ */ diff --git a/breakpad/google_breakpad/common/minidump_cpu_ppc.h b/breakpad/google_breakpad/common/minidump_cpu_ppc.h deleted file mode 100644 index 02ac32202..000000000 --- a/breakpad/google_breakpad/common/minidump_cpu_ppc.h +++ /dev/null @@ -1,163 +0,0 @@ -/* Copyright (c) 2006, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/* minidump_format.h: A cross-platform reimplementation of minidump-related - * portions of DbgHelp.h from the Windows Platform SDK. - * - * (This is C99 source, please don't corrupt it with C++.) - * - * This file contains the necessary definitions to read minidump files - * produced on ppc. These files may be read on any platform provided - * that the alignments of these structures on the processing system are - * identical to the alignments of these structures on the producing system. - * For this reason, precise-sized types are used. The structures defined - * by this file have been laid out to minimize alignment problems by ensuring - * ensuring that all members are aligned on their natural boundaries. In - * In some cases, tail-padding may be significant when different ABIs specify - * different tail-padding behaviors. To avoid problems when reading or - * writing affected structures, MD_*_SIZE macros are provided where needed, - * containing the useful size of the structures without padding. - * - * Structures that are defined by Microsoft to contain a zero-length array - * are instead defined here to contain an array with one element, as - * zero-length arrays are forbidden by standard C and C++. In these cases, - * *_minsize constants are provided to be used in place of sizeof. For a - * cleaner interface to these sizes when using C++, see minidump_size.h. - * - * These structures are also sufficient to populate minidump files. - * - * These definitions may be extended to support handling minidump files - * for other CPUs and other operating systems. - * - * Because precise data type sizes are crucial for this implementation to - * function properly and portably in terms of interoperability with minidumps - * produced by DbgHelp on Windows, a set of primitive types with known sizes - * are used as the basis of each structure defined by this file. DbgHelp - * on Windows is assumed to be the reference implementation; this file - * seeks to provide a cross-platform compatible implementation. To avoid - * collisions with the types and values defined and used by DbgHelp in the - * event that this implementation is used on Windows, each type and value - * defined here is given a new name, beginning with "MD". Names of the - * equivalent types and values in the Windows Platform SDK are given in - * comments. - * - * Author: Mark Mentovai - * Change to split into its own file: Neal Sidhwaney */ - -/* - * Breakpad minidump extension for PowerPC support. Based on Darwin/Mac OS X' - * mach/ppc/_types.h - */ - -#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ -#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ - -#define MD_FLOATINGSAVEAREA_PPC_FPR_COUNT 32 - -typedef struct { - /* fpregs is a double[32] in mach/ppc/_types.h, but a uint64_t is used - * here for precise sizing. */ - uint64_t fpregs[MD_FLOATINGSAVEAREA_PPC_FPR_COUNT]; - uint32_t fpscr_pad; - uint32_t fpscr; /* Status/control */ -} MDFloatingSaveAreaPPC; /* Based on ppc_float_state */ - - -#define MD_VECTORSAVEAREA_PPC_VR_COUNT 32 - -typedef struct { - /* Vector registers (including vscr) are 128 bits, but mach/ppc/_types.h - * exposes them as four 32-bit quantities. */ - uint128_struct save_vr[MD_VECTORSAVEAREA_PPC_VR_COUNT]; - uint128_struct save_vscr; /* Status/control */ - uint32_t save_pad5[4]; - uint32_t save_vrvalid; /* Indicates which vector registers are saved */ - uint32_t save_pad6[7]; -} MDVectorSaveAreaPPC; /* ppc_vector_state */ - - -#define MD_CONTEXT_PPC_GPR_COUNT 32 - -/* Use the same 32-bit alignment when accessing this structure from 64-bit code - * as is used natively in 32-bit code. #pragma pack is a MSVC extension - * supported by gcc. */ -#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) -#pragma pack(4) -#else -#pragma pack(push, 4) -#endif - -typedef struct { - /* context_flags is not present in ppc_thread_state, but it aids - * identification of MDRawContextPPC among other raw context types, - * and it guarantees alignment when we get to float_save. */ - uint32_t context_flags; - - uint32_t srr0; /* Machine status save/restore: stores pc - * (instruction) */ - uint32_t srr1; /* Machine status save/restore: stores msr - * (ps, program/machine state) */ - /* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is - * used for brevity. */ - uint32_t gpr[MD_CONTEXT_PPC_GPR_COUNT]; - uint32_t cr; /* Condition */ - uint32_t xer; /* Integer (fiXed-point) exception */ - uint32_t lr; /* Link */ - uint32_t ctr; /* Count */ - uint32_t mq; /* Multiply/Quotient (PPC 601, POWER only) */ - uint32_t vrsave; /* Vector save */ - - /* float_save and vector_save aren't present in ppc_thread_state, but - * are represented in separate structures that still define a thread's - * context. */ - MDFloatingSaveAreaPPC float_save; - MDVectorSaveAreaPPC vector_save; -} MDRawContextPPC; /* Based on ppc_thread_state */ - -#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) -#pragma pack(0) -#else -#pragma pack(pop) -#endif - -/* For (MDRawContextPPC).context_flags. These values indicate the type of - * context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its - * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other - * CPUs. */ -#define MD_CONTEXT_PPC 0x20000000 -#define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001) -#define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008) -#define MD_CONTEXT_PPC_VECTOR (MD_CONTEXT_PPC | 0x00000020) - -#define MD_CONTEXT_PPC_FULL MD_CONTEXT_PPC_BASE -#define MD_CONTEXT_PPC_ALL (MD_CONTEXT_PPC_FULL | \ - MD_CONTEXT_PPC_FLOATING_POINT | \ - MD_CONTEXT_PPC_VECTOR) - -#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ */ diff --git a/breakpad/google_breakpad/common/minidump_cpu_ppc64.h b/breakpad/google_breakpad/common/minidump_cpu_ppc64.h deleted file mode 100644 index 3a883230a..000000000 --- a/breakpad/google_breakpad/common/minidump_cpu_ppc64.h +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (c) 2008, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/* minidump_format.h: A cross-platform reimplementation of minidump-related - * portions of DbgHelp.h from the Windows Platform SDK. - * - * (This is C99 source, please don't corrupt it with C++.) - * - * This file contains the necessary definitions to read minidump files - * produced on ppc64. These files may be read on any platform provided - * that the alignments of these structures on the processing system are - * identical to the alignments of these structures on the producing system. - * For this reason, precise-sized types are used. The structures defined - * by this file have been laid out to minimize alignment problems by ensuring - * ensuring that all members are aligned on their natural boundaries. In - * In some cases, tail-padding may be significant when different ABIs specify - * different tail-padding behaviors. To avoid problems when reading or - * writing affected structures, MD_*_SIZE macros are provided where needed, - * containing the useful size of the structures without padding. - * - * Structures that are defined by Microsoft to contain a zero-length array - * are instead defined here to contain an array with one element, as - * zero-length arrays are forbidden by standard C and C++. In these cases, - * *_minsize constants are provided to be used in place of sizeof. For a - * cleaner interface to these sizes when using C++, see minidump_size.h. - * - * These structures are also sufficient to populate minidump files. - * - * These definitions may be extended to support handling minidump files - * for other CPUs and other operating systems. - * - * Because precise data type sizes are crucial for this implementation to - * function properly and portably in terms of interoperability with minidumps - * produced by DbgHelp on Windows, a set of primitive types with known sizes - * are used as the basis of each structure defined by this file. DbgHelp - * on Windows is assumed to be the reference implementation; this file - * seeks to provide a cross-platform compatible implementation. To avoid - * collisions with the types and values defined and used by DbgHelp in the - * event that this implementation is used on Windows, each type and value - * defined here is given a new name, beginning with "MD". Names of the - * equivalent types and values in the Windows Platform SDK are given in - * comments. - * - * Author: Neal Sidhwaney */ - - -/* - * Breakpad minidump extension for PPC64 support. Based on Darwin/Mac OS X' - * mach/ppc/_types.h - */ - -#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ -#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ - -#include "minidump_cpu_ppc.h" - -// these types are the same in ppc64 & ppc -typedef MDFloatingSaveAreaPPC MDFloatingSaveAreaPPC64; -typedef MDVectorSaveAreaPPC MDVectorSaveAreaPPC64; - -#define MD_CONTEXT_PPC64_GPR_COUNT MD_CONTEXT_PPC_GPR_COUNT - -typedef struct { - /* context_flags is not present in ppc_thread_state, but it aids - * identification of MDRawContextPPC among other raw context types, - * and it guarantees alignment when we get to float_save. */ - uint64_t context_flags; - - uint64_t srr0; /* Machine status save/restore: stores pc - * (instruction) */ - uint64_t srr1; /* Machine status save/restore: stores msr - * (ps, program/machine state) */ - /* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is - * used for brevity. */ - uint64_t gpr[MD_CONTEXT_PPC64_GPR_COUNT]; - uint64_t cr; /* Condition */ - uint64_t xer; /* Integer (fiXed-point) exception */ - uint64_t lr; /* Link */ - uint64_t ctr; /* Count */ - uint64_t vrsave; /* Vector save */ - - /* float_save and vector_save aren't present in ppc_thread_state, but - * are represented in separate structures that still define a thread's - * context. */ - MDFloatingSaveAreaPPC float_save; - MDVectorSaveAreaPPC vector_save; -} MDRawContextPPC64; /* Based on ppc_thread_state */ - -/* For (MDRawContextPPC).context_flags. These values indicate the type of - * context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its - * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other - * CPUs. */ -#define MD_CONTEXT_PPC64 0x01000000 -#define MD_CONTEXT_PPC64_BASE (MD_CONTEXT_PPC64 | 0x00000001) -#define MD_CONTEXT_PPC64_FLOATING_POINT (MD_CONTEXT_PPC64 | 0x00000008) -#define MD_CONTEXT_PPC64_VECTOR (MD_CONTEXT_PPC64 | 0x00000020) - -#define MD_CONTEXT_PPC64_FULL MD_CONTEXT_PPC64_BASE -#define MD_CONTEXT_PPC64_ALL (MD_CONTEXT_PPC64_FULL | \ - MD_CONTEXT_PPC64_FLOATING_POINT | \ - MD_CONTEXT_PPC64_VECTOR) - -#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ */ diff --git a/breakpad/google_breakpad/common/minidump_cpu_sparc.h b/breakpad/google_breakpad/common/minidump_cpu_sparc.h deleted file mode 100644 index ddc4c7590..000000000 --- a/breakpad/google_breakpad/common/minidump_cpu_sparc.h +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright (c) 2006, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/* minidump_format.h: A cross-platform reimplementation of minidump-related - * portions of DbgHelp.h from the Windows Platform SDK. - * - * (This is C99 source, please don't corrupt it with C++.) - * - * This file contains the necessary definitions to read minidump files - * produced on sparc. These files may be read on any platform provided - * that the alignments of these structures on the processing system are - * identical to the alignments of these structures on the producing system. - * For this reason, precise-sized types are used. The structures defined - * by this file have been laid out to minimize alignment problems by ensuring - * ensuring that all members are aligned on their natural boundaries. In - * In some cases, tail-padding may be significant when different ABIs specify - * different tail-padding behaviors. To avoid problems when reading or - * writing affected structures, MD_*_SIZE macros are provided where needed, - * containing the useful size of the structures without padding. - * - * Structures that are defined by Microsoft to contain a zero-length array - * are instead defined here to contain an array with one element, as - * zero-length arrays are forbidden by standard C and C++. In these cases, - * *_minsize constants are provided to be used in place of sizeof. For a - * cleaner interface to these sizes when using C++, see minidump_size.h. - * - * These structures are also sufficient to populate minidump files. - * - * These definitions may be extended to support handling minidump files - * for other CPUs and other operating systems. - * - * Because precise data type sizes are crucial for this implementation to - * function properly and portably in terms of interoperability with minidumps - * produced by DbgHelp on Windows, a set of primitive types with known sizes - * are used as the basis of each structure defined by this file. DbgHelp - * on Windows is assumed to be the reference implementation; this file - * seeks to provide a cross-platform compatible implementation. To avoid - * collisions with the types and values defined and used by DbgHelp in the - * event that this implementation is used on Windows, each type and value - * defined here is given a new name, beginning with "MD". Names of the - * equivalent types and values in the Windows Platform SDK are given in - * comments. - * - * Author: Mark Mentovai - * Change to split into its own file: Neal Sidhwaney */ - -/* - * SPARC support, see (solaris)sys/procfs_isa.h also - */ - -#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ -#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ - -#define MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT 32 - -typedef struct { - - /* FPU floating point regs */ - uint64_t regs[MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT]; - - uint64_t filler; - uint64_t fsr; /* FPU status register */ -} MDFloatingSaveAreaSPARC; /* FLOATING_SAVE_AREA */ - -#define MD_CONTEXT_SPARC_GPR_COUNT 32 - -typedef struct { - /* The next field determines the layout of the structure, and which parts - * of it are populated - */ - uint32_t context_flags; - uint32_t flag_pad; - /* - * General register access (SPARC). - * Don't confuse definitions here with definitions in . - * Registers are 32 bits for ILP32, 64 bits for LP64. - * SPARC V7/V8 is for 32bit, SPARC V9 is for 64bit - */ - - /* 32 Integer working registers */ - - /* g_r[0-7] global registers(g0-g7) - * g_r[8-15] out registers(o0-o7) - * g_r[16-23] local registers(l0-l7) - * g_r[24-31] in registers(i0-i7) - */ - uint64_t g_r[MD_CONTEXT_SPARC_GPR_COUNT]; - - /* several control registers */ - - /* Processor State register(PSR) for SPARC V7/V8 - * Condition Code register (CCR) for SPARC V9 - */ - uint64_t ccr; - - uint64_t pc; /* Program Counter register (PC) */ - uint64_t npc; /* Next Program Counter register (nPC) */ - uint64_t y; /* Y register (Y) */ - - /* Address Space Identifier register (ASI) for SPARC V9 - * WIM for SPARC V7/V8 - */ - uint64_t asi; - - /* Floating-Point Registers State register (FPRS) for SPARC V9 - * TBR for for SPARC V7/V8 - */ - uint64_t fprs; - - /* The next field is included with MD_CONTEXT_SPARC_FLOATING_POINT */ - MDFloatingSaveAreaSPARC float_save; - -} MDRawContextSPARC; /* CONTEXT_SPARC */ - -/* For (MDRawContextSPARC).context_flags. These values indicate the type of - * context stored in the structure. MD_CONTEXT_SPARC is Breakpad-defined. Its - * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other - * CPUs. */ -#define MD_CONTEXT_SPARC 0x10000000 -#define MD_CONTEXT_SPARC_CONTROL (MD_CONTEXT_SPARC | 0x00000001) -#define MD_CONTEXT_SPARC_INTEGER (MD_CONTEXT_SPARC | 0x00000002) -#define MD_CONTEXT_SAPARC_FLOATING_POINT (MD_CONTEXT_SPARC | 0x00000004) -#define MD_CONTEXT_SAPARC_EXTRA (MD_CONTEXT_SPARC | 0x00000008) - -#define MD_CONTEXT_SPARC_FULL (MD_CONTEXT_SPARC_CONTROL | \ - MD_CONTEXT_SPARC_INTEGER) - -#define MD_CONTEXT_SPARC_ALL (MD_CONTEXT_SPARC_FULL | \ - MD_CONTEXT_SAPARC_FLOATING_POINT | \ - MD_CONTEXT_SAPARC_EXTRA) - -#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ */ diff --git a/breakpad/google_breakpad/common/minidump_exception_linux.h b/breakpad/google_breakpad/common/minidump_exception_linux.h deleted file mode 100644 index 9e7e4f1e1..000000000 --- a/breakpad/google_breakpad/common/minidump_exception_linux.h +++ /dev/null @@ -1,87 +0,0 @@ -/* Copyright (c) 2006, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/* minidump_exception_linux.h: A definition of exception codes for - * Linux - * - * (This is C99 source, please don't corrupt it with C++.) - * - * Author: Mark Mentovai - * Split into its own file: Neal Sidhwaney */ - - -#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ -#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ - -#include - -#include "google_breakpad/common/breakpad_types.h" - - -/* For (MDException).exception_code. These values come from bits/signum.h. - */ -typedef enum { - MD_EXCEPTION_CODE_LIN_SIGHUP = 1, /* Hangup (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGINT = 2, /* Interrupt (ANSI) */ - MD_EXCEPTION_CODE_LIN_SIGQUIT = 3, /* Quit (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGILL = 4, /* Illegal instruction (ANSI) */ - MD_EXCEPTION_CODE_LIN_SIGTRAP = 5, /* Trace trap (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGABRT = 6, /* Abort (ANSI) */ - MD_EXCEPTION_CODE_LIN_SIGBUS = 7, /* BUS error (4.2 BSD) */ - MD_EXCEPTION_CODE_LIN_SIGFPE = 8, /* Floating-point exception (ANSI) */ - MD_EXCEPTION_CODE_LIN_SIGKILL = 9, /* Kill, unblockable (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGUSR1 = 10, /* User-defined signal 1 (POSIX). */ - MD_EXCEPTION_CODE_LIN_SIGSEGV = 11, /* Segmentation violation (ANSI) */ - MD_EXCEPTION_CODE_LIN_SIGUSR2 = 12, /* User-defined signal 2 (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGPIPE = 13, /* Broken pipe (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGALRM = 14, /* Alarm clock (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGTERM = 15, /* Termination (ANSI) */ - MD_EXCEPTION_CODE_LIN_SIGSTKFLT = 16, /* Stack faultd */ - MD_EXCEPTION_CODE_LIN_SIGCHLD = 17, /* Child status has changed (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGCONT = 18, /* Continue (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGSTOP = 19, /* Stop, unblockable (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGTSTP = 20, /* Keyboard stop (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGTTIN = 21, /* Background read from tty (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGTTOU = 22, /* Background write to tty (POSIX) */ - MD_EXCEPTION_CODE_LIN_SIGURG = 23, - /* Urgent condition on socket (4.2 BSD) */ - MD_EXCEPTION_CODE_LIN_SIGXCPU = 24, /* CPU limit exceeded (4.2 BSD) */ - MD_EXCEPTION_CODE_LIN_SIGXFSZ = 25, - /* File size limit exceeded (4.2 BSD) */ - MD_EXCEPTION_CODE_LIN_SIGVTALRM = 26, /* Virtual alarm clock (4.2 BSD) */ - MD_EXCEPTION_CODE_LIN_SIGPROF = 27, /* Profiling alarm clock (4.2 BSD) */ - MD_EXCEPTION_CODE_LIN_SIGWINCH = 28, /* Window size change (4.3 BSD, Sun) */ - MD_EXCEPTION_CODE_LIN_SIGIO = 29, /* I/O now possible (4.2 BSD) */ - MD_EXCEPTION_CODE_LIN_SIGPWR = 30, /* Power failure restart (System V) */ - MD_EXCEPTION_CODE_LIN_SIGSYS = 31, /* Bad system call */ - MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED = 0xFFFFFFFF /* No exception, - dump requested. */ -} MDExceptionCodeLinux; - -#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ */ diff --git a/breakpad/google_breakpad/common/minidump_exception_mac.h b/breakpad/google_breakpad/common/minidump_exception_mac.h deleted file mode 100644 index 91c1c0974..000000000 --- a/breakpad/google_breakpad/common/minidump_exception_mac.h +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (c) 2006, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/* minidump_exception_mac.h: A definition of exception codes for Mac - * OS X - * - * (This is C99 source, please don't corrupt it with C++.) - * - * Author: Mark Mentovai - * Split into its own file: Neal Sidhwaney */ - - -#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__ -#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__ - -#include - -#include "google_breakpad/common/breakpad_types.h" - -/* For (MDException).exception_code. Breakpad minidump extension for Mac OS X - * support. Based on Darwin/Mac OS X' mach/exception_types.h. This is - * what Mac OS X calls an "exception", not a "code". */ -typedef enum { - /* Exception code. The high 16 bits of exception_code contains one of - * these values. */ - MD_EXCEPTION_MAC_BAD_ACCESS = 1, /* code can be a kern_return_t */ - /* EXC_BAD_ACCESS */ - MD_EXCEPTION_MAC_BAD_INSTRUCTION = 2, /* code is CPU-specific */ - /* EXC_BAD_INSTRUCTION */ - MD_EXCEPTION_MAC_ARITHMETIC = 3, /* code is CPU-specific */ - /* EXC_ARITHMETIC */ - MD_EXCEPTION_MAC_EMULATION = 4, /* code is CPU-specific */ - /* EXC_EMULATION */ - MD_EXCEPTION_MAC_SOFTWARE = 5, - /* EXC_SOFTWARE */ - MD_EXCEPTION_MAC_BREAKPOINT = 6, /* code is CPU-specific */ - /* EXC_BREAKPOINT */ - MD_EXCEPTION_MAC_SYSCALL = 7, - /* EXC_SYSCALL */ - MD_EXCEPTION_MAC_MACH_SYSCALL = 8, - /* EXC_MACH_SYSCALL */ - MD_EXCEPTION_MAC_RPC_ALERT = 9 - /* EXC_RPC_ALERT */ -} MDExceptionMac; - -/* For (MDException).exception_flags. Breakpad minidump extension for Mac OS X - * support. Based on Darwin/Mac OS X' mach/ppc/exception.h and - * mach/i386/exception.h. This is what Mac OS X calls a "code". */ -typedef enum { - /* With MD_EXCEPTION_BAD_ACCESS. These are relevant kern_return_t values - * from mach/kern_return.h. */ - MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS = 1, - /* KERN_INVALID_ADDRESS */ - MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE = 2, - /* KERN_PROTECTION_FAILURE */ - MD_EXCEPTION_CODE_MAC_NO_ACCESS = 8, - /* KERN_NO_ACCESS */ - MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE = 9, - /* KERN_MEMORY_FAILURE */ - MD_EXCEPTION_CODE_MAC_MEMORY_ERROR = 10, - /* KERN_MEMORY_ERROR */ - - /* With MD_EXCEPTION_SOFTWARE */ - MD_EXCEPTION_CODE_MAC_BAD_SYSCALL = 0x00010000, /* Mach SIGSYS */ - MD_EXCEPTION_CODE_MAC_BAD_PIPE = 0x00010001, /* Mach SIGPIPE */ - MD_EXCEPTION_CODE_MAC_ABORT = 0x00010002, /* Mach SIGABRT */ - /* Custom values */ - MD_EXCEPTION_CODE_MAC_NS_EXCEPTION = 0xDEADC0DE, /* uncaught NSException */ - - /* With MD_EXCEPTION_MAC_BAD_ACCESS on arm */ - MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN = 0x0101, /* EXC_ARM_DA_ALIGN */ - MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG = 0x0102, /* EXC_ARM_DA_DEBUG */ - - /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on arm */ - MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED = 1, /* EXC_ARM_UNDEFINED */ - - /* With MD_EXCEPTION_MAC_BREAKPOINT on arm */ - MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT = 1, /* EXC_ARM_BREAKPOINT */ - - /* With MD_EXCEPTION_MAC_BAD_ACCESS on ppc */ - MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ = 0x0101, - /* EXC_PPC_VM_PROT_READ */ - MD_EXCEPTION_CODE_MAC_PPC_BADSPACE = 0x0102, - /* EXC_PPC_BADSPACE */ - MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED = 0x0103, - /* EXC_PPC_UNALIGNED */ - - /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on ppc */ - MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL = 1, - /* EXC_PPC_INVALID_SYSCALL */ - MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION = 2, - /* EXC_PPC_UNIPL_INST */ - MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION = 3, - /* EXC_PPC_PRIVINST */ - MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER = 4, - /* EXC_PPC_PRIVREG */ - MD_EXCEPTION_CODE_MAC_PPC_TRACE = 5, - /* EXC_PPC_TRACE */ - MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR = 6, - /* EXC_PPC_PERFMON */ - - /* With MD_EXCEPTION_MAC_ARITHMETIC on ppc */ - MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW = 1, - /* EXC_PPC_OVERFLOW */ - MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE = 2, - /* EXC_PPC_ZERO_DIVIDE */ - MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT = 3, - /* EXC_FLT_INEXACT */ - MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE = 4, - /* EXC_PPC_FLT_ZERO_DIVIDE */ - MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW = 5, - /* EXC_PPC_FLT_UNDERFLOW */ - MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW = 6, - /* EXC_PPC_FLT_OVERFLOW */ - MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER = 7, - /* EXC_PPC_FLT_NOT_A_NUMBER */ - - /* With MD_EXCEPTION_MAC_EMULATION on ppc */ - MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION = 8, - /* EXC_PPC_NOEMULATION */ - MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST = 9, - /* EXC_PPC_ALTIVECASSIST */ - - /* With MD_EXCEPTION_MAC_SOFTWARE on ppc */ - MD_EXCEPTION_CODE_MAC_PPC_TRAP = 0x00000001, /* EXC_PPC_TRAP */ - MD_EXCEPTION_CODE_MAC_PPC_MIGRATE = 0x00010100, /* EXC_PPC_MIGRATE */ - - /* With MD_EXCEPTION_MAC_BREAKPOINT on ppc */ - MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT = 1, /* EXC_PPC_BREAKPOINT */ - - /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86, see also x86 interrupt - * values below. */ - MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION = 1, /* EXC_I386_INVOP */ - - /* With MD_EXCEPTION_MAC_ARITHMETIC on x86 */ - MD_EXCEPTION_CODE_MAC_X86_DIV = 1, /* EXC_I386_DIV */ - MD_EXCEPTION_CODE_MAC_X86_INTO = 2, /* EXC_I386_INTO */ - MD_EXCEPTION_CODE_MAC_X86_NOEXT = 3, /* EXC_I386_NOEXT */ - MD_EXCEPTION_CODE_MAC_X86_EXTOVR = 4, /* EXC_I386_EXTOVR */ - MD_EXCEPTION_CODE_MAC_X86_EXTERR = 5, /* EXC_I386_EXTERR */ - MD_EXCEPTION_CODE_MAC_X86_EMERR = 6, /* EXC_I386_EMERR */ - MD_EXCEPTION_CODE_MAC_X86_BOUND = 7, /* EXC_I386_BOUND */ - MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR = 8, /* EXC_I386_SSEEXTERR */ - - /* With MD_EXCEPTION_MAC_BREAKPOINT on x86 */ - MD_EXCEPTION_CODE_MAC_X86_SGL = 1, /* EXC_I386_SGL */ - MD_EXCEPTION_CODE_MAC_X86_BPT = 2, /* EXC_I386_BPT */ - - /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86. These are the raw - * x86 interrupt codes. Most of these are mapped to other Mach - * exceptions and codes, are handled, or should not occur in user space. - * A few of these will do occur with MD_EXCEPTION_MAC_BAD_INSTRUCTION. */ - /* EXC_I386_DIVERR = 0: mapped to EXC_ARITHMETIC/EXC_I386_DIV */ - /* EXC_I386_SGLSTP = 1: mapped to EXC_BREAKPOINT/EXC_I386_SGL */ - /* EXC_I386_NMIFLT = 2: should not occur in user space */ - /* EXC_I386_BPTFLT = 3: mapped to EXC_BREAKPOINT/EXC_I386_BPT */ - /* EXC_I386_INTOFLT = 4: mapped to EXC_ARITHMETIC/EXC_I386_INTO */ - /* EXC_I386_BOUNDFLT = 5: mapped to EXC_ARITHMETIC/EXC_I386_BOUND */ - /* EXC_I386_INVOPFLT = 6: mapped to EXC_BAD_INSTRUCTION/EXC_I386_INVOP */ - /* EXC_I386_NOEXTFLT = 7: should be handled by the kernel */ - /* EXC_I386_DBLFLT = 8: should be handled (if possible) by the kernel */ - /* EXC_I386_EXTOVRFLT = 9: mapped to EXC_BAD_ACCESS/(PROT_READ|PROT_EXEC) */ - MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT = 10, - /* EXC_INVTSSFLT */ - MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT = 11, - /* EXC_SEGNPFLT */ - MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT = 12, - /* EXC_STKFLT */ - MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT = 13, - /* EXC_GPFLT */ - /* EXC_I386_PGFLT = 14: should not occur in user space */ - /* EXC_I386_EXTERRFLT = 16: mapped to EXC_ARITHMETIC/EXC_I386_EXTERR */ - MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT = 17 - /* EXC_ALIGNFLT (for vector operations) */ - /* EXC_I386_ENOEXTFLT = 32: should be handled by the kernel */ - /* EXC_I386_ENDPERR = 33: should not occur */ -} MDExceptionCodeMac; - -#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_OSX_H__ */ diff --git a/breakpad/google_breakpad/common/minidump_exception_ps3.h b/breakpad/google_breakpad/common/minidump_exception_ps3.h deleted file mode 100644 index adff5a6bb..000000000 --- a/breakpad/google_breakpad/common/minidump_exception_ps3.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (c) 2013, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/* minidump_exception_ps3.h: A definition of exception codes for - * PS3 */ - - -#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_PS3_H__ -#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_PS3_H__ - -#include - -#include "google_breakpad/common/breakpad_types.h" - -typedef enum { - MD_EXCEPTION_CODE_PS3_UNKNOWN = 0, - MD_EXCEPTION_CODE_PS3_TRAP_EXCEP = 1, - MD_EXCEPTION_CODE_PS3_PRIV_INSTR = 2, - MD_EXCEPTION_CODE_PS3_ILLEGAL_INSTR = 3, - MD_EXCEPTION_CODE_PS3_INSTR_STORAGE = 4, - MD_EXCEPTION_CODE_PS3_INSTR_SEGMENT = 5, - MD_EXCEPTION_CODE_PS3_DATA_STORAGE = 6, - MD_EXCEPTION_CODE_PS3_DATA_SEGMENT = 7, - MD_EXCEPTION_CODE_PS3_FLOAT_POINT = 8, - MD_EXCEPTION_CODE_PS3_DABR_MATCH = 9, - MD_EXCEPTION_CODE_PS3_ALIGN_EXCEP = 10, - MD_EXCEPTION_CODE_PS3_MEMORY_ACCESS = 11, - MD_EXCEPTION_CODE_PS3_COPRO_ALIGN = 12, - MD_EXCEPTION_CODE_PS3_COPRO_INVALID_COM = 13, - MD_EXCEPTION_CODE_PS3_COPRO_ERR = 14, - MD_EXCEPTION_CODE_PS3_COPRO_FIR = 15, - MD_EXCEPTION_CODE_PS3_COPRO_DATA_SEGMENT = 16, - MD_EXCEPTION_CODE_PS3_COPRO_DATA_STORAGE = 17, - MD_EXCEPTION_CODE_PS3_COPRO_STOP_INSTR = 18, - MD_EXCEPTION_CODE_PS3_COPRO_HALT_INSTR = 19, - MD_EXCEPTION_CODE_PS3_COPRO_HALTINST_UNKNOWN = 20, - MD_EXCEPTION_CODE_PS3_COPRO_MEMORY_ACCESS = 21, - MD_EXCEPTION_CODE_PS3_GRAPHIC = 22 -} MDExceptionCodePS3; - -#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_PS3_H__ */ diff --git a/breakpad/google_breakpad/common/minidump_exception_solaris.h b/breakpad/google_breakpad/common/minidump_exception_solaris.h deleted file mode 100644 index f18ddf424..000000000 --- a/breakpad/google_breakpad/common/minidump_exception_solaris.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright (c) 2006, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/* minidump_exception_solaris.h: A definition of exception codes for - * Solaris - * - * (This is C99 source, please don't corrupt it with C++.) - * - * Author: Mark Mentovai - * Split into its own file: Neal Sidhwaney */ - - -#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ -#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ - -#include - -#include "google_breakpad/common/breakpad_types.h" - -/* For (MDException).exception_code. These values come from sys/iso/signal_iso.h - */ -typedef enum { - MD_EXCEPTION_CODE_SOL_SIGHUP = 1, /* Hangup */ - MD_EXCEPTION_CODE_SOL_SIGINT = 2, /* interrupt (rubout) */ - MD_EXCEPTION_CODE_SOL_SIGQUIT = 3, /* quit (ASCII FS) */ - MD_EXCEPTION_CODE_SOL_SIGILL = 4, /* illegal instruction (not reset when caught) */ - MD_EXCEPTION_CODE_SOL_SIGTRAP = 5, /* trace trap (not reset when caught) */ - MD_EXCEPTION_CODE_SOL_SIGIOT = 6, /* IOT instruction */ - MD_EXCEPTION_CODE_SOL_SIGABRT = 6, /* used by abort, replace SIGIOT in the future */ - MD_EXCEPTION_CODE_SOL_SIGEMT = 7, /* EMT instruction */ - MD_EXCEPTION_CODE_SOL_SIGFPE = 8, /* floating point exception */ - MD_EXCEPTION_CODE_SOL_SIGKILL = 9, /* kill (cannot be caught or ignored) */ - MD_EXCEPTION_CODE_SOL_SIGBUS = 10, /* bus error */ - MD_EXCEPTION_CODE_SOL_SIGSEGV = 11, /* segmentation violation */ - MD_EXCEPTION_CODE_SOL_SIGSYS = 12, /* bad argument to system call */ - MD_EXCEPTION_CODE_SOL_SIGPIPE = 13, /* write on a pipe with no one to read it */ - MD_EXCEPTION_CODE_SOL_SIGALRM = 14, /* alarm clock */ - MD_EXCEPTION_CODE_SOL_SIGTERM = 15, /* software termination signal from kill */ - MD_EXCEPTION_CODE_SOL_SIGUSR1 = 16, /* user defined signal 1 */ - MD_EXCEPTION_CODE_SOL_SIGUSR2 = 17, /* user defined signal 2 */ - MD_EXCEPTION_CODE_SOL_SIGCLD = 18, /* child status change */ - MD_EXCEPTION_CODE_SOL_SIGCHLD = 18, /* child status change alias (POSIX) */ - MD_EXCEPTION_CODE_SOL_SIGPWR = 19, /* power-fail restart */ - MD_EXCEPTION_CODE_SOL_SIGWINCH = 20, /* window size change */ - MD_EXCEPTION_CODE_SOL_SIGURG = 21, /* urgent socket condition */ - MD_EXCEPTION_CODE_SOL_SIGPOLL = 22, /* pollable event occurred */ - MD_EXCEPTION_CODE_SOL_SIGIO = 22, /* socket I/O possible (SIGPOLL alias) */ - MD_EXCEPTION_CODE_SOL_SIGSTOP = 23, /* stop (cannot be caught or ignored) */ - MD_EXCEPTION_CODE_SOL_SIGTSTP = 24, /* user stop requested from tty */ - MD_EXCEPTION_CODE_SOL_SIGCONT = 25, /* stopped process has been continued */ - MD_EXCEPTION_CODE_SOL_SIGTTIN = 26, /* background tty read attempted */ - MD_EXCEPTION_CODE_SOL_SIGTTOU = 27, /* background tty write attempted */ - MD_EXCEPTION_CODE_SOL_SIGVTALRM = 28, /* virtual timer expired */ - MD_EXCEPTION_CODE_SOL_SIGPROF = 29, /* profiling timer expired */ - MD_EXCEPTION_CODE_SOL_SIGXCPU = 30, /* exceeded cpu limit */ - MD_EXCEPTION_CODE_SOL_SIGXFSZ = 31, /* exceeded file size limit */ - MD_EXCEPTION_CODE_SOL_SIGWAITING = 32, /* reserved signal no longer used by threading code */ - MD_EXCEPTION_CODE_SOL_SIGLWP = 33, /* reserved signal no longer used by threading code */ - MD_EXCEPTION_CODE_SOL_SIGFREEZE = 34, /* special signal used by CPR */ - MD_EXCEPTION_CODE_SOL_SIGTHAW = 35, /* special signal used by CPR */ - MD_EXCEPTION_CODE_SOL_SIGCANCEL = 36, /* reserved signal for thread cancellation */ - MD_EXCEPTION_CODE_SOL_SIGLOST = 37, /* resource lost (eg, record-lock lost) */ - MD_EXCEPTION_CODE_SOL_SIGXRES = 38, /* resource control exceeded */ - MD_EXCEPTION_CODE_SOL_SIGJVM1 = 39, /* reserved signal for Java Virtual Machine */ - MD_EXCEPTION_CODE_SOL_SIGJVM2 = 40 /* reserved signal for Java Virtual Machine */ -} MDExceptionCodeSolaris; - -#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ */ diff --git a/breakpad/google_breakpad/common/minidump_size.h b/breakpad/google_breakpad/common/minidump_size.h deleted file mode 100644 index 918544b66..000000000 --- a/breakpad/google_breakpad/common/minidump_size.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -// minidump_size.h: Provides a C++ template for programmatic access to -// the sizes of various types defined in minidump_format.h. -// -// Author: Mark Mentovai - -#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__ -#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__ - -#include - -#include "google_breakpad/common/minidump_format.h" - -namespace google_breakpad { - -template -class minidump_size { - public: - static size_t size() { return sizeof(T); } -}; - -// Explicit specializations for variable-length types. The size returned -// for these should be the size for an object without its variable-length -// section. - -template<> -class minidump_size { - public: - static size_t size() { return MDString_minsize; } -}; - -template<> -class minidump_size { - public: - static size_t size() { return MDRawThreadList_minsize; } -}; - -template<> -class minidump_size { - public: - static size_t size() { return MDCVInfoPDB20_minsize; } -}; - -template<> -class minidump_size { - public: - static size_t size() { return MDCVInfoPDB70_minsize; } -}; - -template<> -class minidump_size { - public: - static size_t size() { return MDImageDebugMisc_minsize; } -}; - -template<> -class minidump_size { - public: - static size_t size() { return MDRawModuleList_minsize; } -}; - -template<> -class minidump_size { - public: - static size_t size() { return MDRawMemoryList_minsize; } -}; - -// Explicit specialization for MDRawModule, for which sizeof may include -// tail-padding on some architectures but not others. - -template<> -class minidump_size { - public: - static size_t size() { return MD_MODULE_SIZE; } -}; - -} // namespace google_breakpad - -#endif // GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__ diff --git a/breakpad/v100/lib32/breakpad_common.lib b/breakpad/v100/lib32/breakpad_common.lib deleted file mode 100644 index 71d71adfd..000000000 Binary files a/breakpad/v100/lib32/breakpad_common.lib and /dev/null differ diff --git a/breakpad/v100/lib32/crash_generation_client.lib b/breakpad/v100/lib32/crash_generation_client.lib deleted file mode 100644 index 06cc0f85e..000000000 Binary files a/breakpad/v100/lib32/crash_generation_client.lib and /dev/null differ diff --git a/breakpad/v100/lib32/crash_generation_server.lib b/breakpad/v100/lib32/crash_generation_server.lib deleted file mode 100644 index 91457a75c..000000000 Binary files a/breakpad/v100/lib32/crash_generation_server.lib and /dev/null differ diff --git a/breakpad/v100/lib32/exception_handler.lib b/breakpad/v100/lib32/exception_handler.lib deleted file mode 100644 index b24390889..000000000 Binary files a/breakpad/v100/lib32/exception_handler.lib and /dev/null differ diff --git a/breakpad/v100/lib64/breakpad_common.lib b/breakpad/v100/lib64/breakpad_common.lib deleted file mode 100644 index c1732b98a..000000000 Binary files a/breakpad/v100/lib64/breakpad_common.lib and /dev/null differ diff --git a/breakpad/v100/lib64/crash_generation_client.lib b/breakpad/v100/lib64/crash_generation_client.lib deleted file mode 100644 index 83cee0e4c..000000000 Binary files a/breakpad/v100/lib64/crash_generation_client.lib and /dev/null differ diff --git a/breakpad/v100/lib64/crash_generation_server.lib b/breakpad/v100/lib64/crash_generation_server.lib deleted file mode 100644 index 5edd72570..000000000 Binary files a/breakpad/v100/lib64/crash_generation_server.lib and /dev/null differ diff --git a/breakpad/v100/lib64/exception_handler.lib b/breakpad/v100/lib64/exception_handler.lib deleted file mode 100644 index fc74515bd..000000000 Binary files a/breakpad/v100/lib64/exception_handler.lib and /dev/null differ diff --git a/breakpad/v110/lib32/breakpad_common.lib b/breakpad/v110/lib32/breakpad_common.lib deleted file mode 100644 index cd0cfb59e..000000000 Binary files a/breakpad/v110/lib32/breakpad_common.lib and /dev/null differ diff --git a/breakpad/v110/lib32/crash_generation_client.lib b/breakpad/v110/lib32/crash_generation_client.lib deleted file mode 100644 index 62e68d946..000000000 Binary files a/breakpad/v110/lib32/crash_generation_client.lib and /dev/null differ diff --git a/breakpad/v110/lib32/crash_generation_server.lib b/breakpad/v110/lib32/crash_generation_server.lib deleted file mode 100644 index 802f787be..000000000 Binary files a/breakpad/v110/lib32/crash_generation_server.lib and /dev/null differ diff --git a/breakpad/v110/lib32/exception_handler.lib b/breakpad/v110/lib32/exception_handler.lib deleted file mode 100644 index e9fd179a4..000000000 Binary files a/breakpad/v110/lib32/exception_handler.lib and /dev/null differ diff --git a/breakpad/v110/lib64/breakpad_common.lib b/breakpad/v110/lib64/breakpad_common.lib deleted file mode 100644 index d6f868e75..000000000 Binary files a/breakpad/v110/lib64/breakpad_common.lib and /dev/null differ diff --git a/breakpad/v110/lib64/crash_generation_client.lib b/breakpad/v110/lib64/crash_generation_client.lib deleted file mode 100644 index 1f8a69805..000000000 Binary files a/breakpad/v110/lib64/crash_generation_client.lib and /dev/null differ diff --git a/breakpad/v110/lib64/crash_generation_server.lib b/breakpad/v110/lib64/crash_generation_server.lib deleted file mode 100644 index 3a72962ca..000000000 Binary files a/breakpad/v110/lib64/crash_generation_server.lib and /dev/null differ diff --git a/breakpad/v110/lib64/exception_handler.lib b/breakpad/v110/lib64/exception_handler.lib deleted file mode 100644 index e64127372..000000000 Binary files a/breakpad/v110/lib64/exception_handler.lib and /dev/null differ diff --git a/breakpad/v120/lib32/breakpad_common.lib b/breakpad/v120/lib32/breakpad_common.lib deleted file mode 100644 index 47876b504..000000000 Binary files a/breakpad/v120/lib32/breakpad_common.lib and /dev/null differ diff --git a/breakpad/v120/lib32/crash_generation_client.lib b/breakpad/v120/lib32/crash_generation_client.lib deleted file mode 100644 index aace8f85a..000000000 Binary files a/breakpad/v120/lib32/crash_generation_client.lib and /dev/null differ diff --git a/breakpad/v120/lib32/crash_generation_server.lib b/breakpad/v120/lib32/crash_generation_server.lib deleted file mode 100644 index 97fa36029..000000000 Binary files a/breakpad/v120/lib32/crash_generation_server.lib and /dev/null differ diff --git a/breakpad/v120/lib32/exception_handler.lib b/breakpad/v120/lib32/exception_handler.lib deleted file mode 100644 index e7f187b2a..000000000 Binary files a/breakpad/v120/lib32/exception_handler.lib and /dev/null differ diff --git a/breakpad/v120/lib64/breakpad_common.lib b/breakpad/v120/lib64/breakpad_common.lib deleted file mode 100644 index 41f442ddf..000000000 Binary files a/breakpad/v120/lib64/breakpad_common.lib and /dev/null differ diff --git a/breakpad/v120/lib64/crash_generation_client.lib b/breakpad/v120/lib64/crash_generation_client.lib deleted file mode 100644 index ecc4820a2..000000000 Binary files a/breakpad/v120/lib64/crash_generation_client.lib and /dev/null differ diff --git a/breakpad/v120/lib64/crash_generation_server.lib b/breakpad/v120/lib64/crash_generation_server.lib deleted file mode 100644 index 864024a11..000000000 Binary files a/breakpad/v120/lib64/crash_generation_server.lib and /dev/null differ diff --git a/breakpad/v120/lib64/exception_handler.lib b/breakpad/v120/lib64/exception_handler.lib deleted file mode 100644 index 30d8a5d6a..000000000 Binary files a/breakpad/v120/lib64/exception_handler.lib and /dev/null differ diff --git a/renderdoc.sln b/renderdoc.sln index 15424dd20..99fd45fe3 100644 --- a/renderdoc.sln +++ b/renderdoc.sln @@ -3,7 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "renderdoc", "renderdoc\renderdoc.vcxproj", "{E2B46D67-90E2-40B6-9597-72930E7845E5}" ProjectSection(ProjectDependencies) = postProject + {7893E300-3ED0-7F4C-158F-67EA63934C57} = {7893E300-3ED0-7F4C-158F-67EA63934C57} + {EC847717-119A-2391-0477-212E1140082C} = {EC847717-119A-2391-0477-212E1140082C} + {B7399F39-300F-450E-F471-9490F959D2A7} = {B7399F39-300F-450E-F471-9490F959D2A7} {6CCB39BA-AB6B-4589-B7C4-9DA879571713} = {6CCB39BA-AB6B-4589-B7C4-9DA879571713} + {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7} = {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "renderdocui", "renderdocui\renderdocui.csproj", "{5504BAC8-287E-4083-A57F-5EE172EDDAEB}" @@ -22,11 +26,25 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{89059266-9C4E- EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "renderdoccmd", "renderdoccmd\renderdoccmd.vcxproj", "{D03DF2F9-513C-4084-BBDD-1DEE8D9250D7}" ProjectSection(ProjectDependencies) = postProject + {7893E300-3ED0-7F4C-158F-67EA63934C57} = {7893E300-3ED0-7F4C-158F-67EA63934C57} + {EC847717-119A-2391-0477-212E1140082C} = {EC847717-119A-2391-0477-212E1140082C} + {B7399F39-300F-450E-F471-9490F959D2A7} = {B7399F39-300F-450E-F471-9490F959D2A7} {E2B46D67-90E2-40B6-9597-72930E7845E5} = {E2B46D67-90E2-40B6-9597-72930E7845E5} + {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7} = {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7} EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utility", "Utility", "{B5A783D9-AEB9-420D-8E77-D4D930F8D88C}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "breakpad", "breakpad", "{9B86ABCF-0A48-41CE-B109-FFA08D80F345}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "breakpad_common", "renderdoc\3rdparty\breakpad\client\windows\common.vcxproj", "{EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_generation_client", "renderdoc\3rdparty\breakpad\client\windows\crash_generation\crash_generation_client.vcxproj", "{EC847717-119A-2391-0477-212E1140082C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_generation_server", "renderdoc\3rdparty\breakpad\client\windows\crash_generation\crash_generation_server.vcxproj", "{7893E300-3ED0-7F4C-158F-67EA63934C57}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exception_handler", "renderdoc\3rdparty\breakpad\client\windows\handler\exception_handler.vcxproj", "{B7399F39-300F-450E-F471-9490F959D2A7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Profile|Win32 = Profile|Win32 @@ -75,15 +93,44 @@ Global {D03DF2F9-513C-4084-BBDD-1DEE8D9250D7}.Release|Win32.Build.0 = Release|Win32 {D03DF2F9-513C-4084-BBDD-1DEE8D9250D7}.Release|x64.ActiveCfg = Release|x64 {D03DF2F9-513C-4084-BBDD-1DEE8D9250D7}.Release|x64.Build.0 = Release|x64 + {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Profile|Win32.ActiveCfg = Profile|Win32 + {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Profile|x64.ActiveCfg = Profile|x64 + {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Release|Win32.ActiveCfg = Release|Win32 + {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Release|Win32.Build.0 = Release|Win32 + {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Release|x64.ActiveCfg = Release|x64 + {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7}.Release|x64.Build.0 = Release|x64 + {EC847717-119A-2391-0477-212E1140082C}.Profile|Win32.ActiveCfg = Profile|Win32 + {EC847717-119A-2391-0477-212E1140082C}.Profile|x64.ActiveCfg = Profile|x64 + {EC847717-119A-2391-0477-212E1140082C}.Release|Win32.ActiveCfg = Release|Win32 + {EC847717-119A-2391-0477-212E1140082C}.Release|Win32.Build.0 = Release|Win32 + {EC847717-119A-2391-0477-212E1140082C}.Release|x64.ActiveCfg = Release|x64 + {EC847717-119A-2391-0477-212E1140082C}.Release|x64.Build.0 = Release|x64 + {7893E300-3ED0-7F4C-158F-67EA63934C57}.Profile|Win32.ActiveCfg = Profile|Win32 + {7893E300-3ED0-7F4C-158F-67EA63934C57}.Profile|x64.ActiveCfg = Profile|x64 + {7893E300-3ED0-7F4C-158F-67EA63934C57}.Release|Win32.ActiveCfg = Release|Win32 + {7893E300-3ED0-7F4C-158F-67EA63934C57}.Release|Win32.Build.0 = Release|Win32 + {7893E300-3ED0-7F4C-158F-67EA63934C57}.Release|x64.ActiveCfg = Release|x64 + {7893E300-3ED0-7F4C-158F-67EA63934C57}.Release|x64.Build.0 = Release|x64 + {B7399F39-300F-450E-F471-9490F959D2A7}.Profile|Win32.ActiveCfg = Profile|Win32 + {B7399F39-300F-450E-F471-9490F959D2A7}.Profile|x64.ActiveCfg = Profile|x64 + {B7399F39-300F-450E-F471-9490F959D2A7}.Release|Win32.ActiveCfg = Release|Win32 + {B7399F39-300F-450E-F471-9490F959D2A7}.Release|Win32.Build.0 = Release|Win32 + {B7399F39-300F-450E-F471-9490F959D2A7}.Release|x64.ActiveCfg = Release|x64 + {B7399F39-300F-450E-F471-9490F959D2A7}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {E2B46D67-90E2-40B6-9597-72930E7845E5} = {B1FB29A4-9C48-4D47-BAEF-CF14CB2A40A3} + {9B86ABCF-0A48-41CE-B109-FFA08D80F345} = {B1FB29A4-9C48-4D47-BAEF-CF14CB2A40A3} {C75532C4-765B-418E-B09B-46D36B2ABDB1} = {89059266-9C4E-4637-AB1D-BFF1DC15096B} {5504BAC8-287E-4083-A57F-5EE172EDDAEB} = {89059266-9C4E-4637-AB1D-BFF1DC15096B} {D03DF2F9-513C-4084-BBDD-1DEE8D9250D7} = {B5A783D9-AEB9-420D-8E77-D4D930F8D88C} {6CCB39BA-AB6B-4589-B7C4-9DA879571713} = {B5A783D9-AEB9-420D-8E77-D4D930F8D88C} + {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7} = {9B86ABCF-0A48-41CE-B109-FFA08D80F345} + {EC847717-119A-2391-0477-212E1140082C} = {9B86ABCF-0A48-41CE-B109-FFA08D80F345} + {7893E300-3ED0-7F4C-158F-67EA63934C57} = {9B86ABCF-0A48-41CE-B109-FFA08D80F345} + {B7399F39-300F-450E-F471-9490F959D2A7} = {9B86ABCF-0A48-41CE-B109-FFA08D80F345} EndGlobalSection EndGlobal diff --git a/breakpad/LICENSE b/renderdoc/3rdparty/breakpad/LICENSE similarity index 100% rename from breakpad/LICENSE rename to renderdoc/3rdparty/breakpad/LICENSE diff --git a/breakpad/README b/renderdoc/3rdparty/breakpad/README similarity index 88% rename from breakpad/README rename to renderdoc/3rdparty/breakpad/README index 3bccd4be8..14f28b2fe 100644 --- a/breakpad/README +++ b/renderdoc/3rdparty/breakpad/README @@ -1,6 +1,9 @@ Breakpad is a set of client and server components which implement a crash-reporting system. +** NOTE - this folder is a stripped down local version to be loaded +** from within renderdoc. For the full source go to the original +** repository, http://code.google.com/p/google-breakpad/ ----- Getting started in 32-bit mode (from trunk) diff --git a/breakpad/client/windows/common.vcxproj b/renderdoc/3rdparty/breakpad/client/windows/common.vcxproj similarity index 65% rename from breakpad/client/windows/common.vcxproj rename to renderdoc/3rdparty/breakpad/client/windows/common.vcxproj index 63d551dc9..7dc0e474b 100644 --- a/breakpad/client/windows/common.vcxproj +++ b/renderdoc/3rdparty/breakpad/client/windows/common.vcxproj @@ -1,20 +1,12 @@  - - Debug + + Profile Win32 - - Debug - x64 - - - Purify - Win32 - - - Purify + + Profile x64 @@ -45,20 +37,18 @@ $(ExecutablePath);$(MSBuildProjectDirectory)\..\..\third_party\cygwin\bin\;$(MSBuildProjectDirectory)\..\..\third_party\python_26\ - $(SolutionDir)$(Configuration)\$(Platform)\ - $(OutDir)obj\$(ProjectName)\ - false - false + $(SolutionDir)renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\ + $(SolutionDir)renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\$(ProjectName)\ false false - true - true + true + true $(ProjectName) $(OutDir)\$(ProjectName).lib - + - ..\..;..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) EnableFastChecks true @@ -106,9 +96,9 @@ _DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) - + - ..\..;..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) EnableFastChecks true @@ -156,108 +146,9 @@ _DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;%(PreprocessorDefinitions) - - - ..\..;..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - /MP %(AdditionalOptions) - true - ProgramDatabase - 4100;4127;4396;4503;4512;4819;4995;4800;%(DisableSpecificWarnings) - false - true - false - MaxSpeed - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions) - MultiThreaded - false - true - Level4 - - - ../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories) - /ignore:4221 %(AdditionalOptions) - $(OutDir)\$(ProjectName).lib - - - wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;%(AdditionalDependencies) - ../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories) - /safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions) - dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs) - false - true - $(OutDir)\$(TargetName).lib - $(OutDir)$(TargetName).map - Console - MachineX86 - - - dlldata.c - true - %(Filename).h - %(Filename)_i.c - $(IntDir) - %(Filename)_p.c - %(Filename).tlb - - - ../..;..\..;..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - 0x0409 - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - - - - - ..\..;..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - /MP %(AdditionalOptions) - false - ProgramDatabase - 4100;4127;4396;4503;4512;4819;4995;4800;%(DisableSpecificWarnings) - false - true - false - Disabled - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions) - MultiThreaded - false - true - Level4 - - - ../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories) - /ignore:4221 %(AdditionalOptions) - $(OutDir)\$(ProjectName).lib - - - wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;%(AdditionalDependencies) - ../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories) - /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions) - dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs) - false - false - true - $(OutDir)\$(TargetName).lib - $(OutDir)$(TargetName).map - Console - MachineX64 - - - dlldata.c - true - %(Filename).h - %(Filename)_i.c - $(IntDir) - %(Filename)_p.c - %(Filename).tlb - - - ../..;..\..;..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - 0x0409 - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - - - ..\..;..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) true @@ -309,13 +200,13 @@ _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - mkdir $(SolutionDir)\$(PlatformToolset)\lib32\ 2> nul -copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib32\ + + - ..\..;..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) true @@ -363,16 +254,32 @@ copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib32\ _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - mkdir $(SolutionDir)\$(PlatformToolset)\lib64\ 2> nul -copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib64\ + + + + + $(SolutionDir)3rdparty\ + + + + + $(SolutionDir)3rdparty\ + + - - - + + + + + + + + + diff --git a/renderdoc/3rdparty/breakpad/client/windows/common.vcxproj.filters b/renderdoc/3rdparty/breakpad/client/windows/common.vcxproj.filters new file mode 100644 index 000000000..24031ab1a --- /dev/null +++ b/renderdoc/3rdparty/breakpad/client/windows/common.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + + + + + + + + + Common includes + + + Common includes + + + Common includes + + + Common includes + + + Common includes + + + Common includes + + + Common includes + + + Common includes + + + + + {0ee0db1a-3e13-4e79-8fb0-0d55d8261558} + + + \ No newline at end of file diff --git a/breakpad/client/windows/common/auto_critical_section.h b/renderdoc/3rdparty/breakpad/client/windows/common/auto_critical_section.h similarity index 100% rename from breakpad/client/windows/common/auto_critical_section.h rename to renderdoc/3rdparty/breakpad/client/windows/common/auto_critical_section.h diff --git a/breakpad/client/windows/common/ipc_protocol.h b/renderdoc/3rdparty/breakpad/client/windows/common/ipc_protocol.h similarity index 98% rename from breakpad/client/windows/common/ipc_protocol.h rename to renderdoc/3rdparty/breakpad/client/windows/common/ipc_protocol.h index a9239ec20..d9391095b 100644 --- a/breakpad/client/windows/common/ipc_protocol.h +++ b/renderdoc/3rdparty/breakpad/client/windows/common/ipc_protocol.h @@ -34,8 +34,8 @@ #include #include #include -#include "common/windows/string_utils-inl.h" -#include "google_breakpad/common/minidump_format.h" +#include "breakpad/common/windows/string_utils-inl.h" +#include "breakpad/google_breakpad/common/minidump_format.h" namespace google_breakpad { diff --git a/breakpad/client/windows/crash_generation/ReadMe.txt b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/ReadMe.txt similarity index 100% rename from breakpad/client/windows/crash_generation/ReadMe.txt rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/ReadMe.txt diff --git a/breakpad/client/windows/crash_generation/client_info.cc b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/client_info.cc similarity index 98% rename from breakpad/client/windows/crash_generation/client_info.cc rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/client_info.cc index 3a1a96262..0630c4e35 100644 --- a/breakpad/client/windows/crash_generation/client_info.cc +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/client_info.cc @@ -27,8 +27,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "client/windows/crash_generation/client_info.h" -#include "client/windows/common/ipc_protocol.h" +#include "breakpad/client/windows/crash_generation/client_info.h" +#include "breakpad/client/windows/common/ipc_protocol.h" static const wchar_t kCustomInfoProcessUptimeName[] = L"ptime"; static const size_t kMaxCustomInfoEntries = 4096; diff --git a/breakpad/client/windows/crash_generation/client_info.h b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/client_info.h similarity index 97% rename from breakpad/client/windows/crash_generation/client_info.h rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/client_info.h index d807e9adf..fc9db7d99 100644 --- a/breakpad/client/windows/crash_generation/client_info.h +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/client_info.h @@ -32,9 +32,9 @@ #include #include -#include "client/windows/common/ipc_protocol.h" -#include "common/scoped_ptr.h" -#include "google_breakpad/common/minidump_format.h" +#include "breakpad/client/windows/common/ipc_protocol.h" +#include "breakpad/common/scoped_ptr.h" +#include "breakpad/google_breakpad/common/minidump_format.h" namespace google_breakpad { diff --git a/breakpad/client/windows/crash_generation/crash_generation.sln b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation.sln similarity index 100% rename from breakpad/client/windows/crash_generation/crash_generation.sln rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation.sln diff --git a/breakpad/client/windows/crash_generation/crash_generation_client.cc b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.cc similarity index 98% rename from breakpad/client/windows/crash_generation/crash_generation_client.cc rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.cc index f88216aba..49d0dcbbb 100644 --- a/breakpad/client/windows/crash_generation/crash_generation_client.cc +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.cc @@ -27,10 +27,10 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "client/windows/crash_generation/crash_generation_client.h" +#include "breakpad/client/windows/crash_generation/crash_generation_client.h" #include #include -#include "client/windows/common/ipc_protocol.h" +#include "breakpad/client/windows/common/ipc_protocol.h" namespace google_breakpad { diff --git a/breakpad/client/windows/crash_generation/crash_generation_client.h b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.h similarity index 98% rename from breakpad/client/windows/crash_generation/crash_generation_client.h rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.h index ce9ec0919..bb47652f3 100644 --- a/breakpad/client/windows/crash_generation/crash_generation_client.h +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.h @@ -35,8 +35,8 @@ #include #include #include -#include "client/windows/common/ipc_protocol.h" -#include "common/scoped_ptr.h" +#include "breakpad/client/windows/common/ipc_protocol.h" +#include "breakpad/common/scoped_ptr.h" namespace google_breakpad { diff --git a/breakpad/client/windows/crash_generation/crash_generation_client.vcxproj b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.vcxproj similarity index 64% rename from breakpad/client/windows/crash_generation/crash_generation_client.vcxproj rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.vcxproj index 75994b72f..92039bb40 100644 --- a/breakpad/client/windows/crash_generation/crash_generation_client.vcxproj +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.vcxproj @@ -1,20 +1,12 @@  - - Debug + + Profile Win32 - - Debug - x64 - - - Purify - Win32 - - - Purify + + Profile x64 @@ -44,20 +36,18 @@ $(ExecutablePath);$(MSBuildProjectDirectory)\..\..\..\third_party\cygwin\bin\;$(MSBuildProjectDirectory)\..\..\..\third_party\python_26\ - $(SolutionDir)$(Configuration)\$(Platform)\ - $(OutDir)obj\$(ProjectName)\ - false - false + $(SolutionDir)renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\ + $(SolutionDir)renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\$(ProjectName)\ false false - true - true + true + true $(ProjectName) $(OutDir)\$(ProjectName).lib - + - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) EnableFastChecks true @@ -105,9 +95,9 @@ _DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) - + - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) EnableFastChecks true @@ -155,108 +145,9 @@ _DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;%(PreprocessorDefinitions) - - - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - /MP %(AdditionalOptions) - true - ProgramDatabase - 4100;4127;4396;4503;4512;4819;4995;4800;%(DisableSpecificWarnings) - false - true - false - MaxSpeed - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions) - MultiThreaded - false - true - Level4 - - - ../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories) - /ignore:4221 %(AdditionalOptions) - $(OutDir)lib\$(ProjectName).lib - - - wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;%(AdditionalDependencies) - ../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories) - /safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions) - dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs) - false - true - $(OutDir)lib\$(TargetName).lib - $(OutDir)$(TargetName).map - Console - MachineX86 - - - dlldata.c - true - %(Filename).h - %(Filename)_i.c - $(IntDir) - %(Filename)_p.c - %(Filename).tlb - - - ../../..;..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - 0x0409 - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - - - - - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - /MP %(AdditionalOptions) - false - ProgramDatabase - 4100;4127;4396;4503;4512;4819;4995;4800;%(DisableSpecificWarnings) - false - true - false - Disabled - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions) - MultiThreaded - false - true - Level4 - - - ../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories) - /ignore:4221 %(AdditionalOptions) - $(OutDir)lib\$(ProjectName).lib - - - wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;%(AdditionalDependencies) - ../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories) - /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions) - dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs) - false - false - true - $(OutDir)lib\$(TargetName).lib - $(OutDir)$(TargetName).map - Console - MachineX64 - - - dlldata.c - true - %(Filename).h - %(Filename)_i.c - $(IntDir) - %(Filename)_p.c - %(Filename).tlb - - - ../../..;..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - 0x0409 - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - - - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) true @@ -308,13 +199,13 @@ _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - mkdir $(SolutionDir)\$(PlatformToolset)\lib32\ 2> nul -copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib32\ + + - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) true @@ -362,16 +253,22 @@ copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib32\ _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - mkdir $(SolutionDir)\$(PlatformToolset)\lib64\ 2> nul -copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib64\ + + - - - + + + $(SolutionDir)3rdparty\ + + + + + $(SolutionDir)3rdparty\ + + - diff --git a/breakpad/client/windows/crash_generation/crash_generation_client.vcxproj.filters b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.vcxproj.filters similarity index 70% rename from breakpad/client/windows/crash_generation/crash_generation_client.vcxproj.filters rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.vcxproj.filters index 89584cb2b..c1f192455 100644 --- a/breakpad/client/windows/crash_generation/crash_generation_client.vcxproj.filters +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_client.vcxproj.filters @@ -5,9 +5,5 @@ - - - - \ No newline at end of file diff --git a/breakpad/client/windows/crash_generation/crash_generation_server.cc b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.cc similarity index 99% rename from breakpad/client/windows/crash_generation/crash_generation_server.cc rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.cc index 016158883..2a89834dd 100644 --- a/breakpad/client/windows/crash_generation/crash_generation_server.cc +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.cc @@ -27,14 +27,14 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "client/windows/crash_generation/crash_generation_server.h" +#include "breakpad/client/windows/crash_generation/crash_generation_server.h" #include #include #include -#include "client/windows/common/auto_critical_section.h" -#include "common/scoped_ptr.h" +#include "breakpad/client/windows/common/auto_critical_section.h" +#include "breakpad/common/scoped_ptr.h" -#include "client/windows/crash_generation/client_info.h" +#include "breakpad/client/windows/crash_generation/client_info.h" namespace google_breakpad { diff --git a/breakpad/client/windows/crash_generation/crash_generation_server.h b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.h similarity index 98% rename from breakpad/client/windows/crash_generation/crash_generation_server.h rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.h index 070198582..1f8a2cbcd 100644 --- a/breakpad/client/windows/crash_generation/crash_generation_server.h +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.h @@ -32,9 +32,9 @@ #include #include -#include "client/windows/common/ipc_protocol.h" -#include "client/windows/crash_generation/minidump_generator.h" -#include "common/scoped_ptr.h" +#include "breakpad/client/windows/common/ipc_protocol.h" +#include "breakpad/client/windows/crash_generation/minidump_generator.h" +#include "breakpad/common/scoped_ptr.h" namespace google_breakpad { class ClientInfo; diff --git a/breakpad/client/windows/crash_generation/crash_generation_server.vcxproj b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.vcxproj similarity index 64% rename from breakpad/client/windows/crash_generation/crash_generation_server.vcxproj rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.vcxproj index a661dbb0f..0530a38a0 100644 --- a/breakpad/client/windows/crash_generation/crash_generation_server.vcxproj +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.vcxproj @@ -1,20 +1,12 @@  - - Debug + + Profile Win32 - - Debug - x64 - - - Purify - Win32 - - - Purify + + Profile x64 @@ -44,20 +36,18 @@ $(ExecutablePath);$(MSBuildProjectDirectory)\..\..\..\third_party\cygwin\bin\;$(MSBuildProjectDirectory)\..\..\..\third_party\python_26\ - $(SolutionDir)$(Configuration)\$(Platform)\ - $(OutDir)obj\$(ProjectName)\ - false - false + $(SolutionDir)renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\ + $(SolutionDir)renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\$(ProjectName)\ false false - true - true + true + true $(ProjectName) $(OutDir)\$(ProjectName).lib - + - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) EnableFastChecks true @@ -105,9 +95,9 @@ _DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) - + - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) EnableFastChecks true @@ -155,108 +145,9 @@ _DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;%(PreprocessorDefinitions) - - - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - /MP %(AdditionalOptions) - true - ProgramDatabase - 4100;4127;4396;4503;4512;4819;4995;4800;%(DisableSpecificWarnings) - false - true - false - MaxSpeed - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions) - MultiThreaded - false - true - Level4 - - - ../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories) - /ignore:4221 %(AdditionalOptions) - $(OutDir)\$(ProjectName).lib - - - wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;%(AdditionalDependencies) - ../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories) - /safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions) - dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs) - false - true - $(OutDir)lib\$(TargetName).lib - $(OutDir)$(TargetName).map - Console - MachineX86 - - - dlldata.c - true - %(Filename).h - %(Filename)_i.c - $(IntDir) - %(Filename)_p.c - %(Filename).tlb - - - ../../..;..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - 0x0409 - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - - - - - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - /MP %(AdditionalOptions) - false - ProgramDatabase - 4100;4127;4396;4503;4512;4819;4995;4800;%(DisableSpecificWarnings) - false - true - false - Disabled - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions) - MultiThreaded - false - true - Level4 - - - ../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories) - /ignore:4221 %(AdditionalOptions) - $(OutDir)\$(ProjectName).lib - - - wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;%(AdditionalDependencies) - ../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories) - /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions) - dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs) - false - false - true - $(OutDir)lib\$(TargetName).lib - $(OutDir)$(TargetName).map - Console - MachineX64 - - - dlldata.c - true - %(Filename).h - %(Filename)_i.c - $(IntDir) - %(Filename)_p.c - %(Filename).tlb - - - ../../..;..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - 0x0409 - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - - - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) true @@ -308,13 +199,13 @@ _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - mkdir $(SolutionDir)\$(PlatformToolset)\lib32\ 2> nul -copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib32\ + + - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) true @@ -362,16 +253,22 @@ copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib32\ _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - mkdir $(SolutionDir)\$(PlatformToolset)\lib64\ 2> nul -copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib64\ + + - - - + + + $(SolutionDir)3rdparty\ + + + + + $(SolutionDir)3rdparty\ + + - diff --git a/breakpad/client/windows/crash_generation/crash_generation_server.vcxproj.filters b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.vcxproj.filters similarity index 79% rename from breakpad/client/windows/crash_generation/crash_generation_server.vcxproj.filters rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.vcxproj.filters index 84f57a469..58f3b5dc0 100644 --- a/breakpad/client/windows/crash_generation/crash_generation_server.vcxproj.filters +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/crash_generation_server.vcxproj.filters @@ -7,11 +7,7 @@ - - - - \ No newline at end of file diff --git a/breakpad/client/windows/crash_generation/minidump_generator.cc b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/minidump_generator.cc similarity index 99% rename from breakpad/client/windows/crash_generation/minidump_generator.cc rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/minidump_generator.cc index dd5515a46..b343bef92 100644 --- a/breakpad/client/windows/crash_generation/minidump_generator.cc +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/minidump_generator.cc @@ -27,7 +27,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "client/windows/crash_generation/minidump_generator.h" +#include "breakpad/client/windows/crash_generation/minidump_generator.h" #include #include @@ -37,8 +37,8 @@ #include #include -#include "client/windows/common/auto_critical_section.h" -#include "common/windows/guid_string.h" +#include "breakpad/client/windows/common/auto_critical_section.h" +#include "breakpad/common/windows/guid_string.h" using std::wstring; diff --git a/breakpad/client/windows/crash_generation/minidump_generator.h b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/minidump_generator.h similarity index 98% rename from breakpad/client/windows/crash_generation/minidump_generator.h rename to renderdoc/3rdparty/breakpad/client/windows/crash_generation/minidump_generator.h index 034772687..f182e30d5 100644 --- a/breakpad/client/windows/crash_generation/minidump_generator.h +++ b/renderdoc/3rdparty/breakpad/client/windows/crash_generation/minidump_generator.h @@ -34,8 +34,8 @@ #include #include #include -#include "google_breakpad/common/minidump_format.h" -#include "client/windows/common/ipc_protocol.h" +#include "breakpad/google_breakpad/common/minidump_format.h" +#include "breakpad/client/windows/common/ipc_protocol.h" namespace google_breakpad { diff --git a/breakpad/client/windows/handler/exception_handler.cc b/renderdoc/3rdparty/breakpad/client/windows/handler/exception_handler.cc similarity index 99% rename from breakpad/client/windows/handler/exception_handler.cc rename to renderdoc/3rdparty/breakpad/client/windows/handler/exception_handler.cc index 10d781289..6d72d87fd 100644 --- a/breakpad/client/windows/handler/exception_handler.cc +++ b/renderdoc/3rdparty/breakpad/client/windows/handler/exception_handler.cc @@ -33,11 +33,11 @@ #include #include -#include "common/windows/string_utils-inl.h" +#include "breakpad/common/windows/string_utils-inl.h" -#include "client/windows/common/ipc_protocol.h" -#include "client/windows/handler/exception_handler.h" -#include "common/windows/guid_string.h" +#include "breakpad/client/windows/common/ipc_protocol.h" +#include "breakpad/client/windows/handler/exception_handler.h" +#include "breakpad/common/windows/guid_string.h" namespace google_breakpad { diff --git a/breakpad/client/windows/handler/exception_handler.h b/renderdoc/3rdparty/breakpad/client/windows/handler/exception_handler.h similarity index 98% rename from breakpad/client/windows/handler/exception_handler.h rename to renderdoc/3rdparty/breakpad/client/windows/handler/exception_handler.h index 6ca40d4f5..4d9c8ad16 100644 --- a/breakpad/client/windows/handler/exception_handler.h +++ b/renderdoc/3rdparty/breakpad/client/windows/handler/exception_handler.h @@ -69,10 +69,10 @@ #include #include -#include "client/windows/common/ipc_protocol.h" -#include "client/windows/crash_generation/crash_generation_client.h" -#include "common/scoped_ptr.h" -#include "google_breakpad/common/minidump_format.h" +#include "breakpad/client/windows/common/ipc_protocol.h" +#include "breakpad/client/windows/crash_generation/crash_generation_client.h" +#include "breakpad/common/scoped_ptr.h" +#include "breakpad/google_breakpad/common/minidump_format.h" namespace google_breakpad { diff --git a/breakpad/client/windows/handler/exception_handler.sln b/renderdoc/3rdparty/breakpad/client/windows/handler/exception_handler.sln similarity index 100% rename from breakpad/client/windows/handler/exception_handler.sln rename to renderdoc/3rdparty/breakpad/client/windows/handler/exception_handler.sln diff --git a/breakpad/client/windows/handler/exception_handler.vcxproj b/renderdoc/3rdparty/breakpad/client/windows/handler/exception_handler.vcxproj similarity index 64% rename from breakpad/client/windows/handler/exception_handler.vcxproj rename to renderdoc/3rdparty/breakpad/client/windows/handler/exception_handler.vcxproj index f4f494fa9..a763541da 100644 --- a/breakpad/client/windows/handler/exception_handler.vcxproj +++ b/renderdoc/3rdparty/breakpad/client/windows/handler/exception_handler.vcxproj @@ -1,20 +1,12 @@  - - Debug + + Profile Win32 - - Debug - x64 - - - Purify - Win32 - - - Purify + + Profile x64 @@ -44,20 +36,18 @@ $(ExecutablePath);$(MSBuildProjectDirectory)\..\..\..\third_party\cygwin\bin\;$(MSBuildProjectDirectory)\..\..\..\third_party\python_26\ - $(SolutionDir)$(Configuration)\$(Platform)\ - $(OutDir)obj\$(ProjectName)\ - false - false + $(SolutionDir)renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\ + $(SolutionDir)renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\$(ProjectName)\ false false - true - true + true + true $(ProjectName) $(OutDir)\$(ProjectName).lib - + - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) EnableFastChecks true @@ -105,9 +95,9 @@ _DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) - + - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) EnableFastChecks true @@ -155,108 +145,9 @@ _DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;%(PreprocessorDefinitions) - - - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - /MP %(AdditionalOptions) - true - ProgramDatabase - 4100;4127;4396;4503;4512;4819;4995;4800;%(DisableSpecificWarnings) - false - true - false - MaxSpeed - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions) - MultiThreaded - false - true - Level4 - - - ../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories) - /ignore:4221 %(AdditionalOptions) - $(OutDir)\$(ProjectName).lib - - - wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;%(AdditionalDependencies) - ../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories) - /safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions) - dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs) - false - true - $(OutDir)lib\$(TargetName).lib - $(OutDir)$(TargetName).map - Console - MachineX86 - - - dlldata.c - true - %(Filename).h - %(Filename)_i.c - $(IntDir) - %(Filename)_p.c - %(Filename).tlb - - - ../../..;..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - 0x0409 - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - - - - - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - /MP %(AdditionalOptions) - false - ProgramDatabase - 4100;4127;4396;4503;4512;4819;4995;4800;%(DisableSpecificWarnings) - false - true - false - Disabled - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions) - MultiThreaded - false - true - Level4 - - - ../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories) - /ignore:4221 %(AdditionalOptions) - $(OutDir)\$(ProjectName).lib - - - wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;%(AdditionalDependencies) - ../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories) - /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions) - dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs) - false - false - true - $(OutDir)lib\$(TargetName).lib - $(OutDir)$(TargetName).map - Console - MachineX64 - - - dlldata.c - true - %(Filename).h - %(Filename)_i.c - $(IntDir) - %(Filename)_p.c - %(Filename).tlb - - - ../../..;..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) - 0x0409 - _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - - - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) true @@ -308,13 +199,13 @@ _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - mkdir $(SolutionDir)\$(PlatformToolset)\lib32\ 2> nul -copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib32\ + + - ..\..\..;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories) + $(SolutionDir)renderdoc\3rdparty\ /MP %(AdditionalOptions) true @@ -362,13 +253,20 @@ copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib32\ _WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - mkdir $(SolutionDir)\$(PlatformToolset)\lib64\ 2> nul -copy $(TargetPath) $(SolutionDir)\$(PlatformToolset)\lib64\ + + - - - + + + $(SolutionDir)3rdparty\ + + + + + $(SolutionDir)3rdparty\ + + diff --git a/breakpad/common/scoped_ptr.h b/renderdoc/3rdparty/breakpad/common/scoped_ptr.h similarity index 100% rename from breakpad/common/scoped_ptr.h rename to renderdoc/3rdparty/breakpad/common/scoped_ptr.h diff --git a/breakpad/common/windows/guid_string.cc b/renderdoc/3rdparty/breakpad/common/windows/guid_string.cc similarity index 96% rename from breakpad/common/windows/guid_string.cc rename to renderdoc/3rdparty/breakpad/common/windows/guid_string.cc index b7f877e66..561ac8a57 100644 --- a/breakpad/common/windows/guid_string.cc +++ b/renderdoc/3rdparty/breakpad/common/windows/guid_string.cc @@ -33,9 +33,9 @@ #include -#include "common/windows/string_utils-inl.h" +#include "breakpad/common/windows/string_utils-inl.h" -#include "common/windows/guid_string.h" +#include "breakpad/common/windows/guid_string.h" namespace google_breakpad { diff --git a/breakpad/common/windows/guid_string.h b/renderdoc/3rdparty/breakpad/common/windows/guid_string.h similarity index 100% rename from breakpad/common/windows/guid_string.h rename to renderdoc/3rdparty/breakpad/common/windows/guid_string.h diff --git a/breakpad/common/windows/http_upload.cc b/renderdoc/3rdparty/breakpad/common/windows/http_upload.cc similarity index 99% rename from breakpad/common/windows/http_upload.cc rename to renderdoc/3rdparty/breakpad/common/windows/http_upload.cc index 838185b75..e6fed65e3 100644 --- a/breakpad/common/windows/http_upload.cc +++ b/renderdoc/3rdparty/breakpad/common/windows/http_upload.cc @@ -34,9 +34,9 @@ #include -#include "common/windows/string_utils-inl.h" +#include "breakpad/common/windows/string_utils-inl.h" -#include "common/windows/http_upload.h" +#include "breakpad/common/windows/http_upload.h" namespace google_breakpad { diff --git a/breakpad/common/windows/http_upload.h b/renderdoc/3rdparty/breakpad/common/windows/http_upload.h similarity index 100% rename from breakpad/common/windows/http_upload.h rename to renderdoc/3rdparty/breakpad/common/windows/http_upload.h diff --git a/breakpad/common/windows/string_utils-inl.h b/renderdoc/3rdparty/breakpad/common/windows/string_utils-inl.h similarity index 100% rename from breakpad/common/windows/string_utils-inl.h rename to renderdoc/3rdparty/breakpad/common/windows/string_utils-inl.h diff --git a/breakpad/common/windows/string_utils.cc b/renderdoc/3rdparty/breakpad/common/windows/string_utils.cc similarity index 98% rename from breakpad/common/windows/string_utils.cc rename to renderdoc/3rdparty/breakpad/common/windows/string_utils.cc index e6ffa0823..ea4d30f91 100644 --- a/breakpad/common/windows/string_utils.cc +++ b/renderdoc/3rdparty/breakpad/common/windows/string_utils.cc @@ -30,7 +30,7 @@ #include #include -#include "common/windows/string_utils-inl.h" +#include "breakpad/common/windows/string_utils-inl.h" namespace google_breakpad { diff --git a/breakpad/dump_syms.exe b/renderdoc/3rdparty/breakpad/dump_syms.exe similarity index 100% rename from breakpad/dump_syms.exe rename to renderdoc/3rdparty/breakpad/dump_syms.exe diff --git a/breakpad/getmssym.sh b/renderdoc/3rdparty/breakpad/getmssym.sh similarity index 100% rename from breakpad/getmssym.sh rename to renderdoc/3rdparty/breakpad/getmssym.sh diff --git a/breakpad/google_breakpad/common/breakpad_types.h b/renderdoc/3rdparty/breakpad/google_breakpad/common/breakpad_types.h similarity index 100% rename from breakpad/google_breakpad/common/breakpad_types.h rename to renderdoc/3rdparty/breakpad/google_breakpad/common/breakpad_types.h diff --git a/breakpad/google_breakpad/common/minidump_cpu_amd64.h b/renderdoc/3rdparty/breakpad/google_breakpad/common/minidump_cpu_amd64.h similarity index 100% rename from breakpad/google_breakpad/common/minidump_cpu_amd64.h rename to renderdoc/3rdparty/breakpad/google_breakpad/common/minidump_cpu_amd64.h diff --git a/breakpad/google_breakpad/common/minidump_cpu_x86.h b/renderdoc/3rdparty/breakpad/google_breakpad/common/minidump_cpu_x86.h similarity index 100% rename from breakpad/google_breakpad/common/minidump_cpu_x86.h rename to renderdoc/3rdparty/breakpad/google_breakpad/common/minidump_cpu_x86.h diff --git a/breakpad/google_breakpad/common/minidump_exception_win32.h b/renderdoc/3rdparty/breakpad/google_breakpad/common/minidump_exception_win32.h similarity index 98% rename from breakpad/google_breakpad/common/minidump_exception_win32.h rename to renderdoc/3rdparty/breakpad/google_breakpad/common/minidump_exception_win32.h index 458a70543..603eb06c6 100644 --- a/breakpad/google_breakpad/common/minidump_exception_win32.h +++ b/renderdoc/3rdparty/breakpad/google_breakpad/common/minidump_exception_win32.h @@ -41,7 +41,7 @@ #include -#include "google_breakpad/common/breakpad_types.h" +#include "breakpad/google_breakpad/common/breakpad_types.h" /* For (MDException).exception_code. These values come from WinBase.h diff --git a/breakpad/google_breakpad/common/minidump_format.h b/renderdoc/3rdparty/breakpad/google_breakpad/common/minidump_format.h similarity index 99% rename from breakpad/google_breakpad/common/minidump_format.h rename to renderdoc/3rdparty/breakpad/google_breakpad/common/minidump_format.h index 90e5ba5b6..8ce2d08e8 100644 --- a/breakpad/google_breakpad/common/minidump_format.h +++ b/renderdoc/3rdparty/breakpad/google_breakpad/common/minidump_format.h @@ -63,7 +63,7 @@ #include -#include "google_breakpad/common/breakpad_types.h" +#include "breakpad/google_breakpad/common/breakpad_types.h" #if defined(_MSC_VER) @@ -114,10 +114,10 @@ typedef struct { } MDRawContextBase; #include "minidump_cpu_amd64.h" -#include "minidump_cpu_arm.h" -#include "minidump_cpu_ppc.h" -#include "minidump_cpu_ppc64.h" -#include "minidump_cpu_sparc.h" +//#include "minidump_cpu_arm.h" +//#include "minidump_cpu_ppc.h" +//#include "minidump_cpu_ppc64.h" +//#include "minidump_cpu_sparc.h" #include "minidump_cpu_x86.h" /* @@ -529,10 +529,10 @@ typedef struct { uint64_t exception_information[MD_EXCEPTION_MAXIMUM_PARAMETERS]; } MDException; /* MINIDUMP_EXCEPTION */ -#include "minidump_exception_linux.h" -#include "minidump_exception_mac.h" -#include "minidump_exception_ps3.h" -#include "minidump_exception_solaris.h" +//#include "minidump_exception_linux.h" +//#include "minidump_exception_mac.h" +//#include "minidump_exception_ps3.h" +//#include "minidump_exception_solaris.h" #include "minidump_exception_win32.h" typedef struct { diff --git a/breakpad/makesym.sh b/renderdoc/3rdparty/breakpad/makesym.sh similarity index 100% rename from breakpad/makesym.sh rename to renderdoc/3rdparty/breakpad/makesym.sh diff --git a/breakpad/symup.sh b/renderdoc/3rdparty/breakpad/symup.sh similarity index 100% rename from breakpad/symup.sh rename to renderdoc/3rdparty/breakpad/symup.sh diff --git a/renderdoc/3rdparty/mhook/COPYING b/renderdoc/3rdparty/mhook/COPYING deleted file mode 100644 index a7fd4533d..000000000 --- a/renderdoc/3rdparty/mhook/COPYING +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2007-2014, Marton Anka -Portions Copyright (c) 2007, Matt Conover - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/renderdoc/3rdparty/mhook/disasm-lib/cpu.c b/renderdoc/3rdparty/mhook/disasm-lib/cpu.c deleted file mode 100644 index 2a12692ac..000000000 --- a/renderdoc/3rdparty/mhook/disasm-lib/cpu.c +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (C) 2003, Matt Conover (mconover@gmail.com) -#include "cpu.h" -#include - -// NOTE: this assumes default scenarios (i.e., we assume CS/DS/ES/SS and flat -// and all have a base of 0 and limit of 0xffffffff, we don't try to verify -// that in the GDT) -// -// TODO: use inline assembly to get selector for segment -// Segment = x86 segment register (SEG_ES = 0, SEG_CS = 1, ...) -BYTE *GetAbsoluteAddressFromSegment(BYTE Segment, DWORD Offset) -{ - switch (Segment) - { - // Windows uses a flat address space (except FS for x86 and GS for x64) - case 0: // SEG_ES - case 1: // SEG_CS - case 2: // SEG_SS - case 3: // SEG_DS - return (BYTE *)(DWORD_PTR)Offset; - case 4: // SEG_FS - case 5: // SEG_GS - return (BYTE *)(DWORD_PTR)Offset; - // Note: we're really supposed to do this, but get_teb is not implemented - // in this bastardized version of the disassembler. - // return (BYTE *)get_teb() + Offset; - default: - assert(0); - return (BYTE *)(DWORD_PTR)Offset; - } -} - -// This is an GDT/LDT selector (pGDT+Selector) -BYTE *GetAbsoluteAddressFromSelector(WORD Selector, DWORD Offset) -{ - DESCRIPTOR_ENTRY Entry; - GATE_ENTRY *Gate; - ULONG_PTR Base; - - assert(Selector < 0x10000); - if (!GetThreadSelectorEntry(GetCurrentThread(), Selector, (LDT_ENTRY *)&Entry)) return NULL; - if (!Entry.Present) return NULL; - if (Entry.System) - { - Base = 0; -#ifdef _WIN64 - Base |= (ULONG_PTR)Entry.HighOffset64 << 32; -#endif - Base |= Entry.BaseHi << 24; - Base |= Entry.BaseMid << 16; - Base |= Entry.BaseLow; - } - else - { - switch (Entry.Type) - { - case 1: // 16-bit TSS (available) - case 2: // LDT - case 3: // 16-bit TSS (busy) - case 9: // 32-bit TSS (available) - case 11: // 32-bit TSS (busy) - Base = 0; -#ifdef _WIN64 - Base |= (ULONG_PTR)Entry.HighOffset64 << 32; -#endif - Base |= Entry.BaseHi << 24; - Base |= Entry.BaseMid << 16; - Base |= Entry.BaseLow; - break; - - case 4: // 16-bit call gate - case 5: // task gate - case 6: // 16-bit interrupt gate - case 7: // 16-bit task gate - case 12: // 32-bit call gate - case 14: // 32-bit interrupt gate - case 15: // 32-bit trap gate - Gate = (GATE_ENTRY *)&Entry; -#ifdef _WIN64 - Base = ((ULONG_PTR)Gate->HighOffset64 << 32) | (Gate->HighOffset << 16) | Gate->LowOffset; -#else - Base = (Gate->HighOffset << 16) | Gate->LowOffset; -#endif - assert(!Offset); Offset = 0; - break; - default: - assert(0); - return NULL; - } - } - return (BYTE *)Base + Offset; -} - diff --git a/renderdoc/3rdparty/mhook/disasm-lib/cpu.h b/renderdoc/3rdparty/mhook/disasm-lib/cpu.h deleted file mode 100644 index dce9d3ee3..000000000 --- a/renderdoc/3rdparty/mhook/disasm-lib/cpu.h +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright (C) 2003, Matt Conover (mconover@gmail.com) -#ifndef CPU_H -#define CPU_H -#ifdef __cplusplus -extern "C" { -#endif -#pragma pack(push,1) - -#pragma warning(disable: 4214) - -#include -#include "misc.h" - -//////////////////////////////////////////////////////// -// System descriptors -//////////////////////////////////////////////////////// - -#define GDT_NULL 0 -#define GDT_R0_CODE 0x08 -#define GDT_R0_DATA 0x10 -#define GDT_R3_CODE 0x18 -#define GDT_R3_DATA 0x20 -#define GDT_TSS 0x28 -#define GDT_PCR 0x30 -#define GDT_R3_TEB 0x38 -#define GDT_VDM 0x40 -#define GDT_LDT 0x48 -#define GDT_DOUBLEFAULT_TSS 0x50 -#define GDT_NMI_TSS 0x58 - -// 16-bit GDT entries: -// TODO: #define GDT_ABIOS_UNKNOWN 0x60 (22F30-32F2F) -#define GDT_ABIOS_VIDEO 0x68 -#define GDT_ABIOS_GDT 0x70 // descriptor describing ABIOS GDT itself -#define GDT_ABIOS_NTOS 0x78 // first 64K of NTOSKRNL -#define GDT_ABIOS_CDA 0xE8 // common data area -#define GDT_ABIOS_CODE 0xF0 // KiI386AbiosCall -#define GDT_ABIOS_STACK 0xF8 - -#define SELECTOR_RPL_MASK 0x03 // bits 0-1 -#define SELECTOR_LDT 0x04 // bit 2 - -// for data selectors -#define DATA_ACCESS_MASK (1<<0) -#define DATA_WRITE_ENABLE_MASK (1<<1) -#define DATA_EXPAND_DOWN_MASK (1<<2) - -// for code selectors -#define CODE_ACCESS_MASK (1<<0) -#define CODE_READ_MASK (1<<1) -#define CODE_CONFORMING_MASK (1<<2) -#define CODE_FLAG (1<<3) - -#define TASK_GATE 5 -#define INTERRUPT_GATE 6 -#define TRAP_GATE 7 - -typedef struct _IDT_ENTRY -{ - USHORT LowOffset; - USHORT Selector; - UCHAR Ignored : 5; - UCHAR Zero : 3; - UCHAR Type : 3; - UCHAR Is32Bit : 1; - UCHAR Ignored2 : 1; - UCHAR DPL : 2; - UCHAR Present : 1; - USHORT HighOffset; -#ifdef _WIN64 - ULONG HighOffset64; - ULONG Reserved; -#endif -} IDT_ENTRY, TRAP_GATE_ENTRY; - -typedef struct _CALL_GATE_ENTRY -{ - USHORT LowOffset; - USHORT Selector; - UCHAR ParameterCount: 4; - UCHAR Ignored : 3; - UCHAR Type : 5; - UCHAR DPL : 2; - UCHAR Present : 1; - USHORT HighOffset; -#ifdef _WIN64 - ULONG HighOffset64; - ULONG Reserved; -#endif -} CALL_GATE_ENTRY; - -typedef struct _TASK_GATE_ENTRY -{ - USHORT Ignored; - USHORT Selector; - UCHAR Ignored2 : 5; - UCHAR Zero : 3; - UCHAR Type : 5; - UCHAR DPL : 2; - UCHAR Present : 1; - USHORT Ignored3; -} TASK_GATE_ENTRY; - -typedef struct _DESCRIPTOR_ENTRY -{ - USHORT LimitLow; - USHORT BaseLow; - UCHAR BaseMid; - UCHAR Type : 4; // 10EWA (code), E=ExpandDown, W=Writable, A=Accessed - // 11CRA (data), C=Conforming, R=Readable, A=Accessed - UCHAR System : 1; // if 1 then it is a gate or LDT - UCHAR DPL : 2; // descriptor privilege level; - // for data selectors, MAX(CPL, RPL) must be <= DPL to access (or else GP# fault) - // for non-conforming code selectors (without callgate), MAX(CPL, RPL) must be <= DPL to access (or else GP# fault) - // for conforming code selectors, MAX(CPL, RPL) must be >= DPL (i.e., CPL 0-2 cannot access if DPL is 3) - // for non-conforming code selectors (with call gate), DPL indicates lowest privilege allowed to access gate - UCHAR Present : 1; - UCHAR LimitHigh : 4; - UCHAR Available: 1; // aka AVL - UCHAR Reserved : 1; - UCHAR Is32Bit : 1; // aka B flag - UCHAR Granularity : 1; // aka G flag - UCHAR BaseHi : 8; -#ifdef _WIN64 - ULONG HighOffset64; - ULONG Reserved2; -#endif -} DESCRIPTOR_ENTRY; - -typedef struct _GATE_ENTRY -{ - USHORT LowOffset; - UCHAR Skip; - UCHAR Type : 5; - UCHAR DPL : 2; - UCHAR Present : 1; - USHORT HighOffset; -#ifdef _WIN64 - ULONG HighOffset64; - ULONG Reserved; -#endif -} GATE_ENTRY; - -// TODO: update for X64 -typedef struct _PTE_ENTRY -{ - ULONG Present : 1; - ULONG Write : 1; - ULONG Owner : 1; // E.g., user mode or supervisor mode - ULONG WriteThrough : 1; - ULONG CacheDisable : 1; - ULONG Accessed : 1; - ULONG Dirty : 1; - ULONG PAT : 1; - ULONG Global : 1; - ULONG CopyOnWrite : 1; - ULONG Prototype : 1; - ULONG Transition : 1; - ULONG Address : 20; -} PTE_ENTRY; - -// TODO: update for X64 -typedef struct _PDE_ENTRY -{ - ULONG Present : 1; - ULONG Write : 1; - ULONG Owner : 1; - ULONG WriteThrough : 1; - ULONG CacheDisable : 1; - ULONG Accessed : 1; - ULONG Reserved1 : 1; - ULONG PageSize : 1; - ULONG Global : 1; - ULONG Reserved : 3; - ULONG Address : 20; -} PDE_ENTRY; - -// TODO: update for X64 -typedef struct _IO_ACCESS_MAP -{ - UCHAR DirectionMap[32]; - UCHAR IoMap[8196]; -} IO_ACCESS_MAP; - -#define MIN_TSS_SIZE FIELD_OFFSET(TSS_ENTRY, IoMaps) -// TODO: update for X64 -typedef struct _TSS_ENTRY -{ - USHORT Backlink; - USHORT Reserved0; - ULONG Esp0; - USHORT Ss0; - USHORT Reserved1; - ULONG NotUsed1[4]; - ULONG CR3; - ULONG Eip; - ULONG NotUsed2[9]; - USHORT Es; - USHORT Reserved2; - USHORT Cs; - USHORT Reserved3; - USHORT Ss; - USHORT Reserved4; - USHORT Ds; - USHORT Reserved5; - USHORT Fs; - USHORT Reserved6; - USHORT Gs; - USHORT Reserved7; - USHORT LDT; - USHORT Reserved8; - USHORT Flags; - USHORT IoMapBase; - IO_ACCESS_MAP IoMaps[1]; - UCHAR IntDirectionMap[32]; -} TSS_ENTRY; - -// TODO: update for X64 -typedef struct _TSS16_ENTRY -{ - USHORT Backlink; - USHORT Sp0; - USHORT Ss0; - USHORT Sp1; - USHORT Ss1; - USHORT Sp2; - USHORT Ss3; - USHORT Ip; - USHORT Flags; - USHORT Ax; - USHORT Cx; - USHORT Dx; - USHORT Bx; - USHORT Sp; - USHORT Bp; - USHORT Si; - USHORT Di; - USHORT Es; - USHORT Cs; - USHORT Ss; - USHORT Ds; - USHORT LDT; -} TSS16_ENTRY; - -// TODO: update for X64 -typedef struct _GDT_ENTRY -{ - USHORT LimitLow; - USHORT BaseLow; - union { - struct { - UCHAR BaseMid; - UCHAR Flags1; - UCHAR Flags2; - UCHAR BaseHi; - } Bytes; - struct { - ULONG BaseMid : 8; - ULONG Type : 5; - ULONG Dpl : 2; - ULONG Pres : 1; - ULONG LimitHi : 4; - ULONG Sys : 1; - ULONG Reserved_0 : 1; - ULONG Default_Big : 1; - ULONG Granularity : 1; - ULONG BaseHi : 8; - } Bits; - } HighWord; -} GDT_ENTRY; - -BYTE *GetAbsoluteAddressFromSegment(BYTE Segment, DWORD Offset); -BYTE *GetAbsoluteAddressFromSelector(WORD Selector, DWORD Offset); - -#pragma pack(pop) -#ifdef __cplusplus -} -#endif -#endif // CPU_H \ No newline at end of file diff --git a/renderdoc/3rdparty/mhook/disasm-lib/disasm.c b/renderdoc/3rdparty/mhook/disasm-lib/disasm.c deleted file mode 100644 index 43e7766b6..000000000 --- a/renderdoc/3rdparty/mhook/disasm-lib/disasm.c +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (C) 2004, Matt Conover (mconover@gmail.com) -#undef NDEBUG -#include -#include -#include "disasm.h" - -#ifdef NO_SANITY_CHECKS -#define NDEBUG -#undef assert -#define assert(x) -#endif - -////////////////////////////////////////////////////////////////////// -// Global variables -////////////////////////////////////////////////////////////////////// - -ARCHITECTURE_FORMAT SupportedArchitectures[] = -{ - { ARCH_X86, &X86 }, - { ARCH_X86_16, &X86 }, - { ARCH_X64, &X86 }, - { ARCH_UNKNOWN, NULL } -}; - -typedef struct _DISASM_ARG_INFO -{ - INSTRUCTION *MatchedInstruction; - BOOL MatchPrefix; - U8 *Opcode; - U32 OpcodeLength; - INSTRUCTION_TYPE InstructionType; - U32 Count; -} DISASM_ARG_INFO; - -////////////////////////////////////////////////////////////////////// -// Function prototypes -////////////////////////////////////////////////////////////////////// - -BOOL InitInstruction(INSTRUCTION *Instruction, DISASSEMBLER *Disassembler); -struct _ARCHITECTURE_FORMAT *GetArchitectureFormat(ARCHITECTURE_TYPE Type); - -////////////////////////////////////////////////////////////////////// -// Disassembler setup -////////////////////////////////////////////////////////////////////// - -BOOL InitDisassembler(DISASSEMBLER *Disassembler, ARCHITECTURE_TYPE Architecture) -{ - ARCHITECTURE_FORMAT *ArchFormat; - - memset(Disassembler, 0, sizeof(DISASSEMBLER)); - Disassembler->Initialized = DISASSEMBLER_INITIALIZED; - - ArchFormat = GetArchitectureFormat(Architecture); - if (!ArchFormat) { assert(0); return FALSE; } - Disassembler->ArchType = ArchFormat->Type; - Disassembler->Functions = ArchFormat->Functions; - return TRUE; -} - -void CloseDisassembler(DISASSEMBLER *Disassembler) -{ - memset(Disassembler, 0, sizeof(DISASSEMBLER)); -} - -////////////////////////////////////////////////////////////////////// -// Instruction setup -////////////////////////////////////////////////////////////////////// - -BOOL InitInstruction(INSTRUCTION *Instruction, DISASSEMBLER *Disassembler) -{ - memset(Instruction, 0, sizeof(INSTRUCTION)); - Instruction->Initialized = INSTRUCTION_INITIALIZED; - Instruction->Disassembler = Disassembler; - memset(Instruction->String, ' ', MAX_OPCODE_DESCRIPTION-1); - Instruction->String[MAX_OPCODE_DESCRIPTION-1] = '\0'; - return TRUE; -} - -// If Decode = FALSE, only the following fields are valid: -// Instruction->Length, Instruction->Address, Instruction->Prefixes, Instruction->PrefixCount, -// Instruction->OpcodeBytes, Instruction->Instruction->OpcodeLength, Instruction->Groups, -// Instruction->Type, Instruction->OperandCount -// -// If Disassemble = TRUE, then Instruction->String is valid (also requires Decode = TRUE) -// -// WARNING: This will overwrite the previously obtained instruction -INSTRUCTION *GetInstruction(DISASSEMBLER *Disassembler, U64 VirtualAddress, U8 *Address, U32 Flags) -{ - if (Disassembler->Initialized != DISASSEMBLER_INITIALIZED) { assert(0); return NULL; } - assert(Address); - InitInstruction(&Disassembler->Instruction, Disassembler); - Disassembler->Instruction.Address = Address; - Disassembler->Instruction.VirtualAddressDelta = VirtualAddress - (U64)Address; - if (!Disassembler->Functions->GetInstruction(&Disassembler->Instruction, Address, Flags)) - { - assert(Disassembler->Instruction.Address == Address); - assert(Disassembler->Instruction.Length < MAX_INSTRUCTION_LENGTH); - - // Save the address that failed, in case the lower-level disassembler didn't - Disassembler->Instruction.Address = Address; - Disassembler->Instruction.ErrorOccurred = TRUE; - return NULL; - } - return &Disassembler->Instruction; -} - -/////////////////////////////////////////////////////////////////////////// -// Miscellaneous -/////////////////////////////////////////////////////////////////////////// - -ARCHITECTURE_FORMAT *GetArchitectureFormat(ARCHITECTURE_TYPE Type) -{ - ARCHITECTURE_FORMAT *Format; - for (Format = SupportedArchitectures; Format->Type != ARCH_UNKNOWN; Format++) - { - if (Format->Type == Type) return Format; - } - - assert(0); - return NULL; -} - diff --git a/renderdoc/3rdparty/mhook/disasm-lib/disasm.h b/renderdoc/3rdparty/mhook/disasm-lib/disasm.h deleted file mode 100644 index ea5cd3f55..000000000 --- a/renderdoc/3rdparty/mhook/disasm-lib/disasm.h +++ /dev/null @@ -1,583 +0,0 @@ -// Copyright (C) 2004, Matt Conover (mconover@gmail.com) -// -// WARNING: -// I wouldn't recommend changing any flags like OP_*, ITYPE_*, or *_MASK -// aside from those marked as UNUSED. This is because the flags parts of -// the flags are architecture independent and other are left to specific -// architectures to define, so unless you understand the relationships -// between them, I would leave them as is. - -#ifndef DISASM_H -#define DISASM_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include -#include "misc.h" - -#pragma warning(disable: 4214) -#pragma warning(disable: 4324) - -typedef signed char S8; -typedef unsigned char U8; -typedef signed short S16; -typedef unsigned short U16; -typedef signed long S32; -typedef unsigned long U32; -typedef LONG64 S64; -typedef ULONG64 U64; - -#ifdef SPEEDY -// On Visual Studio 6, making the internal functions inline makes compiling take forever -#define INTERNAL static _inline -#define INLINE _inline -#else -#define INTERNAL static -#define INLINE -#endif - -#define VALID_INSTRUCTION(i) ((i) && !((i)->ErrorOccurred)) -#define NEXT_INSTRUCTION(i) ((i)->Address + (i)->Length) -#define DISASM_ARCH_TYPE(dis) ((dis)->ArchType) -#define INS_ARCH_TYPE(ins) DISASM_ARCH_TYPE((ins)->Disassembler) - -// NOTE: these should be as big set to the maximum of the supported architectures -#define MAX_PREFIX_LENGTH 15 -#define MAX_OPERAND_COUNT 3 -#define MAX_INSTRUCTION_LENGTH 25 -#define MAX_OPCODE_LENGTH 3 -#define MAX_OPCODE_DESCRIPTION 256 - -///////////////////////////////////////////////////////////////////// -// Code branch -///////////////////////////////////////////////////////////////////// - -#define MAX_CODE_REFERENCE_COUNT 3 - -typedef struct _CODE_BRANCH -{ - U64 Addresses[MAX_CODE_REFERENCE_COUNT]; // NULL if multiple to addresses - U32 Count; - U8 IsLoop : 1; - U8 IsCall : 1; // branch if false - U8 IsIndirect : 1; // call/jmp [Address] - U8 AddressOffset: 5; - struct _INSTRUCTION_OPERAND *Operand; // the operand containg the address -} CODE_BRANCH; - -///////////////////////////////////////////////////////////////////// -// Data references -///////////////////////////////////////////////////////////////////// - -#define MAX_DATA_REFERENCE_COUNT 3 - -typedef struct _DATA_REFERENCE -{ - U64 Addresses[MAX_DATA_REFERENCE_COUNT]; // NULL if multiple to addresses - U32 Count; - ULONG_PTR DataSize; - struct _INSTRUCTION_OPERAND *Operand; // the operand containg the address -} DATA_REFERENCE; - -//////////////////////////////////////////////////////////////////// -// Instruction -///////////////////////////////////////////////////////////////////// - -// -// Instruction types (bits 0-7) -// Instruction groups (bits 8-26) -// -#define ITYPE_EXEC_OFFSET (1<<8) -#define ITYPE_ARITH_OFFSET (1<<9) -#define ITYPE_LOGIC_OFFSET (1<<10) -#define ITYPE_STACK_OFFSET (1<<11) -#define ITYPE_TESTCOND_OFFSET (1<<12) -#define ITYPE_LOAD_OFFSET (1<<13) -#define ITYPE_ARRAY_OFFSET (1<<14) -#define ITYPE_BIT_OFFSET (1<<15) -#define ITYPE_FLAG_OFFSET (1<<16) -#define ITYPE_FPU_OFFSET (1<<17) -#define ITYPE_TRAPS_OFFSET (1<<18) -#define ITYPE_SYSTEM_OFFSET (1<<19) -#define ITYPE_OTHER_OFFSET (1<<20) -#define ITYPE_UNUSED1_OFFSET (1<<21) -#define ITYPE_UNUSED2_OFFSET (1<<22) -#define ITYPE_UNUSED3_OFFSET (1<<23) -#define ITYPE_UNUSED4_OFFSET (1<<24) -#define ITYPE_UNUSED5_OFFSET (1<<25) -#define ITYPE_UNUSED6_OFFSET (1<<26) -#define ITYPE_EXT_UNUSED1 (1<<27) -#define ITYPE_EXT_UNUSED2 (1<<28) -#define ITYPE_EXT_UNUSED3 (1<<29) -#define ITYPE_EXT_UNUSED4 (1<<30) -#define ITYPE_EXT_UNUSED5 (1<<31) - -// -// X86-specific flags (bits 27-31) -// - -#define ITYPE_EXT_64 ITYPE_EXT_UNUSED1 // Use index 1 if in 64-bit mode and 0 otherwise -#define ITYPE_EXT_MODRM ITYPE_EXT_UNUSED2 // ModRM byte may extend the opcode -#define ITYPE_EXT_SUFFIX ITYPE_EXT_UNUSED3 // byte after ModRM/SIB/displacement is the third opcode -#define ITYPE_EXT_PREFIX ITYPE_EXT_UNUSED4 // prefix -#define ITYPE_EXT_FPU ITYPE_EXT_UNUSED5 // FPU instructions require special handling - -#define ITYPE_3DNOW_OFFSET ITYPE_UNUSED1_OFFSET -#define ITYPE_MMX_OFFSET ITYPE_UNUSED2_OFFSET -#define ITYPE_SSE_OFFSET ITYPE_UNUSED3_OFFSET -#define ITYPE_SSE2_OFFSET ITYPE_UNUSED4_OFFSET -#define ITYPE_SSE3_OFFSET ITYPE_UNUSED5_OFFSET - -// -// Instruction types -// - -#define ITYPE_TYPE_MASK 0x7FFFFFFF -#define ITYPE_GROUP_MASK 0x7FFFFF00 - -typedef enum _INSTRUCTION_TYPE -{ - // ITYPE_EXEC group - ITYPE_EXEC = ITYPE_EXEC_OFFSET, - ITYPE_BRANCH, - ITYPE_BRANCHCC, // conditional (not necessarily just flags) - ITYPE_CALL, - ITYPE_CALLCC, // conditional (not necessarily just flags) - ITYPE_RET, - ITYPE_LOOPCC, - - // ITYPE_ARITH group - ITYPE_ARITH = ITYPE_ARITH_OFFSET, - ITYPE_XCHGADD, - ITYPE_ADD, - ITYPE_SUB, - ITYPE_MUL, - ITYPE_DIV, - ITYPE_INC, - ITYPE_DEC, - ITYPE_SHL, - ITYPE_SHR, - ITYPE_ROL, - ITYPE_ROR, - - // ITYPE_LOGIC group - ITYPE_LOGIC=ITYPE_LOGIC_OFFSET, - ITYPE_AND, - ITYPE_OR, - ITYPE_XOR, - ITYPE_NOT, - ITYPE_NEG, - - // ITYPE_STACK group - ITYPE_STACK=ITYPE_STACK_OFFSET, - ITYPE_PUSH, - ITYPE_POP, - ITYPE_PUSHA, - ITYPE_POPA, - ITYPE_PUSHF, - ITYPE_POPF, - ITYPE_ENTER, - ITYPE_LEAVE, - - // ITYPE_TESTCOND group - ITYPE_TESTCOND=ITYPE_TESTCOND_OFFSET, - ITYPE_TEST, - ITYPE_CMP, - - // ITYPE_LOAD group - ITYPE_LOAD=ITYPE_LOAD_OFFSET, - ITYPE_MOV, - ITYPE_MOVCC, // conditional - ITYPE_LEA, - ITYPE_XCHG, - ITYPE_XCHGCC, // conditional - - // ITYPE_ARRAY group - ITYPE_ARRAY=ITYPE_ARRAY_OFFSET, - ITYPE_STRCMP, - ITYPE_STRLOAD, - ITYPE_STRMOV, - ITYPE_STRSTOR, - ITYPE_XLAT, - - // ITYPE_BIT group - ITYPE_BIT=ITYPE_BIT_OFFSET, - ITYPE_BITTEST, - ITYPE_BITSET, - ITYPE_BITCLR, - - // ITYPE_FLAG group - // PF = parify flag - // ZF = zero flag - // OF = overflow flag - // DF = direction flag - // SF = sign flag - ITYPE_FLAG=ITYPE_FLAG_OFFSET, - // clear - ITYPE_CLEARCF, - ITYPE_CLEARZF, - ITYPE_CLEAROF, - ITYPE_CLEARDF, - ITYPE_CLEARSF, - ITYPE_CLEARPF, - // set - ITYPE_SETCF, - ITYPE_SETZF, - ITYPE_SETOF, - ITYPE_SETDF, - ITYPE_SETSF, - ITYPE_SETPF, - // toggle - ITYPE_TOGCF, - ITYPE_TOGZF, - ITYPE_TOGOF, - ITYPE_TOGDF, - ITYPE_TOGSF, - ITYPE_TOGPF, - - // ITYPE_FPU group - ITYPE_FPU=ITYPE_FPU_OFFSET, - ITYPE_FADD, - ITYPE_FSUB, - ITYPE_FMUL, - ITYPE_FDIV, - ITYPE_FCOMP, - ITYPE_FEXCH, - ITYPE_FLOAD, - ITYPE_FLOADENV, - ITYPE_FSTORE, - ITYPE_FSTOREENV, - ITYPE_FSAVE, - ITYPE_FRESTORE, - ITYPE_FMOVCC, - - ITYPE_UNUSED1=ITYPE_UNUSED1_OFFSET, - ITYPE_UNUSED2=ITYPE_UNUSED2_OFFSET, - ITYPE_UNUSED3=ITYPE_UNUSED3_OFFSET, - - // ITYPE_MMX group - ITYPE_MMX=ITYPE_MMX_OFFSET, - ITYPE_MMX_MOV, - ITYPE_MMX_ADD, - ITYPE_MMX_SUB, - ITYPE_MMX_MUL, - ITYPE_MMX_DIV, - ITYPE_MMX_AND, - ITYPE_MMX_OR, - ITYPE_MMX_XOR, - ITYPE_MMX_CMP, - - // ITYPE_SSE group - ITYPE_SSE=ITYPE_SSE_OFFSET, - ITYPE_SSE_MOV, - ITYPE_SSE_ADD, - ITYPE_SSE_SUB, - ITYPE_SSE_MUL, - ITYPE_SSE_DIV, - ITYPE_SSE_AND, - ITYPE_SSE_OR, - ITYPE_SSE_XOR, - ITYPE_SSE_CMP, - - // ITYPE_SSE2 group - ITYPE_SSE2=ITYPE_SSE2_OFFSET, - ITYPE_SSE2_MOV, - ITYPE_SSE2_ADD, - ITYPE_SSE2_SUB, - ITYPE_SSE2_MUL, - ITYPE_SSE2_DIV, - ITYPE_SSE2_AND, - ITYPE_SSE2_OR, - ITYPE_SSE2_XOR, - ITYPE_SSE2_CMP, - - // ITYPE_SSE3 group - ITYPE_SSE3=ITYPE_SSE3_OFFSET, - ITYPE_SSE3_MOV, - ITYPE_SSE3_ADD, - ITYPE_SSE3_SUB, - ITYPE_SSE3_MUL, - ITYPE_SSE3_DIV, - ITYPE_SSE3_AND, - ITYPE_SSE3_OR, - ITYPE_SSE3_XOR, - ITYPE_SSE3_CMP, - - // ITYPE_3DNOW group - ITYPE_3DNOW=ITYPE_3DNOW_OFFSET, - ITYPE_3DNOW_ADD, - ITYPE_3DNOW_SUB, - ITYPE_3DNOW_MUL, - ITYPE_3DNOW_DIV, - ITYPE_3DNOW_CMP, - ITYPE_3DNOW_XCHG, - - // ITYPE_TRAP - ITYPE_TRAPS=ITYPE_TRAPS_OFFSET, - ITYPE_TRAP, // generate trap - ITYPE_TRAPCC, // conditional trap gen - ITYPE_TRAPRET, // return from trap - ITYPE_BOUNDS, // gen bounds trap - ITYPE_DEBUG, // gen breakpoint trap - ITYPE_TRACE, // gen single step trap - ITYPE_INVALID, // gen invalid instruction - ITYPE_OFLOW, // gen overflow trap - - // ITYPE_SYSTEM group - ITYPE_SYSTEM=ITYPE_SYSTEM_OFFSET, - ITYPE_HALT, // halt machine - ITYPE_IN, // input form port - ITYPE_OUT, // output to port - ITYPE_CPUID, // identify cpu - ITYPE_SETIF, // allow interrupts - ITYPE_CLEARIF, // block interrupts - ITYPE_SYSCALL, - ITYPE_SYSCALLRET, - - // ITYPE_OTHER group - ITYPE_OTHER = ITYPE_OTHER_OFFSET, - ITYPE_NOP, - ITYPE_BCDCONV, // convert to/from BCD - ITYPE_SZCONV // convert size of operand -} INSTRUCTION_TYPE; - -// -// Operand flags -// - -// Type = bits 0-6 (these are mutually exclusive -- bits 0-6 will always be a power of 2)) -#define OPTYPE_NONE 0x00 -#define OPTYPE_IMM 0x01 // immediate value -#define OPTYPE_OFFSET 0x02 // relative offset -#define OPTYPE_FLOAT 0x03 // floating point -#define OPTYPE_BCD 0x04 -#define OPTYPE_STRING 0x05 -#define OPTYPE_SPECIAL 0x06 -#define OPTYPE_MASK 0x7F - -// Flags = bits 7-23 (these can be combinations) -// These are used in the X86 opcode table -#define OP_REG (1<<7) // 0x80 -#define OP_SIGNED (1<<8) -#define OP_SYS (1<<9) // parameter is an index into some system structure -#define OP_CONDR (1<<10) -#define OP_CONDW (1<<11) -#define OP_UNUSED (1<<12) -#define OP_SRC (1<<13) // operand is source operand -#define OP_DST (1<<14) // operand is destination operand -#define OP_EXEC (1<<15) // operand is executed - -#define OP_CONDE OP_CONDR -#define OP_COND_EXEC (OP_CONDE|OP_EXEC) // executed only if the pre-conditions are met -#define OP_COND_SRC (OP_CONDR|OP_SRC) // set only if pre-conditions are met -#define OP_COND_DST (OP_CONDW|OP_DST) // set only if pre-conditions are met -#define OP_COND (OP_CONDR|OP_CONDW) - -// Bits 16-31 are available for use outside of the opcode table, but they can only -// be used in INSTRUCTION_OPERAND.Flags, they may conflit with the architecture specific -// operands. For example, bits 16-31 are used in X86 for AMODE_* and OPTYPE_* -#define OP_ADDRESS (1<<16) -#define OP_LOCAL (1<<17) -#define OP_PARAM (1<<18) -#define OP_GLOBAL (1<<19) -#define OP_FAR (1<<20) -#define OP_IPREL (1<<21) - -// -// X86-specific flags (bits 27-31) -// -#define OP_MSR (OP_SYS|OP_UNUSED) - -// -// Other architecture flags -// -#define OP_DELAY OP_UNUSED // delayed instruction (e.g., delayed branch that executes after the next instruction) - -///////////////////////////////////////////////////////////////////// -// Architectures -///////////////////////////////////////////////////////////////////// - -typedef enum _ARCHITECTURE_TYPE -{ - ARCH_UNKNOWN=0, - - // x86-based - ARCH_X86, // 32-bit x86 - ARCH_X86_16, // 16-bit x86 - ARCH_X64, // AMD64 and Intel EMD64 - - // everything else - ARCH_ALPHA, - ARCH_ARM, - ARCH_DOTNET, - ARCH_EFI, - ARCH_IA64, - ARCH_M68K, - ARCH_MIPS, - ARCH_PPC, - ARCH_SH3, - ARCH_SH4, - ARCH_SPARC, - ARCH_THUMB - -} ARCHITECTURE_TYPE; - -struct _INSTRUCTION; - -typedef BOOL (*INIT_INSTRUCTION)(struct _INSTRUCTION *Instruction); -typedef void (*DUMP_INSTRUCTION)(struct _INSTRUCTION *Instruction, BOOL ShowBytes, BOOL Verbose); -typedef BOOL (*GET_INSTRUCTION)(struct _INSTRUCTION *Instruction, U8 *Address, U32 Flags); -typedef U8 *(*FIND_FUNCTION_BY_PROLOGUE)(struct _INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, U32 Flags); - -typedef struct _ARCHITECTURE_FORMAT_FUNCTIONS -{ - INIT_INSTRUCTION InitInstruction; - DUMP_INSTRUCTION DumpInstruction; - GET_INSTRUCTION GetInstruction; - FIND_FUNCTION_BY_PROLOGUE FindFunctionByPrologue; -} ARCHITECTURE_FORMAT_FUNCTIONS; - -typedef struct _ARCHITECTURE_FORMAT -{ - ARCHITECTURE_TYPE Type; - ARCHITECTURE_FORMAT_FUNCTIONS *Functions; -} ARCHITECTURE_FORMAT; - -#define DISASSEMBLER_INITIALIZED 0x1234566F -#define INSTRUCTION_INITIALIZED 0x1234567F - -#include "disasm_x86.h" - -typedef struct DECLSPEC_ALIGN(16) _S128 -{ - U64 Low; - S64 High; -} S128; -typedef struct DECLSPEC_ALIGN(16) _U128 -{ - U64 Low; - U64 High; -} U128; - -typedef struct _INSTRUCTION_OPERAND -{ - U32 Flags; - U8 Type : 6; - U8 Unused : 2; - U16 Length; - - - // If non-NULL, this indicates the target address of the instruction (e.g., a branch or - // a displacement with no base register). However, this address is only reliable if the - // image is mapped correctly (e.g., the executable is mapped as an image and fixups have - // been applied if it is not at its preferred image base). - // - // If disassembling a 16-bit DOS application, TargetAddress is in the context of - // X86Instruction->Segment. For example, if TargetAddress is the address of a code branch, - // it is in the CS segment (unless X86Instruction->HasSegmentOverridePrefix is set). If - // TargetAddress is a data pointer, it is in the DS segment (unless - // X86Instruction->HasSegmentOverridePrefix is set) - U64 TargetAddress; - U32 Register; - - union - { - // All 8/16/32-bit operands are extended to 64-bits automatically - // If you want to downcast, check whether Flags & OP_SIGNED is set - // Like this: - // U32 GetOperand32(OPERAND *Operand) - // { - // if (Operand->Flags & OP_SIGNED) return (S32)Operand->Value_S64; - // else return (U32)Operand->Value_U64; - //} - U64 Value_U64; - S64 Value_S64; - U128 Value_U128; - U128 Float128; - U8 Float80[80]; - U8 BCD[10]; - }; -} INSTRUCTION_OPERAND; - -typedef struct _INSTRUCTION -{ - U32 Initialized; - struct _DISASSEMBLER *Disassembler; - - char String[MAX_OPCODE_DESCRIPTION]; - U8 StringIndex; - U64 VirtualAddressDelta; - - U32 Groups; // ITYPE_EXEC, ITYPE_ARITH, etc. -- NOTE groups can be OR'd together - INSTRUCTION_TYPE Type; // ITYPE_ADD, ITYPE_RET, etc. -- NOTE there is only one possible type - - U8 *Address; - U8 *OpcodeAddress; - U32 Length; - - U8 Prefixes[MAX_PREFIX_LENGTH]; - U32 PrefixCount; - - U8 LastOpcode; // last byte of opcode - U8 OpcodeBytes[MAX_OPCODE_LENGTH]; - U32 OpcodeLength; // excludes any operands and prefixes - - INSTRUCTION_OPERAND Operands[MAX_OPERAND_COUNT]; - U32 OperandCount; - - X86_INSTRUCTION X86; - - DATA_REFERENCE DataSrc; - DATA_REFERENCE DataDst; - CODE_BRANCH CodeBranch; - - // Direction depends on which direction the stack grows - // For example, on x86 a push results in StackChange < 0 since the stack grows down - // This is only relevant if (Group & ITYPE_STACK) is true - // - // If Groups & ITYPE_STACK is set but StackChange = 0, it means that the change - // couldn't be determined (non-constant) - LONG StackChange; - - // Used to assist in debugging - // If set, the current instruction is doing something that requires special handling - // For example, popf can cause tracing to be disabled - - U8 StringAligned : 1; // internal only - U8 NeedsEmulation : 1; // instruction does something that re - U8 Repeat : 1; // instruction repeats until some condition is met (e.g., REP prefix on X86) - U8 ErrorOccurred : 1; // set if instruction is invalid - U8 AnomalyOccurred : 1; // set if instruction is anomalous - U8 LastInstruction : 1; // tells the iterator callback it is the last instruction - U8 CodeBlockFirst: 1; - U8 CodeBlockLast : 1; -} INSTRUCTION; - -typedef struct _DISASSEMBLER -{ - U32 Initialized; - ARCHITECTURE_TYPE ArchType; - ARCHITECTURE_FORMAT_FUNCTIONS *Functions; - INSTRUCTION Instruction; - U32 Stage1Count; // GetInstruction called - U32 Stage2Count; // Opcode fully decoded - U32 Stage3CountNoDecode; // made it through all checks when DISASM_DECODE is not set - U32 Stage3CountWithDecode; // made it through all checks when DISASM_DECODE is set -} DISASSEMBLER; - -#define DISASM_DISASSEMBLE (1<<1) -#define DISASM_DECODE (1<<2) -#define DISASM_SUPPRESSERRORS (1<<3) -#define DISASM_SHOWFLAGS (1<<4) -#define DISASM_ALIGNOUTPUT (1<<5) -#define DISASM_DISASSEMBLE_MASK (DISASM_ALIGNOUTPUT|DISASM_SHOWBYTES|DISASM_DISASSEMBLE) - -BOOL InitDisassembler(DISASSEMBLER *Disassembler, ARCHITECTURE_TYPE Architecture); -void CloseDisassembler(DISASSEMBLER *Disassembler); -INSTRUCTION *GetInstruction(DISASSEMBLER *Disassembler, U64 VirtualAddress, U8 *Address, U32 Flags); - -#ifdef __cplusplus -} -#endif -#endif // DISASM_H diff --git a/renderdoc/3rdparty/mhook/disasm-lib/disasm_x86.c b/renderdoc/3rdparty/mhook/disasm-lib/disasm_x86.c deleted file mode 100644 index 9a16abe4a..000000000 --- a/renderdoc/3rdparty/mhook/disasm-lib/disasm_x86.c +++ /dev/null @@ -1,4664 +0,0 @@ -// Copyright (C) 2004, Matt Conover (mconover@gmail.com) -#undef NDEBUG -#include -#include "disasm.h" -#include "cpu.h" - -// Since addresses are internally represented as 64-bit, we need to specially handle -// cases where IP + Displacement wraps around for 16-bit/32-bit operand size -// Otherwise, ignorethe possibility of wraparounds -#define SUPPORT_WRAPAROUND - -#ifdef NO_SANITY_CHECKS -#undef NDEBUG -#undef DEBUG_DISASM -#undef assert -#define assert(x) -#endif - -#ifdef DEBUG_DISASM -#define DISASM_OUTPUT(x) printf x -#else -#define DISASM_OUTPUT(x) -#endif - -#include "disasm_x86_tables.h" - -#ifdef _WIN64 -#pragma warning(disable:4311 4312) -#endif - -#pragma warning(disable:4702) - -//////////////////////////////////////////////////////////////////////// -// Internal macros -//////////////////////////////////////////////////////////////////////// - -#define VIRTUAL_ADDRESS ((U64)Instruction->Address + Instruction->VirtualAddressDelta) - -#define AMD64_DIFF (AMD64_8BIT_OFFSET-X86_8BIT_OFFSET) -#define IS_AMD64() (INS_ARCH_TYPE(Instruction) == ARCH_X64) -#define IS_X86_32() (INS_ARCH_TYPE(Instruction) == ARCH_X86) -#define IS_X86_16() (INS_ARCH_TYPE(Instruction) == ARCH_X86_16) - -#define X86_BOUND 0x62 -#define X86_PUSH_REG 0x50 -#define X86_PUSH_CS 0x0e -#define X86_PUSH_DS 0x1e -#define X86_PUSH_SS 0x16 -#define X86_PUSH_ES 0x06 -#define X86_PUSH_FS 0xa0 -#define X86_PUSH_GS 0xa8 -#define X86_PUSH_U8 0x6a -#define X86_PUSH_U32 0x68 -#define X86_POP_DS 0x1f -#define X86_POP_ES 0x07 -#define X86_POP_SS 0x17 -#define X86_POP_FS 0xa1 -#define X86_POP_GS 0xa9 -#define X86_POP_REG 0x58 - -#define OPCSTR Instruction->String+Instruction->StringIndex -#define APPEND Instruction->StringIndex += (U8)_snprintf -#define APPENDPAD(x) \ -{ \ - if (Instruction->StringAligned) \ - { \ - if (Instruction->StringIndex > x) assert(0); \ - while (x != Instruction->StringIndex) APPENDB(' '); \ - } \ - else if (Instruction->StringIndex) \ - { \ - APPENDB(' '); \ - } \ -} - -#define APPENDB(a) Instruction->String[Instruction->StringIndex++] = a -#define APPENDS(a) APPEND(OPCSTR, SIZE_LEFT, a); - -#define SIZE_LEFT (MAX_OPCODE_DESCRIPTION-1 > Instruction->StringIndex ? MAX_OPCODE_DESCRIPTION-Instruction->StringIndex : 0) - -// If an address size prefix is used for an instruction that doesn't make sense, restore it -// to the default - -#define SANITY_CHECK_OPERAND_SIZE() \ -{ \ - if (!Instruction->AnomalyOccurred && X86Instruction->HasOperandSizePrefix) \ - { \ - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected operand size prefix\n", VIRTUAL_ADDRESS); \ - Instruction->AnomalyOccurred = TRUE; \ - X86Instruction->HasOperandSizePrefix = FALSE; \ - switch (X86Instruction->OperandSize) \ - { \ - case 4: X86Instruction->OperandSize = 2; break; \ - case 2: X86Instruction->OperandSize = 4; break; \ - default: assert(0); \ - } \ - } \ -} - -#define SANITY_CHECK_ADDRESS_SIZE() \ -{ \ - if (!Instruction->AnomalyOccurred && X86Instruction->HasAddressSizePrefix) \ - { \ - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected address size prefix\n", VIRTUAL_ADDRESS); \ - Instruction->AnomalyOccurred = TRUE; \ - } \ - X86Instruction->HasAddressSizePrefix = FALSE; \ - switch (INS_ARCH_TYPE(Instruction)) \ - { \ - case ARCH_X64: X86Instruction->AddressSize = 8; break; \ - case ARCH_X86: X86Instruction->AddressSize = 4; break; \ - case ARCH_X86_16: X86Instruction->AddressSize = 2; break; \ - } \ -} - -#define SANITY_CHECK_SEGMENT_OVERRIDE() \ - if (!Instruction->AnomalyOccurred && X86Instruction->HasSegmentOverridePrefix) \ - { \ - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected segment override\n", VIRTUAL_ADDRESS); \ - Instruction->AnomalyOccurred = TRUE; \ - } - -#define INSTR_INC(size) \ -{ \ - Instruction->Length += size; \ - Address += size; \ -} - -#define X86_SET_TARGET() \ -{ \ - if (X86Instruction->HasSelector) \ - { \ - if (!Instruction->AnomalyOccurred) \ - { \ - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: unexpected segment 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->Selector); \ - Instruction->AnomalyOccurred = TRUE; \ - } \ - } \ - else \ - { \ - switch (X86Instruction->Segment) \ - { \ - case SEG_CS: \ - case SEG_DS: \ - case SEG_SS: \ - case SEG_ES: \ - assert(!X86Instruction->HasSelector); \ - Operand->TargetAddress = (U64)X86Instruction->Displacement; \ - /* assert(!GetAbsoluteAddressFromSegment((BYTE)X86Instruction->Segment, (DWORD)X86Instruction->Displacement) || GetAbsoluteAddressFromSegment(X86Instruction->Segment, (DWORD)X86Instruction->Displacement) == Operand->TargetAddress); */ \ - break; \ - case SEG_FS: \ - case SEG_GS: \ - assert(!X86Instruction->HasSelector); \ - Operand->TargetAddress = (U64)GetAbsoluteAddressFromSegment((BYTE)X86Instruction->Segment, (DWORD)X86Instruction->Displacement); \ - break; \ - default: \ - assert(0); /* shouldn't be possible */ \ - break; \ - } \ - } \ -} - -#define X86_SET_SEG(reg) \ -{ \ - if (!X86Instruction->HasSegmentOverridePrefix && (reg == REG_EBP || reg == REG_ESP)) \ - { \ - assert(!X86Instruction->HasSelector); \ - X86Instruction->Segment = SEG_SS; \ - } \ -} - -#define X86_SET_ADDR() \ -{ \ - if (Operand->Flags & OP_DST) \ - { \ - assert(!X86Instruction->HasDstAddressing); \ - X86Instruction->HasDstAddressing = TRUE; \ - X86Instruction->DstOpIndex[X86Instruction->DstOpCount] = (U8)OperandIndex; \ - X86Instruction->DstOpCount++; \ - X86Instruction->DstAddressIndex = (U8)OperandIndex; \ - } \ - if (Operand->Flags & OP_SRC) \ - { \ - if (Instruction->Type != ITYPE_STRCMP) assert(!X86Instruction->HasSrcAddressing); \ - X86Instruction->HasSrcAddressing = TRUE; \ - X86Instruction->SrcOpIndex[X86Instruction->SrcOpCount] = (U8)OperandIndex; \ - X86Instruction->SrcOpCount++; \ - X86Instruction->SrcAddressIndex = (U8)OperandIndex; \ - } \ -} - -#define X86_SET_REG(reg) \ -{ \ - if (Operand->Flags & OP_DST) \ - { \ - X86Instruction->DstOpIndex[X86Instruction->DstOpCount] = (U8)OperandIndex; \ - X86Instruction->DstOpCount++; \ - assert(OperandIndex < 2); \ - if (Operand->Length > 1 && reg == REG_ESP) Instruction->Groups |= ITYPE_STACK; \ - } \ - if (Operand->Flags & OP_SRC) \ - { \ - X86Instruction->SrcOpIndex[X86Instruction->SrcOpCount] = (U8)OperandIndex; \ - X86Instruction->SrcOpCount++; \ - } \ -} - -#define CHECK_AMD64_REG() { if (IS_AMD64()) Operand->Register += AMD64_DIFF; } - -//////////////////////////////////////////////////////////////////////// -// Internal structures/variables -//////////////////////////////////////////////////////////////////////// - -ARCHITECTURE_FORMAT_FUNCTIONS X86 = -{ - X86_InitInstruction, - NULL, - X86_GetInstruction, - X86_FindFunctionByPrologue -}; - -char *X86_Registers[0xE0] = -{ - // Segments - "es", // 0x00 - "cs", // 0x01 - "ss", // 0x02 - "ds", // 0x03 - "fs", // 0x04 - "gs", // 0x05 - "flags", // 0x06 - "eflags", // 0x07 - "rflags", // 0x08 - "ip+ilen", // 0x09 - "eip+ilen", // 0x0A - "rip+ilen", // 0x0B - NULL, // 0x0C - NULL, // 0x0D - NULL, // 0x0E - NULL, // 0x0F - - // Test - "tr0", // 0x10 - "tr1", // 0x11 - "tr2", // 0x12 - "tr3", // 0x13 - "tr4", // 0x14 - "tr5", // 0x15 - "tr6", // 0x16 - "tr7", // 0x17 - "tr8", // 0x18 - "tr9", // 0x19 - "tr10", // 0x1A - "tr11", // 0x1B - "tr12", // 0x1C - "tr13", // 0x1D - "tr14", // 0x1E - "tr15", // 0x1F - - // Control - "cr0", // 0x20 - "cr1", // 0x21 - "cr2", // 0x22 - "cr3", // 0x23 - "cr4", // 0x24 - "cr5", // 0x25 - "cr6", // 0x26 - "cr7", // 0x27 - "cr8", // 0x18 - "cr9", // 0x19 - "cr10", // 0x1A - "cr11", // 0x1B - "cr12", // 0x1C - "cr13", // 0x1D - "cr14", // 0x1E - "cr15", // 0x1F - - // Debug - "dr0", // 0x30 - "dr1", // 0x31 - "dr2", // 0x32 - "dr3", // 0x33 - "dr4", // 0x34 - "dr5", // 0x35 - "dr6", // 0x36 - "dr7", // 0x37 - "dr8", // 0x38 - "dr9", // 0x39 - "dr10", // 0x3A - "dr11", // 0x3B - "dr12", // 0x3C - "dr13", // 0x3D - "dr14", // 0x3E - "dr15", // 0x3F - - // FPU - "st(0)", // 0x40 - "st(1)", // 0x41 - "st(2)", // 0x42 - "st(3)", // 0x43 - "st(4)", // 0x44 - "st(5)", // 0x45 - "st(6)", // 0x46 - "st(7)", // 0x47 - NULL, // 0x48 - NULL, // 0x49 - NULL, // 0x4A - NULL, // 0x4B - NULL, // 0x4C - NULL, // 0x4D - NULL, // 0x4E - NULL, // 0x4F - - // MMX - "mm0", // 0x50 - "mm1", // - "mm2", - "mm3", - "mm4", - "mm5", - "mm6", - "mm7", - NULL, // 0x58 - NULL, // 0x59 - NULL, // 0x5A - NULL, // 0x5B - NULL, // 0x5C - NULL, // 0x5D - NULL, // 0x5E - NULL, // 0x5F - - // XMM - "xmm0", // 0x60 - "xmm1", // 0x61 - "xmm2", // 0x62 - "xmm3", // 0x63 - "xmm4", // 0x64 - "xmm5", // 0x65 - "xmm6", // 0x66 - "xmm7", // 0x67 - "xmm8", // 0x68 - "xmm9", // 0x69 - "xmm10", // 0x6a - "xmm11", // 0x6b - "xmm12", // 0x6c - "xmm13", // 0x6d - "xmm14", // 0x6e - "xmm15", // 0x6f - - // 8-bit - "al", // 0x70 - "cl", // 0x71 - "dl", // 0x72 - "bl", // 0x73 - "ah", // 0x74 - "ch", // 0x75 - "dh", // 0x76 - "bh", // 0x77 - NULL, // 0x78 - NULL, // 0x79 - NULL, // 0x7A - NULL, // 0x7B - NULL, // 0x7C - NULL, // 0x7D - NULL, // 0x7E - NULL, // 0x7F - - // 16-bit - "ax", // 0x80 - "cx", // 0x81 - "dx", // 0x82 - "bx", // 0x83 - "sp", // 0x84 - "bp", // 0x85 - "si", // 0x86 - "di", // 0x87 - NULL, // 0x88 - NULL, // 0x89 - NULL, // 0x8A - NULL, // 0x8B - NULL, // 0x8C - NULL, // 0x8D - NULL, // 0x8E - NULL, // 0x8F - - // 32-bit - "eax", // 0x90 - "ecx", // 0x91 - "edx", // 0x92 - "ebx", // 0x93 - "esp", // 0x94 - "ebp", // 0x95 - "esi", // 0x96 - "edi", // 0x97 - NULL, // 0x98 - NULL, // 0x99 - NULL, // 0x9A - NULL, // 0x9B - NULL, // 0x9C - NULL, // 0x9D - NULL, // 0x9E - NULL, // 0x9F - - // X86-64 8-bit register - "al", // 0xA0 - "cl", // 0xA1 - "dl", // 0xA2 - "bl", // 0xA3 - "spl", // 0xA4 - "bpl", // 0xA5 - "sil", // 0xA6 - "dil", // 0xA7 - "r8b", // 0xA8 - "r9b", // 0xA9 - "r10b", // 0xAA - "r11b", // 0xAB - "r12b", // 0xAC - "r13b", // 0xAD - "r14b", // 0xAE - "r15b", // 0xAF - - // X86-64 16-bit register - "ax", // 0xB0 - "cx", // 0xB1 - "dx", // 0xB2 - "bx", // 0xB3 - "sp", // 0xB4 - "bp", // 0xB5 - "si", // 0xB6 - "di", // 0xB7 - "r8w", // 0xB8 - "r9w", // 0xB9 - "r10w", // 0xBA - "r11w", // 0xBB - "r12w", // 0xBC - "r13w", // 0xBD - "r14w", // 0xBE - "r15w", // 0xBF - - // X86-64 32-bit register - "eax", // 0xC0 - "ecx", // 0xC1 - "edx", // 0xC2 - "ebx", // 0xC3 - "esp", // 0xC4 - "ebp", // 0xC5 - "esi", // 0xC6 - "edi", // 0xC7 - "r8d", // 0xC8 - "r9d", // 0xC9 - "r10d", // 0xCA - "r11d", // 0xCB - "r12d", // 0xCC - "r13d", // 0xCD - "r14d", // 0xCE - "r15d", // 0xCF - - // X86-64 64-bit register - "rax", // 0xD0 - "rcx", // 0xD1 - "rdx", // 0xD2 - "rbx", // 0xD3 - "rsp", // 0xD4 - "rbp", // 0xD5 - "rsi", // 0xD6 - "rdi", // 0xD7 - "r8", // 0xD8 - "r9", // 0xD9 - "r10", // 0xDA - "r11", // 0xDB - "r12", // 0xDC - "r13", // 0xDD - "r14", // 0xDE - "r15" // 0xDF -}; - -void OutputBounds(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputDescriptor(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputSegOffset(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputPackedReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputPackedBCD(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputScalarReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputScalarGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputFPUEnvironment(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputFPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputCPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); - -typedef void (*OUTPUT_OPTYPE)(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -#define OPTYPE_SHIFT 24 -#define MAX_OPTYPE_INDEX 26 -OUTPUT_OPTYPE OptypeHandlers[] = -{ - NULL, - OutputBounds, // 01 OPTYPE_a - OutputGeneral, // 02 OPTYPE_b - OutputGeneral, // 03 OPTYPE_d - OutputSegOffset, // 04 OPTYPE_p - OutputGeneral, // 05 OPTYPE_q - OutputDescriptor, // 06 OPTYPE_dt - OutputGeneral, // 07 OPTYPE_v - OutputGeneral, // 08 OPTYPE_w - OutputPackedReal, // 09 OPTYPE_ps - OutputPackedReal, // 0A OPTYPE_pd - OutputPackedBCD, // 0B OPTYPE_pb - OutputScalarReal, // 0C OPTYPE_ss - OutputScalarReal, // 0D OPTYPE_sd - OutputScalarReal, // 0E OPTYPE_se - OutputFPUEnvironment, // 0F OPTYPE_fev - OutputFPUState, // 10 OPTYPE_fst1 - OutputFPUState, // 11 OPTYPE_fst2 - OutputGeneral, // 12 OPTYPE_z - OutputGeneral, // 13 OPTYPE_o - OutputGeneral, // 14 OPTYPE_dq - OutputGeneral, // 15 OPTYPE_mw - OutputScalarGeneral, // 16 OPTYPE_sso - OutputScalarGeneral, // 17 OPTYPE_sdo - OutputCPUState, // 18 OPTYPE_cpu - OutputGeneral, // 19 OPTYPE_lea -}; - -#define OPTYPE_a 0x01000000 -#define OPTYPE_b 0x02000000 -#define OPTYPE_d 0x03000000 -#define OPTYPE_p 0x04000000 -#define OPTYPE_q 0x05000000 -#define OPTYPE_dt 0x06000000 -#define OPTYPE_v 0x07000000 -#define OPTYPE_w 0x08000000 -#define OPTYPE_ps 0x09000000 // packed 128-bit single real -#define OPTYPE_pd 0x0A000000 // packed 128-bit double real -#define OPTYPE_pb 0x0B000000 // packed BCD (10 bytes, 18-bit precision) -#define OPTYPE_ss 0x0C000000 // scalar single real -#define OPTYPE_sd 0x0D000000 // scalar double real -#define OPTYPE_se 0x0E000000 // scalar extended real -#define OPTYPE_fev 0x0F000000 // FPU environment (28 bytes if 32-bit modes, 14 bytes in 16-bit mode) -#define OPTYPE_fst1 0x10000000 // FPU state (108 bytes in 32-bit modes, 94 bytes in 16-bit real mode) -#define OPTYPE_fst2 0x11000000 // FPU/MMX/XMM/MXCSR state (512 bytes) -#define OPTYPE_z 0x12000000 -#define OPTYPE_o 0x13000000 -#define OPTYPE_dq 0x14000000 // OPTYPE_d or OPTYPE_o -#define OPTYPE_mw 0x15000000 // word if memory, register size otherwise -#define OPTYPE_sso 0x16000000 // OPTYPE_ss or OPTYPE_o -#define OPTYPE_sdo 0x17000000 // OPTYPE_ss or OPTYPE_o -#define OPTYPE_cpu 0x18000000 // pointer to CPU state structure -#define OPTYPE_lea 0x19000000 // size set by other operand - -//////////////////////////////////////////////////////////////////////// -// Internal functions -//////////////////////////////////////////////////////////////////////// - -#ifdef TEST_DISASM // TODO: remove -U32 X86_GetLength(INSTRUCTION *Instruction, U8 *Address); -#endif - -INTERNAL BOOL IsValidLockPrefix(X86_INSTRUCTION *Instruction, U8 Opcode, U32 OpcodeLength, U8 Group, U8 OpcodeExtension); -INTERNAL U8 *SetOperands(INSTRUCTION *Instruction, U8 *Address, U32 Flags); -INTERNAL U8 *SetModRM32(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors); -INTERNAL U8 *SetModRM16(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors); -INTERNAL U8 *SetSIB(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors); -INTERNAL U64 ApplyDisplacement(U64 Address, INSTRUCTION *Instruction); - -////////////////////////////////////////////////////////// -// Instruction setup -////////////////////////////////////////////////////////// - -#define APPLY_OFFSET(addr) \ -{ \ - switch (X86Instruction->OperandSize) \ - { \ - case 8: addr = ((U64)(addr + Instruction->VirtualAddressDelta)); break; \ - case 4: addr = (U64)((U32)(addr + Instruction->VirtualAddressDelta)); break; \ - case 2: addr = (U64)((U8)(addr + Instruction->VirtualAddressDelta)); break; \ - default: assert(0); break; \ - } \ -} - -BOOL X86_InitInstruction(INSTRUCTION *Instruction) -{ - X86_INSTRUCTION *X86Instruction; -#ifdef NO_SANITY_CHECKS - assert(0); // be sure assertions are disabled -#endif - X86Instruction = &Instruction->X86; - memset(X86Instruction, 0, sizeof(X86_INSTRUCTION)); - - switch (INS_ARCH_TYPE(Instruction)) - { - case ARCH_X64: - X86Instruction->AddressSize = 8; - X86Instruction->OperandSize = 4; - break; - case ARCH_X86: - X86Instruction->AddressSize = 4; - X86Instruction->OperandSize = 4; - break; - case ARCH_X86_16: - X86Instruction->AddressSize = 2; - X86Instruction->OperandSize = 2; - break; - default: - assert(0); - return FALSE; - } - X86Instruction->Instruction = Instruction; - X86Instruction->Segment = SEG_DS; - return TRUE; -} - -//////////////////////////////////////////////////////////// -// Formatting -// You can change these to whatever you prefer -//////////////////////////////////////////////////////////// - -#define X86_WRITE_OPFLAGS() \ - if (Flags & DISASM_SHOWFLAGS) \ - { \ - APPENDB('{'); \ - assert(Operand->Flags & (OP_EXEC|OP_SRC|OP_DST)); \ - if (Operand->Flags & OP_IPREL) APPENDB('r'); \ - if (Operand->Flags & OP_FAR) APPENDB('f'); \ - if (Operand->Flags & OP_CONDR) APPENDB('c'); \ - if (Operand->Flags & OP_EXEC) APPENDB('X'); \ - else if (Operand->Flags & OP_SRC) APPENDB('R'); \ - if (Operand->Flags & OP_CONDW) APPENDB('c'); \ - if (Operand->Flags & OP_DST) APPENDB('W'); \ - if (Operand->Flags & OP_SYS) APPENDB('S'); \ - if (Operand->Flags & OP_ADDRESS) APPENDB('A'); \ - if (Operand->Flags & OP_PARAM) APPENDB('P'); \ - if (Operand->Flags & OP_LOCAL) APPENDB('L'); \ - if (Operand->Flags & OP_GLOBAL) APPENDB('G'); \ - APPENDB('}'); \ - } - -#define X86_WRITE_IMMEDIATE() \ -{ \ - switch (Operand->Length) \ - { \ - case 8: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%02I64X=", Operand->Value_U64); \ - if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%I64u", Operand->Value_U64); \ - /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02I64X=%I64d", -Operand->Value_S64, Operand->Value_S64);*/ \ - else APPEND(OPCSTR, SIZE_LEFT, "%I64d", Operand->Value_S64); \ - break; \ - case 4: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%02lX=", (U32)Operand->Value_U64); \ - if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%lu", (U32)Operand->Value_U64); \ - /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02lX=%ld", (U32)-Operand->Value_S64, (S32)Operand->Value_S64);*/ \ - else APPEND(OPCSTR, SIZE_LEFT, "%ld", (S32)Operand->Value_S64); \ - break; \ - case 2: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%02X=", (U16)Operand->Value_U64); \ - if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%u", (U16)Operand->Value_U64); \ - /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X=%d", (U16)-Operand->Value_S64, (S16)Operand->Value_S64);*/ \ - else APPEND(OPCSTR, SIZE_LEFT, "%d", (S16)Operand->Value_S64); \ - break; \ - case 1: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%02X=", (U8)Operand->Value_U64); \ - if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%u", (U8)Operand->Value_U64); \ - /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X=%d", (U8)-Operand->Value_S64, (S8)Operand->Value_S64);*/ \ - else APPEND(OPCSTR, SIZE_LEFT, "%d", (S8)Operand->Value_S64); \ - break; \ - default: assert(0); break; \ - } \ -} - -#define X86_WRITE_ABSOLUTE_DISPLACEMENT() \ -{ \ - switch (X86Instruction->AddressSize) \ - { \ - case 8: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%04I64X", X86Instruction->Displacement); \ - break; \ - case 4: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%04lX", (U32)X86Instruction->Displacement); \ - break; \ - case 2: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%04X", (U16)X86Instruction->Displacement); \ - break; \ - default: assert(0); break; \ - } \ -} - -#define X86_WRITE_RELATIVE_DISPLACEMENT64() \ - if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02I64X", X86Instruction->Displacement); \ - else APPEND(OPCSTR, SIZE_LEFT, "-0x%02I64X", -X86Instruction->Displacement); - -#define X86_WRITE_RELATIVE_DISPLACEMENT32() \ - if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02lX", (U32)X86Instruction->Displacement); \ - else APPEND(OPCSTR, SIZE_LEFT, "-0x%02lX", (U32)-X86Instruction->Displacement); - -#define X86_WRITE_RELATIVE_DISPLACEMENT16() \ - if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02X", (U16)X86Instruction->Displacement); \ - else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X", (U16)-X86Instruction->Displacement); - -#define X86_WRITE_RELATIVE_DISPLACEMENT() \ -{ \ - switch (X86Instruction->AddressSize) \ - { \ - case 8: \ - X86_WRITE_RELATIVE_DISPLACEMENT64() \ - break; \ - case 4: \ - X86_WRITE_RELATIVE_DISPLACEMENT32() \ - break; \ - case 2: \ - X86_WRITE_RELATIVE_DISPLACEMENT16() \ - break; \ - default: assert(0); break; \ - } \ -} - -#define X86_WRITE_IP_OFFSET(op) \ -{ \ - switch (X86Instruction->OperandSize) \ - { \ - case 8: \ - APPENDS("[rip+ilen"); \ - assert((op)->TargetAddress); \ - X86_WRITE_RELATIVE_DISPLACEMENT64() \ - APPEND(OPCSTR, SIZE_LEFT, "]=0x%04I64X", (op)->TargetAddress+Instruction->VirtualAddressDelta); \ - break; \ - case 4: \ - APPENDS("[eip+ilen"); \ - assert((op)->TargetAddress); \ - X86_WRITE_RELATIVE_DISPLACEMENT32() \ - APPEND(OPCSTR, SIZE_LEFT, "]=0x%04lX", (U32)((op)->TargetAddress+Instruction->VirtualAddressDelta)); \ - break; \ - case 2: \ - APPENDS("[ip+ilen"); \ - X86_WRITE_RELATIVE_DISPLACEMENT16() \ - APPEND(OPCSTR, SIZE_LEFT, "]=0x%04X", (U16)((op)->TargetAddress+Instruction->VirtualAddressDelta)); \ - break; \ - default: assert(0); break; \ - } \ -} - -#define X86_WRITE_OFFSET(op) \ -{ \ - assert((op)->Length <= 8); \ - if (X86Instruction->HasSelector) \ - { \ - assert((op)->Flags & OP_FAR); \ - APPEND(OPCSTR, SIZE_LEFT, "%s 0x%02X:[", DataSizes[((op)->Length >> 1)], X86Instruction->Selector); \ - } \ - else \ - { \ - assert(!((op)->Flags & OP_FAR)); \ - assert(X86Instruction->Segment < SEG_MAX) ; \ - APPEND(OPCSTR, SIZE_LEFT, "%s %s:[", DataSizes[((op)->Length >> 1)], Segments[X86Instruction->Segment]); \ - } \ - X86_WRITE_ABSOLUTE_DISPLACEMENT() \ - APPENDB(']'); \ -} - -void OutputAddress(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - BOOL ShowDisplacement = FALSE; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - - assert(!X86Instruction->HasSelector); - assert(X86Instruction->SrcAddressIndex == OperandIndex || X86Instruction->DstAddressIndex == OperandIndex); - if (Operand->Length > 16 || (Operand->Length > 1 && (Operand->Length & 1))) APPEND(OPCSTR, SIZE_LEFT, "%d_byte ptr ", Operand->Length); - else APPEND(OPCSTR, SIZE_LEFT, "%s ", DataSizes[Operand->Length >> 1]); - - // - // This attempts to display the address intelligently - // If it has a positive 32-bit displacement, it is shown as seg:Displacement[base+index*scale] - // If it is a negative displacement or 8-bit, it is shown as seg:[base+index*scale+displacement] - // - APPEND(OPCSTR, SIZE_LEFT, "%s:", Segments[X86Instruction->Segment]); - if (X86Instruction->HasBaseRegister) - { - if (X86Instruction->Displacement) - { - if (X86Instruction->HasFullDisplacement) X86_WRITE_ABSOLUTE_DISPLACEMENT() - else ShowDisplacement = TRUE; - } - APPEND(OPCSTR, SIZE_LEFT, "[%s", X86_Registers[X86Instruction->BaseRegister]); - if (X86Instruction->HasIndexRegister) - { - APPEND(OPCSTR, SIZE_LEFT, "+%s", X86_Registers[X86Instruction->IndexRegister]); - if (X86Instruction->Scale > 1) APPEND(OPCSTR, SIZE_LEFT, "*%d", X86Instruction->Scale); - } - if (ShowDisplacement) X86_WRITE_RELATIVE_DISPLACEMENT() - APPENDB(']'); - if (X86Instruction->Relative) - { - U64 Address = Operand->TargetAddress; - assert(Address); - APPLY_OFFSET(Address) - APPEND(OPCSTR, SIZE_LEFT, "=[0x%04I64X]", Address); - } - } - else if (X86Instruction->HasIndexRegister) - { - if (X86Instruction->Displacement) - { - if (X86Instruction->HasFullDisplacement) X86_WRITE_ABSOLUTE_DISPLACEMENT() - else ShowDisplacement = TRUE; - } - APPEND(OPCSTR, SIZE_LEFT, "[%s", X86_Registers[X86Instruction->IndexRegister]); - if (X86Instruction->Scale > 1) APPEND(OPCSTR, SIZE_LEFT, "*%d", X86Instruction->Scale); - if (ShowDisplacement) X86_WRITE_RELATIVE_DISPLACEMENT() - APPENDB(']'); - } - else // just a displacement - { - APPENDB('['); - X86_WRITE_ABSOLUTE_DISPLACEMENT() - APPENDB(']'); - } -} - -void OutputBounds(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing); - assert(!(Operand->Length & 1)); - Operand->Length >>= 1; - APPENDB('('); - OutputAddress(Instruction, Operand, OperandIndex); - APPENDS(", "); - X86Instruction->Displacement += Operand->Length; - OutputAddress(Instruction, Operand, OperandIndex); - X86Instruction->Displacement -= Operand->Length; - APPENDB(')'); - Operand->Length <<= 1; -} - -void OutputGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) || - (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex)) - { - OutputAddress(Instruction, Operand, OperandIndex); - } - else - { - APPENDS(X86_Registers[Operand->Register]); - } -} - -void OutputDescriptor(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing); - OutputAddress(Instruction, Operand, OperandIndex); -} - -void OutputPackedReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) || - (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex)) - { - OutputAddress(Instruction, Operand, OperandIndex); - } - else - { - APPENDS(X86_Registers[Operand->Register]); - } -} - -void OutputPackedBCD(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) || - (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex)) - { - OutputAddress(Instruction, Operand, OperandIndex); - } - else - { - APPENDS(X86_Registers[Operand->Register]); - } -} - -void OutputScalarReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) || - (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex)) - { - OutputAddress(Instruction, Operand, OperandIndex); - } - else - { - APPENDS(X86_Registers[Operand->Register]); - } -} - -void OutputScalarGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - if (Operand->Type == OPTYPE_FLOAT) - { - OutputScalarReal(Instruction, Operand, OperandIndex); - } - else - { - OutputGeneral(Instruction, Operand, OperandIndex); - } -} - -void OutputFPUEnvironment(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing); - OutputAddress(Instruction, Operand, OperandIndex); -} - -void OutputFPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing); - OutputAddress(Instruction, Operand, OperandIndex); -} - -void OutputCPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing); - OutputAddress(Instruction, Operand, OperandIndex); -} - -void OutputSegOffset(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing); - OutputAddress(Instruction, Operand, OperandIndex); -} - -//////////////////////////////////////////////////////////// -// Prologue support -//////////////////////////////////////////////////////////// - -typedef struct _PROLOGUE -{ - char *Data; - U32 Length; -} PROLOGUE; - -PROLOGUE StandardPrologues[] = -{ - { "\x55\x8b\xec", 3 }, - { "\x55\x89\xe5", 3 }, - { "\x83\xec", 2 }, - { "\x81\xec", 2 }, - // TODO: add AMD64 prologues - // TODO: add VS2003/VS2003 prologues - // TODO: add any unique prologues from other compilers - { NULL, 0 } -}; - -// Find the first function between StartAddress and EndAddress -// -// This will match a standard prologue and then analyze the following instructions to verify -// it is a valid function -U8 *X86_FindFunctionByPrologue(INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, U32 Flags) -{ - assert(0); // TODO - return NULL; -} - -////////////////////////////////////////////////////////// -// Instruction decoder -////////////////////////////////////////////////////////// - -BOOL X86_GetInstruction(INSTRUCTION *Instruction, U8 *Address, U32 Flags) -{ - BOOL SpecialExtension = FALSE; - U8 Opcode = 0, OpcodeExtension = 0, Group = 0, SSE_Prefix = 0, Suffix; - U32 i = 0, Result = 0, tmpScale; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - X86_OPCODE *X86Opcode; -#ifdef TEST_DISASM - U32 InstructionLength = 0; -#endif - INSTRUCTION_OPERAND *Operand, *Operand1 = NULL; - DISASSEMBLER *Disassembler = Instruction->Disassembler; - BOOL Decode = Flags & DISASM_DECODE; - BOOL Disassemble = Flags & DISASM_DISASSEMBLE; - BOOL SuppressErrors = Flags & DISASM_SUPPRESSERRORS; - - if (Disassemble && !Decode) - { - assert(0); - Decode = TRUE; - } - - if (!Address || !X86_InitInstruction(Instruction)) - { - assert(0); - goto abort; - } - - assert(Instruction->Address == Address); - assert(!Instruction->StringIndex && !Instruction->Length); - - Disassembler->Stage1Count++; - if (Flags & DISASM_ALIGNOUTPUT) Instruction->StringAligned = TRUE; - - // - // Get prefixes or three byte opcode - // - while (TRUE) - { - Opcode = *Address; - INSTR_INC(1); // increment Instruction->Length and address - X86Opcode = &X86_Opcodes_1[Opcode]; - - // Handle a misplaced REX prefix -- AMD64 manual says it is just ignored - if (IS_AMD64() && (Opcode >= REX_PREFIX_START && Opcode <= REX_PREFIX_END) && X86_PREFIX((&X86_Opcodes_1[*Address]))) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: REX prefix before legacy prefix 0x%02X\n", VIRTUAL_ADDRESS, Opcode); - Instruction->AnomalyOccurred = TRUE; - } - continue; - } - - if (X86_PREFIX(X86Opcode)) - { - if (!Instruction->AnomalyOccurred) - { - for (i = 0; i < Instruction->PrefixCount; i++) - { - if (Instruction->Prefixes[i] == Opcode) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Duplicate prefix 0x%02X\n", VIRTUAL_ADDRESS, Opcode); - Instruction->AnomalyOccurred = TRUE; - break; - } - } - } - - switch (Opcode) - { - case PREFIX_REPNE: // may be three byte opcode - SSE_Prefix = Opcode; - if (!Instruction->AnomalyOccurred && X86Instruction->HasRepeatWhileEqualPrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - Instruction->Repeat = TRUE; - X86Instruction->HasRepeatWhileEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileNotEqualPrefix = TRUE; - break; - case PREFIX_REP: // may be three byte opcode - SSE_Prefix = Opcode; - if (!Instruction->AnomalyOccurred && X86Instruction->HasRepeatWhileNotEqualPrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - - Instruction->Repeat = TRUE; - X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileEqualPrefix = TRUE; - break; - - case PREFIX_OPERAND_SIZE: // may be three byte opcode - SSE_Prefix = Opcode; - if (!Instruction->AnomalyOccurred && X86Instruction->HasOperandSizePrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - - if (X86Instruction->HasOperandSizePrefix) break; - else X86Instruction->HasOperandSizePrefix = TRUE; - switch (X86Instruction->OperandSize) - { - case 4: X86Instruction->OperandSize = 2; break; - case 2: X86Instruction->OperandSize = 4; break; - default: assert(0); goto abort; - } - break; - - case PREFIX_ADDRESS_SIZE: - if (!Instruction->AnomalyOccurred && X86Instruction->HasAddressSizePrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - - if (X86Instruction->HasAddressSizePrefix) break; - else X86Instruction->HasAddressSizePrefix = TRUE; - switch (X86Instruction->AddressSize) - { - case 8: - X86Instruction->AddressSize = 4; - break; - case 4: - assert(!IS_AMD64()); // this should not be possible - X86Instruction->AddressSize = 2; - break; - case 2: - X86Instruction->AddressSize = 4; - break; - default: - assert(0); goto abort; - } - break; - - case PREFIX_SEGMENT_OVERRIDE_ES: - SANITY_CHECK_SEGMENT_OVERRIDE(); - if (!IS_AMD64()) - { - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_ES; - } - else if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - break; - case PREFIX_SEGMENT_OVERRIDE_CS: - SANITY_CHECK_SEGMENT_OVERRIDE(); - if (!IS_AMD64()) - { - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_CS; - } - else if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - break; - case PREFIX_SEGMENT_OVERRIDE_SS: - SANITY_CHECK_SEGMENT_OVERRIDE(); - if (!IS_AMD64()) - { - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_SS; - } - else if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - break; - case PREFIX_SEGMENT_OVERRIDE_DS: - SANITY_CHECK_SEGMENT_OVERRIDE(); - if (!IS_AMD64()) - { - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_DS; - } - else if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - break; - case PREFIX_SEGMENT_OVERRIDE_FS: - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_FS; - break; - case PREFIX_SEGMENT_OVERRIDE_GS: - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_GS; - break; - - case PREFIX_LOCK: - if (!Instruction->AnomalyOccurred && X86Instruction->HasLockPrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasLockPrefix = TRUE; - break; - - default: - assert(0); - goto abort; - } - - if (Instruction->PrefixCount >= X86_MAX_INSTRUCTION_LEN) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH); - goto abort; - } - else if (Instruction->PrefixCount == X86_MAX_PREFIX_LENGTH) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH); - Instruction->AnomalyOccurred = TRUE; - } - - assert(Instruction->AnomalyOccurred || Instruction->PrefixCount < X86_MAX_PREFIX_LENGTH); - Instruction->Prefixes[Instruction->PrefixCount] = Opcode; - Instruction->PrefixCount++; - //DISASM_OUTPUT(("[0x%08I64X] Prefix 0x%02X (prefix count %d)\n", VIRTUAL_ADDRESS, Opcode, Instruction->PrefixCount)); - } - else - { - break; - } - } - - // Check for REX opcode - // This is checked here instead of the prefix loop above because it must be the - // last prefix - if (IS_AMD64() && (Opcode >= REX_PREFIX_START && Opcode <= REX_PREFIX_END)) - { - if (Instruction->PrefixCount >= X86_MAX_INSTRUCTION_LEN) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH); - goto abort; - } - else if (!Instruction->AnomalyOccurred && Instruction->PrefixCount == AMD64_MAX_PREFIX_LENGTH) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH); - Instruction->AnomalyOccurred = TRUE; - } - - assert(Instruction->AnomalyOccurred || Instruction->PrefixCount < AMD64_MAX_PREFIX_LENGTH); - - Instruction->Prefixes[Instruction->PrefixCount] = Opcode; - Instruction->PrefixCount++; - X86Instruction->rex_b = Opcode; - SET_REX(X86Instruction->rex, X86Instruction->rex_b); - DISASM_OUTPUT(("[0x%08I64X] REX prefix 0x%02X (prefix count %d, w=%d, r=%d, x=%d, b=%d)\n", VIRTUAL_ADDRESS, Opcode, Instruction->PrefixCount, X86Instruction->rex.w, X86Instruction->rex.r, X86Instruction->rex.x, X86Instruction->rex.b)); - - assert(X86Instruction->AddressSize >= 4); - if (X86Instruction->rex.w) - { - X86Instruction->OperandSize = 8; - X86Instruction->HasOperandSizePrefix = FALSE; - } - else if (X86Instruction->HasOperandSizePrefix) - { - assert(X86Instruction->OperandSize == 2); - } - else if (X86Instruction->rex_b == REX_PREFIX_START) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: meaningless REX prefix used\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->rex_b = 0; - } - - Opcode = *Address; - INSTR_INC(1); // increment Instruction->Length and address - - X86Opcode = &X86_Opcodes_1[Opcode]; - assert(!X86_PREFIX(X86Opcode)); - } - //DISASM_OUTPUT(("[0x%08I64X] OperandSize = %d, AddressSize = %d\n", VIRTUAL_ADDRESS, X86Instruction->OperandSize, X86Instruction->AddressSize)); - Instruction->LastOpcode = Opcode; - Instruction->OpcodeAddress = Address-1; - - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid opcode 0x%02X\n", VIRTUAL_ADDRESS, Opcode); - goto abort; - } - - if (Opcode == X86_TWO_BYTE_OPCODE) - { - // - // Handle case that it is a group (with opcode extension), floating point, or two byte opcode - // - assert(!Instruction->OpcodeLength); - Instruction->LastOpcode = Opcode = *Address; - INSTR_INC(1); // increment Instruction->Length and address - assert(X86Opcode->Table == X86_Opcodes_2); - X86Opcode = &X86_Opcodes_2[Opcode]; - - // - // Check for errors - // - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid two byte opcode 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode); - goto abort; - } - - if (X86Instruction->AddressSize == 8) - { - if (X86_Invalid_Addr64_2[Opcode]) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X 0x%02X (\"%s\") illegal in 64-bit mode\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic); - goto abort; - } -#if 0 - if (X86Instruction->rex_b && - (GET_REX_B(X86Instruction->rex_b) && !GET_REX_B(X86_REX_2[Opcode]) || - GET_REX_X(X86Instruction->rex_b) && !GET_REX_X(X86_REX_2[Opcode]) || - GET_REX_R(X86Instruction->rex_b) && !GET_REX_R(X86_REX_2[Opcode]) || - GET_REX_W(X86Instruction->rex_b) && !GET_REX_W(X86_REX_2[Opcode]))) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal REX prefix 0x%02X for opcode 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->rex_b, X86_TWO_BYTE_OPCODE, Opcode); - assert(0); - goto abort; - } -#endif - } - - if (X86Instruction->OperandSize == 2 && X86_Invalid_Op16_2[Opcode]) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X 0x%02X (\"%s\") illegal with 16-bit operand size\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic); - goto abort; - } - - X86Instruction->HasModRM = X86_ModRM_2[Opcode]; - if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address; - Instruction->OpcodeBytes[0] = X86_TWO_BYTE_OPCODE; - Instruction->OpcodeBytes[1] = Opcode; - Instruction->OpcodeLength = 2; - - if (X86_SPECIAL_EXTENSION(X86Opcode)) - { - DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode)); - SpecialExtension = TRUE; - goto HasSpecialExtension; - } - else if (SSE_Prefix && !X86_INVALID(&X86_SSE[Opcode])) // SSEx instruction - { - Instruction->OpcodeLength = 3; - Instruction->OpcodeBytes[2] = SSE_Prefix; - assert(Instruction->OpcodeBytes[1] == Opcode); - - // Since the prefix was really an opcode extension, remove it from - // the prefix list - for (i = 0; i < Instruction->PrefixCount; i++) - { - if (Instruction->Prefixes[i]) break; - } - assert(i != Instruction->PrefixCount); - Instruction->PrefixCount--; - Instruction->Prefixes[i] = 0; - - // Slide any prefixes following the removed prefix down by 1 - memmove(&Instruction->Prefixes[i], &Instruction->Prefixes[i+1], Instruction->PrefixCount-i); - Instruction->Prefixes[Instruction->PrefixCount] = 0; - Instruction->Repeat = FALSE; - X86Instruction->HasRepeatWhileEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE; - X86Instruction->HasOperandSizePrefix = FALSE; - if (SSE_Prefix == PREFIX_OPERAND_SIZE) - { - if (IS_AMD64() && X86Instruction->rex.w) X86Instruction->OperandSize = 8; - else X86Instruction->OperandSize = 4; - } - - if (IS_X86_16()) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: SSE invalid in 16-bit mode\n", VIRTUAL_ADDRESS); - goto abort; - } - - assert(X86Instruction->HasModRM); - switch (SSE_Prefix) - { - case PREFIX_OPERAND_SIZE: X86Opcode = &X86_SSE[0x000+Opcode]; break; - case PREFIX_REPNE: X86Opcode = &X86_SSE[0x100+Opcode]; break; - case PREFIX_REP: X86Opcode = &X86_SSE[0x200+Opcode]; break; - } - - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal SSE instruction opcode 0x%02X 0x%02X + prefix 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Instruction->OpcodeBytes[2]); - goto abort; - } - else if (X86_EXTENDED_OPCODE(X86Opcode)) - { - // SSE in group (13, 14, or 15) - OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b); - Group = X86_Groups_2[Opcode]; - X86Instruction->Group = (U8)Group; - assert(Group >= 13 && Group <= 15 && X86Opcode->Table); - switch (SSE_Prefix) - { - case PREFIX_OPERAND_SIZE: X86Opcode = &X86Opcode->Table[0x00+OpcodeExtension]; break; - case PREFIX_REPNE: X86Opcode = &X86Opcode->Table[0x08+OpcodeExtension]; break; - case PREFIX_REP: X86Opcode = &X86Opcode->Table[0x10+OpcodeExtension]; break; - } - - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal SSE instruction opcode 0x%02X 0x%02X + prefix 0x%02X + extension %d\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Instruction->OpcodeBytes[2], OpcodeExtension); - goto abort; - } - } - - Instruction->Repeat = FALSE; - X86Instruction->HasRepeatWhileEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE; - X86Instruction->HasOperandSizePrefix = FALSE; - switch (X86_GET_CATEGORY(X86Opcode)) - { - case ITYPE_SSE: case ITYPE_SSE2: case ITYPE_SSE3: break; - default: assert(0); goto abort; - } - } - else if (X86_EXTENDED_OPCODE(X86Opcode)) // 2 byte group - { - assert(!X86Opcode->MnemonicFlags); - OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b); - - assert(X86Opcode->Table); - X86Opcode = &X86Opcode->Table[OpcodeExtension]; - if (X86_INVALID(X86Opcode)) - { - Instruction->Length++; - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension); - goto abort; - } - - assert(!X86_SPECIAL_EXTENSION(X86Opcode)); - Group = X86_Groups_2[Opcode]; - X86Instruction->Group = (U8)Group; - assert(Group > 0 && Group <= 19); - assert(X86Opcode->Mnemonic); - DISASM_OUTPUT(("[0x%08I64X] Group %d (bytes 0x%02X 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension, X86Opcode->Mnemonic)); - } - else - { - assert(X86Opcode->Mnemonic); - DISASM_OUTPUT(("[0x%08I64X] Two byte opcode 0x%02X 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic)); - X86Instruction->HasModRM = X86_ModRM_2[Opcode]; - if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address; - } - } - else // 1-byte opcode - { - if (X86Instruction->AddressSize == 8) - { - if (X86_Invalid_Addr64_1[Opcode]) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X (\"%s\") illegal in 64-bit mode\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic); - goto abort; - } - -#if 0 - if (X86Instruction->rex_b && - (GET_REX_B(X86Instruction->rex_b) && !GET_REX_B(X86_REX_1[Opcode]) || - GET_REX_X(X86Instruction->rex_b) && !GET_REX_X(X86_REX_1[Opcode]) || - GET_REX_R(X86Instruction->rex_b) && !GET_REX_R(X86_REX_1[Opcode]) || - GET_REX_W(X86Instruction->rex_b) && !GET_REX_W(X86_REX_1[Opcode]))) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal REX prefix 0x%02X for opcode 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->rex_b, Opcode); - assert(0); - goto abort; - } -#endif - } - - if (X86Instruction->OperandSize == 2 && X86_Invalid_Op16_1[Opcode]) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X (\"%s\") illegal with 16-bit operand size\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic); - goto abort; - } - - Instruction->OpcodeBytes[0] = Opcode; - Instruction->OpcodeLength = 1; - X86Instruction->HasModRM = X86_ModRM_1[Opcode]; - if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address; - - if (X86_EXTENDED_OPCODE(X86Opcode)) // a group - { - assert(X86Instruction->HasModRM); - OpcodeExtension = GET_MODRM_EXT(*Address); // leave Address pointing at ModRM byte - - if (X86_SPECIAL_EXTENSION(X86Opcode)) - { - DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode)); - SpecialExtension = TRUE; - goto HasSpecialExtension; - } - - assert(X86Opcode->Table); - X86Opcode = &X86Opcode->Table[OpcodeExtension]; - if (X86_INVALID(X86Opcode)) - { - Instruction->Length++; - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, Opcode, OpcodeExtension); - goto abort; - } - - Group = X86_Groups_1[Opcode]; - X86Instruction->Group = (U8)Group; - DISASM_OUTPUT(("[0x%08I64X] Group %d (byte 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, Opcode, OpcodeExtension, X86Opcode->Mnemonic)); - assert(Group > 0 && Group <= 17); - assert(X86Opcode->Mnemonic); - } - else - { - if (X86_SPECIAL_EXTENSION(X86Opcode)) - { - DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X\n", VIRTUAL_ADDRESS, Opcode)); - SpecialExtension = TRUE; - goto HasSpecialExtension; - } - - DISASM_OUTPUT(("[0x%08I64X] One byte opcode 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic)); - } - } - -HasSpecialExtension: - if (SpecialExtension) - { - if (X86Opcode->MnemonicFlags & ITYPE_EXT_MODRM) - { - assert(X86Opcode->Table); - assert(Instruction->OpcodeLength == 2); - assert(X86Instruction->HasModRM); - X86Opcode = &X86Opcode->Table[*Address]; - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal opcode 0x%02X 0x%02X + modrm 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], *Address); - goto abort; - } - else if (X86_EXTENDED_OPCODE(X86Opcode)) - { - assert(!X86Opcode->MnemonicFlags); - OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b); - - assert(X86Opcode->Table); - X86Opcode = &X86Opcode->Table[OpcodeExtension]; - if (X86_INVALID(X86Opcode)) - { - Instruction->Length++; - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension); - goto abort; - } - - assert(!X86_SPECIAL_EXTENSION(X86Opcode)); - Group = X86_Groups_2[Opcode]; - X86Instruction->Group = (U8)Group; - assert(Group > 0 && Group <= 19); - assert(X86Opcode->Mnemonic); - DISASM_OUTPUT(("[0x%08I64X] Group %d (bytes 0x%02X 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension, X86Opcode->Mnemonic)); - } - else if (!X86_OPERAND_COUNT(X86Opcode)) - { - INSTR_INC(1); // increment Instruction->Length and address - } - } - else if (X86Opcode->MnemonicFlags & ITYPE_EXT_FPU) - { - assert(X86Opcode->Table); - if (X86Instruction->modrm_b < 0xC0) - { - // It is an opcode extension, use the X86Opcode->Table - OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b); - X86Opcode = &X86Opcode->Table[OpcodeExtension]; - } - else - { - // The whole ModRM byte is used, these start at index 0x08 in X86Opcode->Table - OpcodeExtension = (X86Instruction->modrm_b & 0x3F); - X86Opcode = &X86Opcode->Table[0x08 + OpcodeExtension]; - } - - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid FPU opcode 0x%02X + modrm extension 0x%02X (index 0x%02X)\n", VIRTUAL_ADDRESS, Opcode, X86Instruction->modrm_b, 0x08 + OpcodeExtension); - goto abort; - } - - DISASM_OUTPUT(("[0x%08I64X] FPU instruction is (\"%s\"): 0x%02X + modrm 0x%02X (index 0x%02X)\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Opcode, X86Instruction->modrm_b, 0x08 + OpcodeExtension)); - if (!X86_OPERAND_COUNT(X86Opcode)) INSTR_INC(1); // increment Instruction->Length and address - } - else if (X86Opcode->MnemonicFlags & ITYPE_EXT_SUFFIX) - { - if (X86Instruction->HasOperandSizePrefix) - { - if (!Instruction->AnomalyOccurred && X86Opcode->Table == X86_3DNOW_0F) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: operand size prefix used with 3DNOW instruction\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasOperandSizePrefix = FALSE; - X86Instruction->OperandSize = 4; - } - Instruction->OperandCount = X86_OPERAND_COUNT(X86Opcode); - assert(Instruction->OpcodeLength == 2 && X86Instruction->HasModRM && Instruction->OperandCount == 2); - memcpy(&X86Instruction->Opcode, X86Opcode, sizeof(X86_OPCODE)); - Instruction->Operands[0].Flags = X86Opcode->OperandFlags[0] & X86_OPFLAGS_MASK; - Instruction->Operands[1].Flags = X86Opcode->OperandFlags[1] & X86_OPFLAGS_MASK; - Instruction->Operands[2].Flags = X86Opcode->OperandFlags[2] & X86_OPFLAGS_MASK; - assert(Address == Instruction->Address + Instruction->Length); - if (!SetOperands(Instruction, Address, Flags & DISASM_SUPPRESSERRORS)) goto abort; - Suffix = Instruction->Address[Instruction->Length++]; - Instruction->OpcodeBytes[2] = Suffix; - Instruction->OpcodeLength = 3; - X86Opcode = &X86Opcode->Table[Suffix]; - - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal opcode 0x%02X 0x%02X + suffix 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Suffix); - goto abort; - } - assert(Instruction->Length >= 4 + Instruction->PrefixCount); - } - else if (X86Opcode->MnemonicFlags & ITYPE_EXT_64) - { - assert(X86Opcode->Table); - if (IS_AMD64()) X86Opcode = &X86Opcode->Table[1]; - else X86Opcode = &X86Opcode->Table[0]; - assert(!X86_INVALID(X86Opcode)); - } - } - - // Detect incompatibilities - if (IS_X86_16() && X86Opcode->CPU > CPU_I386) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Instruction \"%s\" (opcode 0x%02X) can't be used in 16-bit X86\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->LastOpcode); - goto abort; - } - if (!IS_AMD64() && X86Opcode->CPU >= CPU_AMD64) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Instruction \"%s\" (opcode 0x%02X) can only be used in X86-64\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->LastOpcode); - goto abort; - } - - // Copy the opcode into the local structure and set the fields - assert(Instruction->OpcodeLength && !X86_INVALID(X86Opcode)); - memcpy(&X86Instruction->Opcode, X86Opcode, sizeof(X86_OPCODE)); - Instruction->Groups |= X86_GET_CATEGORY(X86Opcode); - assert(Instruction->Groups); - Instruction->Type |= X86_GET_TYPE(X86Opcode); - assert((U32)Instruction->Type >= Instruction->Groups); - Instruction->OperandCount = X86_OPERAND_COUNT(X86Opcode); - - // - // Sanity check prefixes now that opcode is known and prefixes are resolved - // - - // Instructions that implicitly reference the CS/DS can't have segment override prefixes - switch (Instruction->Type) - { - case ITYPE_PUSHF: case ITYPE_POPF: - case ITYPE_ENTER: case ITYPE_LEAVE: - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSegmentOverridePrefix = FALSE; - X86Instruction->Segment = SEG_SS; - break; - case ITYPE_RET: case ITYPE_DEBUG: - case ITYPE_OFLOW: case ITYPE_TRAP: - case ITYPE_TRAPRET: - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSegmentOverridePrefix = FALSE; - X86Instruction->Segment = SEG_CS; - break; - } - - // Check illegal prefixes used with FPU/MMX/SSEx - if (Instruction->Groups & (ITYPE_FPU|ITYPE_MMX|ITYPE_SSE|ITYPE_SSE2|ITYPE_SSE3)) - { - // Check for prefixes that produce unpredictable results - for (i = 0; i < Instruction->PrefixCount; i++) - { - switch (Instruction->Prefixes[i]) - { - case PREFIX_OPERAND_SIZE: - switch (Instruction->Type) - { - case ITYPE_FSTOREENV: case ITYPE_FLOADENV: case ITYPE_FSAVE: case ITYPE_FRESTORE: continue; - default: break; - } - - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: operand size prefix used with FPU/MMX/SSEx\n", VIRTUAL_ADDRESS); - goto abort; - } - X86Instruction->HasOperandSizePrefix = FALSE; - if (X86Instruction->OperandSize == 2) X86Instruction->OperandSize = 2; - break; - - case PREFIX_REPNE: - case PREFIX_REP: - if (Instruction->Groups & ITYPE_FPU) { assert(Instruction->Repeat); continue; } - // The Intel manual says this results in unpredictable behavior -- it's not even - // clear which SSE prefix is used as the third opcode byte in this case - // (e.g., is it the first or last SSE prefix?) - if (!SuppressErrors) printf("[0x%08I64X] ERROR: rep/repne used with MMX/SSEx\n", VIRTUAL_ADDRESS); - goto abort; - - default: - break; - } - } - } - - // Check for conflicts involving operand size - if (IS_AMD64()) - { - // Check for use of rex.w=1 with an operand size prefix - if (X86Instruction->rex.w) - { - assert(X86Instruction->OperandSize == 8); - for (i = 0; i < Instruction->PrefixCount; i++) - { - if (Instruction->Prefixes[i] == PREFIX_OPERAND_SIZE) - { - X86Instruction->HasOperandSizePrefix = FALSE; - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of operand size prefix meaningless when REX.w=1\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - } - } - } - - // Set default operand size to 64 instead of 32 for some instructions - switch (Instruction->Type) - { - case ITYPE_PUSH: case ITYPE_POP: - case ITYPE_PUSHF: case ITYPE_POPF: - case ITYPE_ENTER: case ITYPE_LEAVE: - case ITYPE_CALL: case ITYPE_BRANCH: - case ITYPE_LOOPCC: case ITYPE_RET: - X86Instruction->HasDefault64Operand = TRUE; - break; - - case ITYPE_SYSTEM: - if (Instruction->OpcodeLength != 2) break; - - // lgdt/lidt/lldt/ltr - if ((Instruction->LastOpcode == 0x00 || Instruction->LastOpcode == 0x01) && - (OpcodeExtension == 0x02 || OpcodeExtension == 0x03)) - { - X86Instruction->HasDefault64Operand = TRUE; - } - break; - - default: - break; - } - - if (X86Instruction->HasDefault64Operand) - { - if (X86Instruction->rex.w) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of REX.w is meaningless (default operand size is 64)\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->rex_b &= ~8; - X86Instruction->rex.w = 0; - } - - if (X86Instruction->HasOperandSizePrefix) - { - assert(X86Instruction->OperandSize == 2); - X86Instruction->HasDefault64Operand = FALSE; - } - else - { - assert(X86Instruction->OperandSize >= 4); - X86Instruction->OperandSize = 8; - } - } - } - - // Make sure rep/repe/repne is set correctly based on instruction - if (Instruction->Repeat) - { - switch (Instruction->Type) - { - case ITYPE_IN: - case ITYPE_OUT: - case ITYPE_STRMOV: - case ITYPE_STRSTOR: - case ITYPE_STRLOAD: - if (X86Instruction->HasRepeatWhileNotEqualPrefix) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: REPNE should only be used with cmps/scas\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - // Treat it as just a "rep" - X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileEqualPrefix = TRUE; - } - break; - case ITYPE_STRCMP: - break; - default: - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Repeat prefix used with non-string instruction\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - Instruction->Repeat = FALSE; - X86Instruction->HasRepeatWhileEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE; - break; - } - } - - if (Disassemble) - { - assert(!Instruction->StringIndex); - if (X86Instruction->HasRepeatWhileEqualPrefix) - { - if (Instruction->Type == ITYPE_STRCMP) { APPENDS("repe "); } - else { APPENDS("rep "); } - } - if (X86Instruction->HasRepeatWhileNotEqualPrefix) APPENDS("repne "); - if (X86Instruction->HasLockPrefix) APPENDS("lock "); - if (X86Instruction->HasBranchTakenPrefix) APPENDS("hinttake "); - if (X86Instruction->HasBranchNotTakenPrefix) APPENDS("hintskip "); - APPENDPAD(12); - APPEND(OPCSTR, SIZE_LEFT, "%s", X86Opcode->Mnemonic); - APPENDPAD(24); - } - - if (Instruction->OperandCount) - { - Instruction->Operands[0].Flags = X86Opcode->OperandFlags[0] & X86_OPFLAGS_MASK; - Instruction->Operands[1].Flags = X86Opcode->OperandFlags[1] & X86_OPFLAGS_MASK; - Instruction->Operands[2].Flags = X86Opcode->OperandFlags[2] & X86_OPFLAGS_MASK; - Address = SetOperands(Instruction, Address, Flags); - if (!Address) goto abort; - assert(!(Instruction->Operands[0].Flags & 0x7F)); - assert(!(Instruction->Operands[1].Flags & 0x7F)); - assert(!(Instruction->Operands[2].Flags & 0x7F)); - } - - Disassembler->Stage2Count++; - -#ifdef TEST_DISASM - ////////////////////////////////////////////////////////////////////// - // Test against other disassemblers - ////////////////////////////////////////////////////////////////////// - - if (IS_X86_32()) - { - InstructionLength = X86_GetLength(Instruction, Instruction->Address); - if (InstructionLength && Instruction->Length != InstructionLength) - { - printf("[0x%08I64X] WARNING: instruction lengths differ (%d vs %d)\n", VIRTUAL_ADDRESS, Instruction->Length, InstructionLength); - DumpInstruction(Instruction, TRUE, TRUE); - assert(0); - } - } - else if (IS_AMD64()) - { - // TODO: need other amd64 (x86-64) disassembler to test against - } - else if (IS_X86_16()) - { - // TODO: need other x86 16-bit disassembler to test against - } -#endif - - ////////////////////////////////////////////////////////////////////// - // Post-operand sanity checks - ////////////////////////////////////////////////////////////////////// - - if (!X86Instruction->HasDstAddressing && !X86Instruction->HasSrcAddressing) - { - if (X86Instruction->HasAddressSizePrefix) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: address size prefix used with no addressing\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasAddressSizePrefix = FALSE; - } - - if (X86Instruction->HasSegmentOverridePrefix) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: segment override used with no addressing\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasSegmentOverridePrefix = FALSE; - } - } - - // Detect use of unusual segments - if (!Instruction->AnomalyOccurred && !IS_X86_16()) - { - switch (X86Instruction->Segment) - { - case SEG_CS: case SEG_DS: case SEG_SS: - break; - case SEG_ES: - switch (Instruction->Type) - { - case ITYPE_IN: case ITYPE_STRMOV: case ITYPE_STRCMP: case ITYPE_STRSTOR: - break; - default: - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment ES\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - break; - } - break; - case SEG_FS: - if (IS_X86_32() && !(Instruction->Groups & ITYPE_EXEC)) break; - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment FS\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - break; - case SEG_GS: - if (IS_AMD64() && !(Instruction->Groups & ITYPE_EXEC)) break; - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment GS\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - break; - default: - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: unexpected segment 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->Selector); - Instruction->AnomalyOccurred = TRUE; - break; - } - } - - if ((X86Opcode->OperandFlags[0] & OP_COND_EXEC) == OP_COND_EXEC) - { - assert(Instruction->Type == ITYPE_BRANCHCC || Instruction->Type == ITYPE_LOOPCC); - for (i = 0; i < Instruction->PrefixCount; i++) - { - switch (Instruction->Prefixes[i]) - { - case PREFIX_BRANCH_NOT_TAKEN: - if (!Instruction->AnomalyOccurred && X86Instruction->Segment != SEG_CS) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used with conditional branch\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasSegmentOverridePrefix = FALSE; - X86Instruction->Segment = SEG_CS; - X86Instruction->HasBranchNotTakenPrefix = TRUE; - break; - case PREFIX_BRANCH_TAKEN: - if (!Instruction->AnomalyOccurred && X86Instruction->Segment != SEG_DS) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used with conditional branch\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasSegmentOverridePrefix = FALSE; - X86Instruction->Segment = SEG_CS; - X86Instruction->HasBranchTakenPrefix = TRUE; - break; - } - } - } - - // - // If lock prefix is enabled, verify it is valid - // - if (X86Instruction->HasLockPrefix && - !IsValidLockPrefix(X86Instruction, Opcode, Instruction->OpcodeLength, Group, OpcodeExtension)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal use of lock prefix for instruction \"%s\"\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic); - goto abort; - } - - ////////////////////////////////////////////////////////////////////// - // Generate disassembly output - ////////////////////////////////////////////////////////////////////// - - if (Disassemble) - { - if ((Flags & DISASM_SHOWFLAGS) && - (X86Instruction->Opcode.Preconditions || X86Instruction->Opcode.FlagsChanged || X86Instruction->Opcode.ResultsIfTrue)) - { - APPENDPAD(124); - if (X86Instruction->Opcode.Preconditions) - { - Result = X86Instruction->Opcode.Preconditions; - APPENDS("COND:{ "); - if (Result & COND_L) APPENDS("L "); - if (Result & COND_NL) APPENDS("NL "); - if (Result & COND_LE) APPENDS("LE "); - if (Result & COND_NLE) APPENDS("NLE "); - if (Result & COND_G) APPENDS("G "); - if (Result & COND_NG) APPENDS("NG "); - if (Result & COND_GE) APPENDS("GE "); - if (Result & COND_NGE) APPENDS("NGE "); - if (Result & COND_A) APPENDS("A "); - if (Result & COND_NA) APPENDS("NA "); - if (Result & COND_AE) APPENDS("AE "); - if (Result & COND_NAE) APPENDS("NAE "); - if (Result & COND_B) APPENDS("B "); - if (Result & COND_NB) APPENDS("NB "); - if (Result & COND_BE) APPENDS("BE "); - if (Result & COND_NBE) APPENDS("NBE "); - if (Result & COND_E) APPENDS("E "); - if (Result & COND_NE) APPENDS("NE "); - if (Result & COND_C) APPENDS("C "); - if (Result & COND_NC) APPENDS("NC "); - if (Result & COND_Z) APPENDS("Z "); - if (Result & COND_NZ) APPENDS("NZ "); - if (Result & COND_P) APPENDS("P "); - if (Result & COND_NP) APPENDS("NP "); - if (Result & COND_PE) APPENDS("PE "); - if (Result & COND_PO) APPENDS("PO "); - if (Result & COND_O) APPENDS("O "); - if (Result & COND_NO) APPENDS("NO "); - if (Result & COND_U) APPENDS("U "); - if (Result & COND_NU) APPENDS("NU "); - if (Result & COND_S) APPENDS("S "); - if (Result & COND_NS) APPENDS("NS "); - if (Result & COND_D) APPENDS("D "); - APPENDB('}'); - } - - if (X86Instruction->Opcode.FlagsChanged) - { - Result = X86Instruction->Opcode.FlagsChanged; - - if (Result & FLAG_SET_MASK) - { - APPENDS("SET:{ "); - if (Result & FLAG_CF_SET) APPENDS("C "); - if (Result & FLAG_DF_SET) APPENDS("D "); - if (Result & FLAG_IF_SET) APPENDS("I "); - APPENDB('}'); - } - - if (Result & FLAG_CLR_MASK) - { - APPENDS("CLR:{ "); - if (Result & FLAG_SF_CLR) APPENDS("S "); - if (Result & FLAG_ZF_CLR) APPENDS("Z "); - if (Result & FLAG_AF_CLR) APPENDS("A "); - if (Result & FLAG_CF_CLR) APPENDS("C "); - if (Result & FLAG_DF_CLR) APPENDS("D "); - if (Result & FLAG_IF_CLR) APPENDS("I "); - if (Result & FLAG_OF_CLR) APPENDS("O "); - if ((Result & FPU_ALL_CLR) == FPU_ALL_CLR) - { - APPENDS("FPU_ALL "); - } - else - { - if (Result & FPU_C0_CLR) APPENDS("FPU_C0 "); - if (Result & FPU_C1_CLR) APPENDS("FPU_C1 "); - if (Result & FPU_C2_CLR) APPENDS("FPU_C2 "); - if (Result & FPU_C3_CLR) APPENDS("FPU_C3 "); - } - APPENDB('}'); - } - - if ((Result & FLAG_MOD_MASK) == FLAG_MOD_MASK) - { - APPENDS("MOD:{ "); - if ((Result & FLAG_ALL_MOD) == FLAG_ALL_MOD) - { - APPENDS("FLAGS_ALL "); - } - else if ((Result & FLAG_COMMON_MOD) == FLAG_COMMON_MOD) - { - APPENDS("FLAGS_COMMON "); - } - else - { - if (Result & FLAG_OF_MOD) APPENDS("O "); - if (Result & FLAG_SF_MOD) APPENDS("S "); - if (Result & FLAG_ZF_MOD) APPENDS("Z "); - if (Result & FLAG_AF_MOD) APPENDS("A "); - if (Result & FLAG_PF_MOD) APPENDS("P "); - if (Result & FLAG_CF_MOD) APPENDS("C "); - if (Result & FLAG_DF_MOD) APPENDS("D "); - if (Result & FLAG_IF_MOD) APPENDS("I "); - } - if ((Result & FPU_ALL_MOD) == FPU_ALL_MOD) - { - APPENDS("FPU_ALL "); - } - else - { - if (Result & FPU_C0_MOD) APPENDS("FPU_C0 "); - if (Result & FPU_C1_MOD) APPENDS("FPU_C1 "); - if (Result & FPU_C2_MOD) APPENDS("FPU_C2 "); - if (Result & FPU_C3_MOD) APPENDS("FPU_C3 "); - } - APPENDB('}'); - } - - if (Result & FLAG_TOG_MASK) - { - APPENDS("TOG:{ "); - if (Result & FLAG_CF_TOG) APPENDS("C "); - APPENDB('}'); - } - } - } - - APPENDS("\n"); - } - else - { - Instruction->String[0] = '\0'; - } - - if (!Instruction->Length || Instruction->Length > X86_MAX_INSTRUCTION_LEN) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: maximum instruction length reached (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - - if (!Decode) - { - Disassembler->Stage3CountNoDecode++; - return TRUE; // all work is done - } - - ////////////////////////////////////////////////////////////////////// - // Detect particularly interesting intructions - ////////////////////////////////////////////////////////////////////// - - Operand1 = &Instruction->Operands[0]; - if (Instruction->Groups & ITYPE_EXEC) - { - // If it is a negative offset with a 1-byte or 2-byte offset, assume it is a loop - if (Operand1->Type == OPTYPE_OFFSET && - Operand1->Length <= 2 && X86Instruction->Displacement < 0) - { - Instruction->CodeBranch.IsLoop = TRUE; - Instruction->CodeBranch.Operand = Operand1; - } - - if (!Instruction->AnomalyOccurred && - Operand1->TargetAddress >= (U64)Instruction->Address && - Operand1->TargetAddress < (U64)Instruction->Address + Instruction->Length) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: branch into the middle of an instruction\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - - switch (Instruction->Type) - { - case ITYPE_BRANCH: - Operand1->Flags |= OP_ADDRESS; - assert(Instruction->OperandCount == 1); - if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR))) - { - assert(!X86Instruction->HasSelector); - X86Instruction->Segment = SEG_CS; - } - - if (Operand1->TargetAddress) - { - assert(!Instruction->CodeBranch.AddressOffset); - Instruction->CodeBranch.Count = 1; - Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress; - Instruction->CodeBranch.Operand = Operand1; - } - // If there is both a base and index register, the Result will probably be too wrong - // to even guess - else if (X86Instruction->HasFullDisplacement && - ((X86Instruction->HasBaseRegister && !X86Instruction->HasIndexRegister) || - (!X86Instruction->HasBaseRegister && X86Instruction->HasIndexRegister))) - { - assert(Operand1->Length <= 0xFF); - if (!X86Instruction->Scale) - { - if (Operand1->Length) X86Instruction->Scale = (U8)Operand1->Length; - else X86Instruction->Scale = X86Instruction->OperandSize; - } - assert(Operand1->Length <= 0xFF); - tmpScale = MAX(X86Instruction->Scale, Operand1->Length); - - assert(tmpScale <= 16); - Instruction->CodeBranch.AddressOffset = (U8)tmpScale; - for (i = 0; i < MAX_CODE_REFERENCE_COUNT; i++) Instruction->CodeBranch.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale); - Instruction->CodeBranch.Count = i; - Instruction->CodeBranch.IsIndirect = TRUE; - Instruction->CodeBranch.Operand = Operand1; - } - break; - - case ITYPE_CALL: - Instruction->Groups |= ITYPE_STACK; - Instruction->CodeBranch.IsCall = TRUE; - Operand1->Flags |= OP_ADDRESS; - assert(Instruction->OperandCount == 1); - if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR))) - { - assert(!X86Instruction->HasSelector); - X86Instruction->Segment = SEG_CS; - } - - if (Operand1->TargetAddress) - { - assert(!Instruction->CodeBranch.AddressOffset); - Instruction->CodeBranch.Count = 1; - Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress; - Instruction->CodeBranch.Operand = Operand1; - } - // If there is both a base and index register, the Result will probably be too wrong - // to even guess - else if (X86Instruction->HasFullDisplacement && - ((X86Instruction->HasBaseRegister && !X86Instruction->HasIndexRegister) || - (!X86Instruction->HasBaseRegister && X86Instruction->HasIndexRegister))) - { - //DISASM_OUTPUT(("[0x%08I64X] Scale %d, displacement 0x%08I64x\n", VIRTUAL_ADDRESS, X86Instruction->Scale, X86Instruction->Displacement)); - if (!X86Instruction->Scale) - { - assert(Operand1->Length <= 0xFF); - if (Operand1->Length) X86Instruction->Scale = (U8)Operand1->Length; - else X86Instruction->Scale = X86Instruction->OperandSize; - } - tmpScale = MAX(X86Instruction->Scale, Operand1->Length); - - assert(tmpScale <= 16); - Instruction->CodeBranch.AddressOffset = (U8)tmpScale; - assert(X86Instruction->Scale > 1); - for (i = 0; i < MAX_CODE_REFERENCE_COUNT; i++) Instruction->CodeBranch.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale); - Instruction->CodeBranch.Count = i; - Instruction->CodeBranch.IsIndirect = TRUE; - Instruction->CodeBranch.Operand = Operand1; - } - break; - - case ITYPE_BRANCHCC: - assert(Instruction->OperandCount == 1); - assert(Operand1->Flags & OP_ADDRESS); - assert(Operand1->Type == OPTYPE_OFFSET); - if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR))) - { - assert(!X86Instruction->HasSelector); - X86Instruction->Segment = SEG_CS; - } - - if (Operand1->TargetAddress) - { - assert(!Instruction->CodeBranch.AddressOffset); - Instruction->CodeBranch.Count = 2; - Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress; - Instruction->CodeBranch.Addresses[1] = (U64)Instruction->Address + Instruction->Length; - Instruction->CodeBranch.Operand = Operand1; - } - break; - - case ITYPE_LOOPCC: - Instruction->CodeBranch.IsLoop = TRUE; - assert(Instruction->OperandCount == 1); - assert(Operand1->Flags & OP_ADDRESS); - assert(Operand1->Type == OPTYPE_OFFSET); - assert(!(Operand1->Flags & (OP_GLOBAL|OP_FAR))); - if (Operand1->TargetAddress) - { - assert(!Instruction->CodeBranch.AddressOffset); - Instruction->CodeBranch.Count = 2; - Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress; - Instruction->CodeBranch.Addresses[1] = (U64)Instruction->Address + Instruction->Length; - Instruction->CodeBranch.Operand = Operand1; - } - break; - - case ITYPE_RET: - Instruction->Groups |= ITYPE_STACK; - break; - - default: - break; // do nothing - } - } - else // possible data instruction - { - for (i = 0, Operand = Instruction->Operands; i < Instruction->OperandCount; i++, Operand++) - { - if (Operand->TargetAddress) - { - if (Operand->Flags & OP_DST) - { - assert(!Instruction->DataDst.Count); - Instruction->DataDst.Count = 1; - Instruction->DataDst.Addresses[0] = Operand->TargetAddress; - Instruction->DataDst.DataSize = Operand->Length; - Instruction->DataDst.Operand = Operand; - DISASM_OUTPUT(("[0x%08I64X] Write of size %d to 0x%04I64X\n", VIRTUAL_ADDRESS, Operand->Length, Operand->TargetAddress)); - } - if (Operand->Flags & OP_SRC) - { - assert(!Instruction->DataSrc.Count); - Instruction->DataSrc.Count = 1; - Instruction->DataSrc.Addresses[0] = Operand->TargetAddress; - Instruction->DataSrc.DataSize = Operand->Length; - Instruction->DataSrc.Operand = Operand; - DISASM_OUTPUT(("[0x%08I64X] Read of size %d to 0x%04I64X\n", VIRTUAL_ADDRESS, Operand->Length, Operand->TargetAddress)); - } - } - - // If there is both a base and index register, the Result will probably be too wrong - // to even guess - else if (Operand->Flags & OP_GLOBAL && - ((X86Instruction->HasBaseRegister && !X86Instruction->HasIndexRegister) || - (!X86Instruction->HasBaseRegister && X86Instruction->HasIndexRegister))) - { - DISASM_OUTPUT(("[0x%08I64X] Data reference (scale %d, size %d, displacement 0x%08I64x)\n", VIRTUAL_ADDRESS, X86Instruction->Scale, Operand->Length, X86Instruction->Displacement)); - if (!X86Instruction->Scale) - { - assert(Operand->Length <= 0xFF); - if (Operand->Length) X86Instruction->Scale = (U8)Operand->Length; - else X86Instruction->Scale = X86Instruction->OperandSize; - } - tmpScale = MAX(X86Instruction->Scale, Operand->Length); - - assert(X86Instruction->HasFullDisplacement); - if (Operand->Flags & OP_DST) - { - assert(!Instruction->DataDst.Count); - assert(tmpScale <= 16); - Instruction->CodeBranch.AddressOffset = (U8)tmpScale; - for (i = 0; i < MAX_DATA_REFERENCE_COUNT; i++) Instruction->DataDst.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale); - Instruction->DataDst.Count = i; - Instruction->DataDst.DataSize = Operand->Length; - Instruction->DataDst.Operand = Operand; - } - if (Operand->Flags & OP_SRC) - { - assert(!Instruction->DataSrc.Count); - assert(tmpScale <= 16); - Instruction->CodeBranch.AddressOffset = (U8)tmpScale; - for (i = 0; i < MAX_DATA_REFERENCE_COUNT; i++) Instruction->DataSrc.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale); - Instruction->DataSrc.Count = i; - Instruction->DataSrc.DataSize = Operand->Length; - Instruction->DataSrc.Operand = Operand; - } - } - } - } - - if (Instruction->Groups & ITYPE_STACK) - { - switch (Instruction->Type) - { - case ITYPE_PUSH: - assert(Instruction->OperandCount == 1 && Operand1->Length); - Instruction->StackChange = -Operand1->Length; - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_POP: - assert(Instruction->OperandCount == 1 && Operand1->Length); - Instruction->StackChange = Operand1->Length; - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_PUSHA: - Instruction->StackChange = -(X86Instruction->OperandSize * 8); // xAX, xCX, xDX, xBX, xBP, xSP, xSI, xDI - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_POPA: - Instruction->StackChange = X86Instruction->OperandSize * 8; // xDI, xSI, xSP, xBP, xBX, xDX, xCX, xAX - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_PUSHF: - Instruction->StackChange = -Operand1->Length; - Instruction->NeedsEmulation = TRUE; - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_POPF: - Instruction->StackChange = Operand1->Length; - Instruction->NeedsEmulation = TRUE; - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_ENTER: - if (!Instruction->AnomalyOccurred) - { - if (Instruction->Operands[1].Value_U64 & 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ENTER has invalid operand 2\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - if (Instruction->Operands[2].Value_U64 & ~0x1F) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ENTER has invalid operand 3\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - } - SANITY_CHECK_ADDRESS_SIZE(); - Instruction->Operands[2].Value_U64 &= 0x1F; - - // frame pointer + stack space - i = Operand1->Length + (U32)Instruction->Operands[1].Value_U64; - Instruction->StackChange = -((LONG)i); - i = (U32)Instruction->Operands[2].Value_U64 * Operand1->Length; - Instruction->StackChange -= i; - break; - - case ITYPE_LEAVE: - // This will do "mov esp, ebp; pop ebp" so the StackChange size is dynamic - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_CALL: - Instruction->StackChange = -X86Instruction->OperandSize; - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_RET: - Instruction->StackChange = X86Instruction->OperandSize; - - switch (Opcode) - { - case 0xC3: // ret with no args - break; - - case 0xC2: // ret with 1 arg - if (!Instruction->AnomalyOccurred && (Operand1->Value_U64 & 3)) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ret has invalid operand 1\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - Instruction->StackChange += (LONG)Operand1->Value_U64; - break; - - case 0xCB: // far ret with no args - Instruction->StackChange *= 2; // account for segment - Instruction->StackChange += (LONG)Operand1->Value_U64; - break; - - case 0xCA: // far ret with 1 arg - if (!Instruction->AnomalyOccurred && (Operand1->Value_U64 & 3)) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: retf has invalid operand 1\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - Instruction->StackChange *= 2; // account for segment - Instruction->StackChange += (LONG)Operand1->Value_U64; - break; - } - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_ADD: - case ITYPE_XCHGADD: - if (Instruction->Operands[1].Value_S64) Instruction->StackChange = (LONG)(Instruction->Operands[1].Value_S64); - break; - case ITYPE_SUB: - if (Instruction->Operands[1].Value_S64) Instruction->StackChange = (LONG)(-Instruction->Operands[1].Value_S64); - break; - case ITYPE_MOV: - case ITYPE_AND: - break; - - default: - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Instruction \"%s\" is modifying the stack\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic); - Instruction->AnomalyOccurred = TRUE; - } - break; - } - - if (!Instruction->AnomalyOccurred && - ((X86Instruction->OperandSize != 2 && (Instruction->StackChange & 3)) || (Instruction->StackChange & 1))) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: \"%s\" has invalid stack change 0x%02X\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->StackChange); - Instruction->AnomalyOccurred = TRUE; - } - } - - if (Instruction->Groups & ITYPE_TRAPS) - { - switch (Instruction->Type) - { - case ITYPE_TRAP: - case ITYPE_TRAPCC: - case ITYPE_TRAPRET: - case ITYPE_BOUNDS: - case ITYPE_DEBUG: - case ITYPE_TRACE: - case ITYPE_INVALID: - case ITYPE_OFLOW: - Instruction->NeedsEmulation = TRUE; - break; - default: - assert(0); - break; - } - } - - if (Instruction->Groups & ITYPE_SYSTEM) - { - switch (Instruction->Type) - { - case ITYPE_CPUID: - case ITYPE_SYSCALL: - case ITYPE_SYSCALLRET: - // This doesn't require privileges - break; - - case ITYPE_HALT: - case ITYPE_IN: - case ITYPE_OUT: - default: - Instruction->NeedsEmulation = TRUE; - break; - } - } - - Disassembler->Stage3CountWithDecode++; - return TRUE; - -abort: - if (!SuppressErrors) - { -#ifdef TEST_DISASM - printf("Dump of 0x%04I64X:\n", VIRTUAL_ADDRESS); - __try { DumpAsBytes(stdout, Instruction->Address, (ULONG_PTR)VIRTUAL_ADDRESS, 16, TRUE); } - __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {} -#endif - fflush(stdout); - } - return FALSE; -} - -// Address = address to first byte after the opcode (e.g., first byte of ModR/M byte or -// immediate value -// -// Returns the address immediately following the operand (e.g., the next operand or the -// start of the next instruction -INTERNAL U8 *SetOperands(INSTRUCTION *Instruction, U8 *Address, U32 Flags) -{ - INSTRUCTION_OPERAND *Operand; - U32 Index, OperandIndex; - S64 Displacement = 0; - U8 Register; - U32 OperandFlags, OperandType, AddressMode, Segment; - U8 Opcode; - MODRM modrm; - REX rex; - REX_MODRM rex_modrm; - X86_OPCODE *X86Opcode; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - BOOL Decode = Flags & DISASM_DECODE; - BOOL Disassemble = Flags & DISASM_DISASSEMBLE; - BOOL SuppressErrors = Flags & DISASM_SUPPRESSERRORS; - - Opcode = Instruction->LastOpcode; - X86Opcode = &X86Instruction->Opcode; - - // Setup Mod R/M byte - if (X86Instruction->HasModRM) - { - SET_MODRM(X86Instruction->modrm, X86Instruction->modrm_b); - modrm = X86Instruction->modrm; - rex = X86Instruction->rex; - SET_REX_MODRM(X86Instruction->rex_modrm, rex, modrm); - rex_modrm = X86Instruction->rex_modrm; - //DISASM_OUTPUT(("[0x%08I64X] ModRM = 0x%02X (mod=%d, reg=%d, rm=%d)\n", VIRTUAL_ADDRESS, X86Instruction->modrm_b, modrm.mod, rex_modrm.reg, rex_modrm.rm)); - INSTR_INC(1); // increment Instruction->Length and address - } - else - { - // initialize them to 0 - modrm = X86Instruction->modrm; - rex = X86Instruction->rex; - rex_modrm = X86Instruction->rex_modrm; - } - - for (OperandIndex = 0; OperandIndex < Instruction->OperandCount; OperandIndex++) - { - Operand = &Instruction->Operands[OperandIndex]; - assert(!(Operand->Flags & 0x7F)); - - OperandFlags = X86Opcode->OperandFlags[OperandIndex] & X86_OPFLAGS_MASK; - OperandType = X86Opcode->OperandFlags[OperandIndex] & X86_OPTYPE_MASK; - AddressMode = X86Opcode->OperandFlags[OperandIndex] & X86_AMODE_MASK; - if (Decode && OperandIndex != 0) APPENDS(", "); - - switch (OperandType) - { - //////////////////////////////////////////////////////////// - // Special operand types with no associated addressing mode - //////////////////////////////////////////////////////////// - - case OPTYPE_0: - if (!Decode) continue; - Operand->Value_U64 = 0; - Operand->Type = OPTYPE_IMM; - //DISASM_OUTPUT(("[SetOperand] const 0\n")); - if (Disassemble) - { - APPENDS("<0>"); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_1: - if (!Decode) continue; - Operand->Value_U64 = 1; - Operand->Type = OPTYPE_IMM; - //DISASM_OUTPUT(("[SetOperand] const 1\n")); - if (Disassemble) - { - APPENDS("<1>"); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FF: - if (!Decode) continue; - Operand->Value_U64 = 0xFF; - Operand->Type = OPTYPE_IMM; - //DISASM_OUTPUT(("[SetOperand] const 0xff\n")); - if (Disassemble) - { - APPENDS("<0xFF>"); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_TSC: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] TSC\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_CS_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] CS MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_EIP_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] EIP MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_ESP_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] ESP MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_KERNELBASE_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] KernelBase MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_STAR_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] KernelBase MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_CSTAR_MSR: - assert(!IS_AMD64()); - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] CSTAR MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_LSTAR_MSR: - assert(IS_AMD64()); - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] LSTAR MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FMASK_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] FMASK MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OP_REG: - if (!Decode) continue; - // The reg field is included in the opcode - Operand->Length = X86Instruction->OperandSize; - Register = X86_GET_REG64(Opcode); - switch (X86Instruction->OperandSize) - { - case 8: - Operand->Register = AMD64_64BIT_OFFSET + Register; - break; - case 4: - Operand->Register = X86_32BIT_OFFSET + Register; - CHECK_AMD64_REG(); - break; - case 2: - Operand->Register = X86_16BIT_OFFSET + Register; - CHECK_AMD64_REG(); - break; - case 1: - Operand->Register = X86_8BIT_OFFSET + Register; - if (X86Instruction->rex_b) CHECK_AMD64_REG(); - break; - default: - assert(0); - return NULL; - } - X86_SET_REG(Register); - - //DISASM_OUTPUT(("[SetOperand] OP_REG %s\n", X86_Registers[Operand->Register])); - if (Disassemble) - { - APPENDB('<'); APPENDS(X86_Registers[Operand->Register]); APPENDB('>'); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_REG8: - if (!Decode) continue; - // The reg field is included in the opcode - Operand->Length = 1; - Register = X86_GET_REG64(Opcode); - Operand->Register = X86_8BIT_OFFSET + Register; - CHECK_AMD64_REG(); - X86_SET_REG(Register); - - //DISASM_OUTPUT(("[SetOperand] OP_REG %s\n", X86_Registers[Operand->Register])); - if (Disassemble) - { - APPENDB('<'); APPENDS(X86_Registers[Operand->Register]); APPENDB('>'); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_REG_AL: - if (!Decode) continue; - Operand->Length = 1; - Operand->Register = X86_REG_AL; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg AL\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_CL: - if (!Decode) continue; - Operand->Length = 1; - Operand->Register = X86_REG_CL; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg CL\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_AH: - if (!Decode) continue; - Operand->Length = 1; - Operand->Register = X86_REG_AH; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg AH\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_AX: - if (!Decode) continue; - Operand->Length = 2; - Operand->Register = X86_REG_AX; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg AX\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_DX: - if (!Decode) continue; - Operand->Length = 2; - Operand->Register = X86_REG_DX; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg DX\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_ECX: - if (!Decode) continue; - Operand->Length = 4; - Operand->Register = X86_REG_ECX; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg ECX\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_REG_xBP: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize; - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = AMD64_REG_RBP; break; - case 4: Operand->Register = X86_REG_EBP; break; - case 2: Operand->Register = X86_REG_BP; break; - default: assert(0); return NULL; - } - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] xAX_BIG (size = %d)\n", Operand->Length)); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_REG_xAX_BIG: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize; - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = AMD64_REG_RAX; break; - case 4: Operand->Register = X86_REG_EAX; break; - case 2: Operand->Register = X86_REG_AX; break; - default: assert(0); return NULL; - } - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] xAX_BIG (size = %d)\n", Operand->Length)); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_xAX_SMALL: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize >> 1; - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = X86_REG_EAX; break; - case 4: Operand->Register = X86_REG_AX; break; - case 2: Operand->Register = X86_REG_AL; break; - default: assert(0); return NULL; - } - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] xAX_SMALL (size = %d)\n", Operand->Length)); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_xCX_HI_xBX_LO: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize << 1; - if (Disassemble) - { - switch (X86Instruction->OperandSize) - { - case 8: APPENDS(""); break; - case 4: APPENDS(""); break; - case 2: APPENDS(""); break; - default: assert(0); return NULL; - } - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] xCX_BIG:xBX_BIG (size = %d)\n", Operand->Length)); - continue; - case OPTYPE_xDX_HI_xAX_LO: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize << 1; - if (Disassemble) - { - switch (X86Instruction->OperandSize) - { - case 8: APPENDS(""); break; - case 4: APPENDS(""); break; - case 2: APPENDS(""); break; - default: assert(0); return NULL; - } - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] xDX_BIG:xAX_BIG (size = %d)\n", Operand->Length)); - continue; - - case OPTYPE_EDX_HI_EAX_LO: - if (!Decode) continue; - Operand->Length = 8; - //DISASM_OUTPUT(("[SetOperand] EDX:EAX\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_EDX_ECX_EBX_EAX: - Operand->Length = 32; - //DISASM_OUTPUT(("[SetOperand] EDX:ECX:EBX:EAX\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_FLAGS: - if (!Decode) continue; - Operand->Length = 2; - Operand->Flags |= OP_REG; - Operand->Register = X86_REG_FLAGS; - //DISASM_OUTPUT(("[SetOperand] reg FLAGS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_xFLAGS: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize; - Operand->Flags |= OP_REG; - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = AMD64_REG_RFLAGS; break; - case 4: Operand->Register = X86_REG_EFLAGS; break; - case 2: Operand->Register = X86_REG_FLAGS; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] reg xFLAGS (size = %d)\n", Operand->Length)); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_CS: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_CS; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg CS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_DS: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_DS; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg DS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_ES: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_ES; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg ES\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FS: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_FS; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg FS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_GS: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_GS; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg GS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_SS: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_SS; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg SS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_CR0: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_REG_CR0; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] reg CR0\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_STx: - if (!Decode) continue; - Operand->Length = 10; - Operand->Type = OPTYPE_FLOAT; - Operand->Flags |= OP_REG; - Register = X86_GET_REG(X86Instruction->modrm_b); - Operand->Register = X86_FPU_OFFSET + Register; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_STx: reg st(%d)\n", Register)); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_ST0: - if (!Decode) continue; - Operand->Length = 10; - Operand->Type = OPTYPE_FLOAT; - Operand->Flags |= OP_REG; - Operand->Register = X86_REG_ST0; - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_ST1: - if (!Decode) continue; - Operand->Length = 10; - Operand->Type = OPTYPE_FLOAT; - Operand->Flags |= OP_REG; - Operand->Register = X86_REG_ST1; - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_FPU_STATUS: - if (!Decode) continue; - Operand->Length = 2; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_FPU_CONTROL: - if (!Decode) continue; - Operand->Length = 2; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_FPU_TAG: - if (!Decode) continue; - Operand->Length = 2; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_FLDZ: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS("<0.0>"); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLD1: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS("<1.0>"); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLDPI: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLDL2T: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLDL2E: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLDLG2: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLDLN2: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - //////////////////////////////////////////////////////////// - // Fixed sizes regardless of operand size - //////////////////////////////////////////////////////////// - - case OPTYPE_b: // byte regardless of operand size - Operand->Length = 1; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_b (size 1, signed %d)\n", ((OperandFlags & OP_SIGNED) != 0))); - break; - - case OPTYPE_w: // word regardless of operand size - Operand->Length = 2; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_w (size 2)\n")); - break; - - case OPTYPE_d: // dword regardless of operand size - Operand->Length = 4; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_d (size 4)\n")); - break; - - case OPTYPE_q: // qword regardless of operand size - Operand->Length = 8; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_q (size 8)\n")); - break; - - case OPTYPE_o: // oword regardless of operand size - Operand->Length = 16; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_o (size 16)\n")); - break; - - case OPTYPE_dt: // 6-byte or 10-byte pseudo descriptor (sgdt, lgdt, sidt, lidt) - if (IS_AMD64()) Operand->Length = 10; - else Operand->Length = 6; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_dt (%d bytes)\n", Operand->Length)); - break; - - case OPTYPE_cpu: - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Undocumented loadall instruction?\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - Operand->Length = 204; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_cpu (size 204)\n")); - break; - - //////////////////////////////////////////////////////////// - // Sizes depending on the operand size - //////////////////////////////////////////////////////////// - - case OPTYPE_z: // word if operand size is 16 bits and dword otherwise - switch (X86Instruction->OperandSize) - { - case 8: case 4: Operand->Length = 4; break; - case 2: Operand->Length = 2; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_z (length %d)\n", Operand->Length)); - break; - - case OPTYPE_v: // word, dword, or qword - Operand->Length = X86Instruction->OperandSize; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_v (size %d, signed = %d)\n", Operand->Length, ((OperandFlags & OP_SIGNED) != 0))); - break; - - case OPTYPE_a: // two word or dword operands in memory (used only by bound) - assert(Instruction->OpcodeBytes[0] == X86_BOUND); - switch (X86Instruction->OperandSize) - { - case 8: case 4: Operand->Length = 8; break; - case 2: Operand->Length = 4; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_a (size %d)\n", Operand->Length)); - break; - - case OPTYPE_p: // 32-bit or 48-bit pointer depending on operand size - if (!Instruction->AnomalyOccurred && X86Instruction->HasSegmentOverridePrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used when segment is explicit\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - switch (X86Instruction->OperandSize) - { - case 8: case 4: Operand->Length = 6; break; - case 2: Operand->Length = 4; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_p (length %d)\n", Operand->Length)); - break; - - case OPTYPE_dq: // dword or qword - //DISASM_OUTPUT(("[SetOperand] OPTYPE_dq (size 4 or 8)\n")); - switch (X86Instruction->OperandSize) - { - case 8: Operand->Length = 8; break; - case 4: case 2: Operand->Length = 4; break; - default: assert(0); return NULL; - } - break; - - case OPTYPE_mw: // a word if the destination operand is memory - //DISASM_OUTPUT(("[SetOperand] OPTYPE_mw (size 0)\n")); - assert(X86Instruction->HasModRM); - if (modrm.mod == 3) Operand->Length = X86Instruction->OperandSize; // using register - else Operand->Length = 2; // using memory - break; - - case OPTYPE_lea: - //DISASM_OUTPUT(("[SetOperand] OPTYPE_lea (size 0)\n")); - assert(OperandIndex == 1); - Operand->Length = Instruction->Operands[0].Length; - break; - - //////////////////////////////////////////////////////////// - // FPU types - //////////////////////////////////////////////////////////// - - case OPTYPE_ps: // packed single real - Operand->Length = 4; - Operand->Type = OPTYPE_FLOAT; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_ps (packed single real)\n")); - break; - case OPTYPE_pd: // packed double real - Operand->Length = 8; - Operand->Type = OPTYPE_FLOAT; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_pd (packed double real)\n")); - break; - case OPTYPE_pb: // packed BCD - Operand->Length = 10; - Operand->Type = OPTYPE_BCD; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_pb (packed BCD)\n")); - break; - case OPTYPE_ss: // scalar single real - Operand->Length = 4; - Operand->Type = OPTYPE_FLOAT; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_ss (single real)\n")); - break; - case OPTYPE_sd: // scalar double real - Operand->Length = 8; - Operand->Type = OPTYPE_FLOAT; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_sd (double real)\n")); - break; - case OPTYPE_se: // extended real - Operand->Length = 10; - Operand->Type = OPTYPE_FLOAT; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_se (extended real)\n")); - break; - - case OPTYPE_fev: // FPU environment (28 bytes in 32-bit modes, 14 bytes in 16-bit real mode) - switch (X86Instruction->OperandSize) - { - case 8: case 4: Operand->Length = 28; break; - case 2: Operand->Length = 14; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_fev (FPU environment, length %d)\n", Operand->Length)); - break; - - case OPTYPE_fst1: // FPU state (108 bytes in 32-bit modes, 94 bytes in 16-bit real mode) - switch (X86Instruction->OperandSize) - { - case 8: case 4: Operand->Length = 108; break; - case 2: Operand->Length = 94; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_fst1 (FPU state, length %d)\n", Operand->Length)); - break; - - case OPTYPE_fst2: // 512 bytes for FPU state (FPU + MMX + XXM + MXCSR) - Operand->Length = 512; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_fst2 (FPU + MMX + XXM + MXCSR state, length 512)\n")); - break; - - case OPTYPE_sso: - if (modrm.mod == 3) // from register - { - Operand->Length = 16; - } - else // from memory - { - Operand->Length = 4; - Operand->Type = OPTYPE_FLOAT; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_sso (single real or oword)\n")); - break; - - case OPTYPE_sdo: - if (modrm.mod == 3) // from register - { - Operand->Length = 16; - } - else // from memory - { - Operand->Length = 8; - Operand->Type = OPTYPE_FLOAT; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_sso (double real or oword)\n")); - break; - - default: - assert(0); - return NULL; - } - - switch (AddressMode) - { - //////////////////////////////////////////////////////////// - // Special types - //////////////////////////////////////////////////////////// - - case AMODE_xlat: // DS:[EBX+AL] - if (!Decode) continue; - assert(Operand->Length == 1); - Operand->Flags |= OP_ADDRESS | OP_REG; - Operand->Type = OPTYPE_STRING; - - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_REG_RBX; break; - case 4: Operand->Register = X86_REG_EBX; break; - case 2: Operand->Register = X86_REG_BX; break; - default: assert(0); return NULL; - } - X86_SET_ADDR(); - X86Instruction->Scale = 1; - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - X86Instruction->IndexRegister = X86_REG_AL; - X86Instruction->HasIndexRegister = TRUE; - - //DISASM_OUTPUT(("[SetOperand] AMODE_xlat (DS:[EBX+AL])\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]", - Segments[X86Instruction->Segment], X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - //////////////////////////////////////////////////////////// - // Without mod R/M byte - //////////////////////////////////////////////////////////// - - case AMODE_I: // immediate value - if (Decode) - { - Operand->Type = OPTYPE_IMM; - switch (Operand->Length) - { - case 8: - if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S64 *)Address); - else Operand->Value_U64 = (U64)*((U64 *)Address); - break; - case 4: - if (!(OperandFlags & OP_SIGNED) && OperandIndex == 1 && - (Instruction->Operands[0].Flags & (OP_REG|OP_ADDRESS)) && - Instruction->Operands[0].Length == 8) - { - // For some opcodes the second operand is a sign-extended imm32 value - assert(X86Instruction->OperandSize == 8); - switch (Instruction->Type) - { - case ITYPE_AND: - case ITYPE_ADD: - case ITYPE_XCHGADD: - case ITYPE_CMP: - case ITYPE_MOV: - case ITYPE_SUB: - case ITYPE_TEST: - case ITYPE_OR: - case ITYPE_XOR: - assert(OperandIndex == 1); - Operand->Value_S64 = (S64)*((S32 *)Address); - break; - default: - assert(0); - if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S32 *)Address); - else Operand->Value_U64 = (U64)*((U32 *)Address); - break; - } - } - else - { - if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S32 *)Address); - else Operand->Value_U64 = (U64)*((U32 *)Address); - } - break; - case 2: - if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S16 *)Address); - else Operand->Value_U64 = (U64)*((U16 *)Address); - break; - case 1: - if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S8 *)Address); - else Operand->Value_U64 = (U64)*((U8 *)Address); - break; - default: - assert(0); - return NULL; - } - } - INSTR_INC(Operand->Length); // increment Instruction->Length and address - assert(X86Instruction->OperandSize >= Operand->Length); - if (Instruction->Type == ITYPE_PUSH) Operand->Length = X86Instruction->OperandSize; - - //DISASM_OUTPUT(("[SetOperand] AMODE_I (immediate data)\n")); - if (Disassemble) - { - X86_WRITE_IMMEDIATE(); - X86_WRITE_OPFLAGS(); - } - continue; - - case AMODE_J: // IP-relative jump offset - SANITY_CHECK_ADDRESS_SIZE(); - if (Decode) - { - Operand->Flags |= OP_IPREL | OP_SIGNED | OP_REG | OP_ADDRESS; - Operand->Type = OPTYPE_OFFSET; - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = AMD64_REG_RIP; break; - case 4: Operand->Register = X86_REG_EIP; break; - case 2: Operand->Register = X86_REG_IP; break; - default: assert(0); return NULL; - } - switch (Operand->Length) - { - case 8: X86Instruction->Displacement = *((S64 *)Address); break; - case 4: X86Instruction->Displacement = (S64)*((S32 *)Address); break; - case 2: X86Instruction->Displacement = (S64)*((S16 *)Address); break; - case 1: X86Instruction->Displacement = (S64)*((S8 *)Address); break; - default: assert(0); return NULL; - } - - Operand->Value_S64 = X86Instruction->Displacement; - X86Instruction->Relative = TRUE; - - if ((Operand->Flags & OP_COND) && !X86Instruction->Displacement) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Both conditions of branch go to same address\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - } - - INSTR_INC(Operand->Length); // increment Instruction->Length and address - if (!Decode) continue; - - assert((Operand->Flags & OP_EXEC) && (Instruction->Groups & ITYPE_EXEC)); - Operand->TargetAddress = ApplyDisplacement((U64)Address, Instruction); - X86Instruction->Relative = TRUE; - X86_SET_ADDR(); - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSegmentOverridePrefix = FALSE; - X86Instruction->Segment = SEG_CS; - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - assert(Instruction->OperandCount == 1); - //DISASM_OUTPUT(("[SetOperand] AMODE_J (branch with relative offset)\n")); - if (Disassemble) - { - X86_WRITE_IP_OFFSET(Operand); - X86_WRITE_OPFLAGS(); - } - continue; - - case AMODE_O: // word/dword offset - Operand->Type = OPTYPE_OFFSET; - Operand->Flags |= OP_ADDRESS; - SANITY_CHECK_OPERAND_SIZE(); - switch (X86Instruction->AddressSize) - { - case 8: - if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = *((S64 *)Address); - else X86Instruction->Displacement = (S64)*((U64 *)Address); - break; - case 4: - if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = (S64)*((S32 *)Address); - else X86Instruction->Displacement = (S64)*((U32 *)Address); - break; - case 2: - if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = (S64)*((S16 *)Address); - else X86Instruction->Displacement = (S64)*((U16 *)Address); - break; - default: - assert(0); - return FALSE; - } - - INSTR_INC(X86Instruction->AddressSize); // increment Instruction->Length and address - if (!Decode) continue; - - X86Instruction->HasFullDisplacement = TRUE; - X86_SET_ADDR(); - X86_SET_TARGET(); - assert(X86Instruction->Segment == SEG_DS || X86Instruction->HasSegmentOverridePrefix); - //DISASM_OUTPUT(("[SetOperand] AMODE_O (offset)\n")); - if (Disassemble) - { - X86_WRITE_OFFSET(Operand); - X86_WRITE_OPFLAGS(); - } - continue; - - case AMODE_A: // absolute address - Operand->Flags |= OP_ADDRESS | OP_FAR; - SANITY_CHECK_ADDRESS_SIZE(); - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSelector = TRUE; - X86Instruction->HasSegmentOverridePrefix = FALSE; - switch (Operand->Length) - { - case 6: - X86Instruction->Segment = *((U16 *)Address); INSTR_INC(2); - X86Instruction->Displacement = (S64)*((S32 *)Address); INSTR_INC(4); - break; - case 4: - X86Instruction->Segment = *((U16 *)Address); INSTR_INC(2); - X86Instruction->Displacement = (S64)*((S16 *)Address); INSTR_INC(2); - break; - default: - assert(0); - return FALSE; - } - if (!Decode) continue; - X86Instruction->HasFullDisplacement = TRUE; - X86_SET_ADDR(); - X86_SET_TARGET(); - //DISASM_OUTPUT(("[SetOperand] AMODE_A (absolute address)\n")); - if (Disassemble) - { - X86_WRITE_OFFSET(Operand); - X86_WRITE_OPFLAGS(); - } - continue; - - case AMODE_X: // DS:[ESI] - if (!Decode) continue; - Operand->Flags |= OP_ADDRESS | OP_REG; - Operand->Type = OPTYPE_STRING; - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_REG_RSI; break; - case 4: Operand->Register = X86_REG_ESI; break; - case 2: Operand->Register = X86_REG_SI; break; - default: assert(0); return NULL; - } - - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - X86_SET_ADDR(); - if (!X86Instruction->HasSegmentOverridePrefix) X86Instruction->Segment = SEG_DS; - - //DISASM_OUTPUT(("[SetOperand] AMODE_X (addressing via DS:[ESI])\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]", - Segments[X86Instruction->Segment], X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case AMODE_Y: // ES:[EDI] - if (!Decode) continue; - Operand->Flags |= OP_ADDRESS | OP_REG; - Operand->Type = OPTYPE_STRING; - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_REG_RDI; break; - case 4: Operand->Register = X86_REG_EDI; break; - case 2: Operand->Register = X86_REG_DI; break; - default: assert(0); return NULL; - } - - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - X86_SET_ADDR(); - if (X86Instruction->HasSegmentOverridePrefix) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: segment override used with AMODE_Y\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - Segment = X86Instruction->DstSegment = SEG_ES; - X86Instruction->HasDstSegment = TRUE; - } - else - { - Segment = X86Instruction->Segment = SEG_ES; - } - - //DISASM_OUTPUT(("[SetOperand] AMODE_Y (addressing via ES:[EDI])\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]", - Segments[Segment], X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - //////////////////////////////////////////////////////////// - // Mod R/M byte with only registers - // Handle that case here since it is straightforward - //////////////////////////////////////////////////////////// - - case AMODE_PR: // modrm.rm = mmx register and modrm.mod = 11 - assert(X86Instruction->HasModRM); - if (modrm.mod != 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_PR (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - else if (rex_modrm.rm > 7) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_PR (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic); - goto abort; - } - else if (X86Instruction->OperandSize == 2) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_PR illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic); - goto abort; - } - if (!Decode) continue; - - Operand->Flags |= OP_REG; - Operand->Register = X86_MMX_OFFSET + rex_modrm.rm; - X86_SET_REG(0); - - if (Disassemble) - { - assert(X86_Registers[Operand->Register]); - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_PR (MMX register)\n")); - continue; - - case AMODE_VR: // modrm.rm = xmm register and modrm.mod = 11 - assert(X86Instruction->HasModRM); - if (modrm.mod != 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_VR (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - else if (X86Instruction->OperandSize == 2) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_VR illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic); - goto abort; - } - if (!Decode) continue; - - Operand->Flags |= OP_REG; - Operand->Register = X86_XMM_OFFSET + rex_modrm.rm; - X86_SET_REG(0); - - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_VR (XMM register)\n")); - continue; - - case AMODE_P: // modrm.reg = mmx register - assert(X86Instruction->HasModRM); - if (rex_modrm.reg > 7) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_P (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.reg, X86Instruction->Opcode.Mnemonic); - goto abort; - } - else if (X86Instruction->OperandSize == 2) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_P illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - if (!Decode) continue; - - Operand->Flags |= OP_REG; - Operand->Register = X86_MMX_OFFSET + rex_modrm.reg; - X86_SET_REG(0); - - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_P (MMX register)\n")); - continue; - - case AMODE_V: // modrm.reg = xmm register - assert(X86Instruction->HasModRM); - if (X86Instruction->OperandSize == 2) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_P illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - if (!Decode) continue; - - Operand->Flags |= OP_REG; - Operand->Register = X86_XMM_OFFSET + rex_modrm.reg; break; - X86_SET_REG(0); - - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_V (XMM register)\n")); - continue; - - case AMODE_R: // modrm.rm is general register and modrm.mod = 11 - assert(X86Instruction->HasModRM); - if (modrm.mod != 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_R (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - if (!Decode) continue; - Operand->Flags |= OP_REG; - switch (Operand->Length) - { - case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break; - case 4: Operand->Register = X86_32BIT_OFFSET, rex_modrm.rm; CHECK_AMD64_REG(); break; - case 2: Operand->Register = X86_16BIT_OFFSET, rex_modrm.rm; CHECK_AMD64_REG(); break; - case 1: Operand->Register = X86_8BIT_OFFSET, rex_modrm.rm; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break; - default: assert(0); return NULL; - } - X86_SET_REG(rex_modrm.rm); - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_R (general register)\n")); - continue; - - case AMODE_G: // modrm.reg = general register - assert(X86Instruction->HasModRM); - if (!Decode) continue; - Operand->Flags |= OP_REG; - switch (Operand->Length) - { - case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.reg; break; - case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.reg; CHECK_AMD64_REG(); break; - case 2: Operand->Register = X86_16BIT_OFFSET + rex_modrm.reg; CHECK_AMD64_REG(); break; - case 1: Operand->Register = X86_8BIT_OFFSET + rex_modrm.reg; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break; - default: assert(0); return NULL; - } - X86_SET_REG(rex_modrm.reg); - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_G (general register)\n")); - continue; - - case AMODE_S: // modrm.reg = segment register - assert(X86Instruction->HasModRM); - if (!Decode) continue; - Operand->Flags |= OP_REG; - switch (X86Instruction->OperandSize) - { - case 8: - case 4: - case 2: - if (rex_modrm.reg <= 5) Operand->Register = X86_SEGMENT_OFFSET + rex_modrm.reg; - break; - default: - assert(0); - return NULL; - } - - X86_SET_REG(0); - if (Disassemble) - { - if (rex_modrm.reg > 5) APPEND(OPCSTR, SIZE_LEFT, "seg_%02X", rex_modrm.reg); - else APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_S (segment register)\n")); - continue; - - case AMODE_T: // modrm.reg = test register - assert(X86Instruction->HasModRM); - if (!Decode) continue; - Instruction->Groups |= ITYPE_SYSTEM; - Instruction->NeedsEmulation = TRUE; - Operand->Flags |= OP_REG; - switch (X86Instruction->OperandSize) - { - case 8: - case 4: - case 2: - Operand->Register = X86_TEST_OFFSET + rex_modrm.reg; - break; - default: - assert(0); - return NULL; - } - - X86_SET_REG(0); - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_T (test register)\n")); - continue; - - case AMODE_C: // modrm.reg = control register - assert(X86Instruction->HasModRM); - assert(Instruction->Type == ITYPE_MOV); - if (!Decode) continue; - Instruction->Groups |= ITYPE_SYSTEM; - Instruction->NeedsEmulation = TRUE; - Operand->Flags |= OP_REG; - if (IS_AMD64()) X86Instruction->OperandSize = 8; - switch (X86Instruction->OperandSize) - { - case 8: - case 4: - case 2: - Operand->Register = X86_CONTROL_OFFSET + rex_modrm.reg; - break; - default: - assert(0); - return NULL; - } - - X86_SET_REG(0); - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_C (control register)\n")); - continue; - - case AMODE_D: // modrm.reg = debug register - assert(X86Instruction->HasModRM); - assert(Instruction->Type == ITYPE_MOV); - if (!Decode) continue; - Instruction->NeedsEmulation = TRUE; - Operand->Flags |= OP_REG; - Instruction->Groups |= ITYPE_SYSTEM; - Instruction->NeedsEmulation = TRUE; - if (IS_AMD64()) X86Instruction->OperandSize = 8; - switch (X86Instruction->OperandSize) - { - case 8: - case 4: - case 2: - Operand->Register = X86_DEBUG_OFFSET + rex_modrm.reg; - break; - default: - assert(0); - return NULL; - } - - X86_SET_REG(0); - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_D (debug register)\n")); - continue; - - //////////////////////////////////////////////////////////// - // Mod R/M byte with memory or register - //////////////////////////////////////////////////////////// - - case AMODE_M: // memory only - assert(X86Instruction->HasModRM); - if (modrm.mod == 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod = 3 for AMODE_M (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - assert(X86Instruction->Segment == SEG_DS || X86Instruction->HasSegmentOverridePrefix); - //DISASM_OUTPUT(("[SetOperand] AMODE_M (memory only)\n")); - Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors); - if (!Address) return NULL; - break; - - case AMODE_E: // general register or memory - assert(X86Instruction->HasModRM); - if (OperandType == OPTYPE_p && modrm.mod == 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod = 3 for AMODE_E with OPTYPE_p (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - - //DISASM_OUTPUT(("[SetOperand] AMODE_E (general register or memory)\n")); - Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors); - if (!Address) return NULL; - if (Decode && (Instruction->Type == ITYPE_PUSH || Instruction->Type == ITYPE_POP)) - { - assert(X86Instruction->OperandSize >= Operand->Length); - Operand->Length = X86Instruction->OperandSize; - } - break; - - case AMODE_Q: // mmx register or memory address - assert(X86Instruction->HasModRM); - //DISASM_OUTPUT(("[SetOperand] AMODE_Q (MMX register or memory address)\n")); - if (modrm.mod == 3) // it is a register - { - if (rex_modrm.rm > 7) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_P (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic); - goto abort; - } - Operand->Register = X86_MMX_OFFSET + rex_modrm.rm; - Operand->Flags |= OP_REG; - X86_SET_REG(0); - } - else - { - Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors); - if (!Address) return NULL; - } - break; - - case AMODE_W: // xmm register or memory address - assert(X86Instruction->HasModRM); - //DISASM_OUTPUT(("[SetOperand] AMODE_W (XMM register or memory address)\n")); - if (modrm.mod == 3) // it is a register - { - Operand->Register = X86_XMM_OFFSET + rex_modrm.rm; - Operand->Flags |= OP_REG; - X86_SET_REG(0); - } - else - { - Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors); - if (!Address) return NULL; - } - break; - - default: - assert(0); - return NULL; - } - - if (!Decode) continue; - - // If this is reached then SetModRM32 was called - if ((Operand->Flags & OP_ADDRESS)) - { - assert(Operand->Length); - switch (Operand->Register) - { - case X86_REG_BP: - case X86_REG_EBP: - case AMD64_REG_RBP: - if (X86Instruction->Displacement > 0) Operand->Flags |= OP_PARAM; - else Operand->Flags |= OP_LOCAL; - break; - default: - break; - } - } - - if (Disassemble) - { - Index = OperandType >> OPTYPE_SHIFT; - assert(Index > 0 && Index < MAX_OPTYPE_INDEX && OptypeHandlers[Index]); - OptypeHandlers[Index](Instruction, Operand, OperandIndex); - X86_WRITE_OPFLAGS(); - } - } - - return Address; - -abort: - if (!SuppressErrors) - { -#ifdef TEST_DISASM - printf("Dump of 0x%04I64X:\n", VIRTUAL_ADDRESS); - __try { DumpAsBytes(stdout, Instruction->Address, (ULONG_PTR)VIRTUAL_ADDRESS, 16, TRUE); } - __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {} -#endif - fflush(stdout); - } - return NULL; -} - -// NOTE: Address points one byte after ModRM -INTERNAL U8 *SetModRM16(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors) -{ - MODRM modrm; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - - DISASM_OUTPUT(("[SetModRM16] Current instruction length = %d\n", Instruction->Length)); - modrm = X86Instruction->modrm; - assert(!X86Instruction->rex_b); - - // - // Both operands are registers - // Condition: mod = 3 - // - if (modrm.mod == 3) - { - //DISASM_OUTPUT(("[SetModRM16] Both regs (rm_reg %d)\n", modrm.rm)); - switch (Operand->Length) - { - case 4: Operand->Register = X86_32BIT_OFFSET + modrm.rm; break; - case 2: Operand->Register = X86_16BIT_OFFSET + modrm.rm; break; - case 1: Operand->Register = X86_8BIT_OFFSET + modrm.rm; break; - default: assert(0); return NULL; - } - Operand->Flags |= OP_REG; - } - - // - // Address is an absolute address (technically a 16-bit offset from DS:0) - // Condition: mod = 0 and rm = 6 - // - else if (modrm.mod == 0 && modrm.rm == 6) - { - //DISASM_OUTPUT(("[SetModRM16] Absolute addressing (displacement 0x%04X)\n", *(S16 *)Address)); - X86Instruction->Displacement = (S64)(*((S16 *)Address)); - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - X86Instruction->HasFullDisplacement = TRUE; - X86_SET_TARGET(); - Operand->Flags |= OP_GLOBAL; - } - X86_SET_ADDR(); - Operand->Flags |= OP_ADDRESS; - INSTR_INC(2); - } - - // Conditions: - // (1) mod = 0 and rm != 6 - // (2) mod = 1-2 and rm = 0-7 - else - { - switch (modrm.mod) - { - case 0: // no displacement - //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (no displacement)\n")); - break; - case 1: // 8-bit signed displacement - //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (displacement = 0x%02X, reg_rm = %d)\n", *(S8 *)Address, modrm.rm)); - X86Instruction->Displacement = (S64)(*((S8 *)Address)); - INSTR_INC(1); // increment Instruction->Length and address - break; - case 2: // 16-bit displacement - //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (displacement = 0x%04X, reg_rm = %d)\n", *(S16 *)Address, modrm.rm)); - X86Instruction->Displacement = (S64)(*((S16 *)Address)); - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - Operand->Flags |= OP_GLOBAL; - X86Instruction->HasFullDisplacement = TRUE; - } - INSTR_INC(2); - break; - } - - switch (modrm.rm) - { - case 0: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX+SI]\n")); - X86Instruction->BaseRegister = X86_REG_BX; - X86Instruction->IndexRegister = X86_REG_SI; - X86Instruction->HasIndexRegister = TRUE; - break; - case 1: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX+DI]\n")); - X86Instruction->BaseRegister = X86_REG_BX; - X86Instruction->IndexRegister = X86_REG_DI; - X86Instruction->HasIndexRegister = TRUE; - break; - case 2: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP+SI]\n")); - X86Instruction->BaseRegister = X86_REG_BP; - X86Instruction->IndexRegister = X86_REG_SI; - X86Instruction->HasIndexRegister = TRUE; - X86_SET_SEG(REG_BP); - break; - case 3: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP+DI]\n")); - X86Instruction->BaseRegister = X86_REG_BP; - X86Instruction->IndexRegister = X86_REG_DI; - X86Instruction->HasIndexRegister = TRUE; - X86_SET_SEG(REG_BP); - break; - case 4: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [SI]\n")); - X86Instruction->BaseRegister = X86_REG_SI; - break; - case 5: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [DI]\n")); - X86Instruction->BaseRegister = X86_REG_DI; - break; - case 6: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP]\n")); - X86Instruction->BaseRegister = X86_REG_BP; - break; - case 7: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX]\n")); - X86Instruction->BaseRegister = X86_REG_BX; - break; - } - - X86Instruction->HasBaseRegister = TRUE; - Operand->Flags |= OP_ADDRESS | OP_REG; - X86_SET_ADDR(); - } - - return Address; -} - -// NOTE: Address points one byte after ModRM -INTERNAL U8 *SetModRM32(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors) -{ - MODRM modrm; - REX_MODRM rex_modrm; - U32 i, ImmediateSize = 0; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - - if (X86Instruction->AddressSize == 2) - { - return SetModRM16(Instruction, Address, Operand, OperandIndex, SuppressErrors); - } - - //DISASM_OUTPUT(("[SetModRM32] Length %d, modrm = 0x%02X\n", Instruction->Length, X86Instruction->modrm_b)); - modrm = X86Instruction->modrm; - rex_modrm = X86Instruction->rex_modrm; - - // - // Both operands are registers - // Condition: mod = 3 - // - if (modrm.mod == 3) - { - switch (Operand->Length) - { - case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break; - case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break; - case 2: Operand->Register = X86_16BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break; - case 1: Operand->Register = X86_8BIT_OFFSET + rex_modrm.rm; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break; - default: assert(0); return NULL; - } - X86_SET_REG(rex_modrm.rm); - Operand->Flags |= OP_REG; - } - - // - // Address is an absolute address (technically a 32-bit offset from DS:0) - // mod = 0 and rm = 5 - // - else if (modrm.mod == 0 && modrm.rm == 5) - { - //DISASM_OUTPUT(("[SetModRM32] Absolute addressing (displacement 0x%08lX)\n", *(S32 *)Address)); - Operand->Flags |= OP_ADDRESS; - X86Instruction->Displacement = (S64)*((S32 *)Address); - INSTR_INC(4); // increment Instruction->Length and address - - if (IS_AMD64()) - { - // RIP-relative addressing always replaced Disp32, even when using a 32-bit address space - // (via address size override prefix) - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = AMD64_REG_RIP; break; - case 4: Operand->Register = X86_REG_EIP; break; - case 2: Operand->Register = X86_REG_IP; break; - default: assert(0); return NULL; - } - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - X86Instruction->Relative = TRUE; - Operand->Flags |= OP_IPREL | OP_SIGNED | OP_REG; - SANITY_CHECK_SEGMENT_OVERRIDE(); - if (!X86Instruction->HasSegmentOverridePrefix) X86Instruction->Segment = SEG_CS; - X86Instruction->HasFullDisplacement = TRUE; - - // Since there may be an immediate value to follow, it is necessary - // to determine the length in order get the proper offset - // - // Maybe there is a better way to do this, since this is wasteful - // (the size of the immediate value will have to be decoded again later - // in SetOperands) - - for (ImmediateSize = 0, i = OperandIndex+1; i < Instruction->OperandCount; i++) - { - if ((X86Instruction->Opcode.OperandFlags[i] & X86_AMODE_MASK) != AMODE_I) continue; - else assert(!ImmediateSize); - switch (X86Instruction->Opcode.OperandFlags[i] & X86_OPTYPE_MASK) - { - case OPTYPE_v: - ImmediateSize = X86Instruction->OperandSize; - break; - case OPTYPE_z: - switch (X86Instruction->OperandSize) - { - case 8: case 4: ImmediateSize = 4; break; - case 2: ImmediateSize = 2; break; - default: assert(0); return NULL; - } - break; - case OPTYPE_b: - ImmediateSize = 1; - break; - case OPTYPE_w: - ImmediateSize = 2; - break; - case OPTYPE_1: - break; - default: - assert(0); - break; - } - } - - Operand->TargetAddress = ApplyDisplacement((U64)Address + ImmediateSize, Instruction); - } - else if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - X86_SET_TARGET(); - Operand->Flags |= OP_GLOBAL; - X86Instruction->HasFullDisplacement = TRUE; - } - - X86_SET_ADDR(); - } - - // - // Addressing mode indicated by SIB byte - // Condition: mod = 0-2 and rm = 4 - // - else if (modrm.rm == 4) - { - // The X86_SET_*() is called from within SetSIB() - Address = SetSIB(Instruction, Address, Operand, OperandIndex, SuppressErrors); - if (!Address) - { - assert(0); - return NULL; - } - - if (X86Instruction->sib.base != 5) // if base == 5, the displacement is handled in SetSIB - { - switch (modrm.mod) - { - case 1: // 8-bit displacement - //DISASM_OUTPUT(("[SetModRM32] After SIB: displacement 0x%02X\n", *((S8 *)Address))); - X86Instruction->Displacement = (S64)(*((S8 *)Address)); - INSTR_INC(1); // increment Instruction->Length and address - break; - case 2: // 32-bit displacement - //DISASM_OUTPUT(("[SetModRM32] After SIB: displacement 0x%08lX\n", *((S32 *)Address))); - X86Instruction->Displacement = (S64)*((S32 *)Address); - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - Operand->Flags |= OP_GLOBAL; - X86Instruction->HasFullDisplacement = TRUE; - } - INSTR_INC(4); // increment Instruction->Length and address - break; - } - } - } - - // Indirect addressing - // Conditions: - // (1) mod = 0 and (rm = 0-3 or 6-7) - // (2) mod = 1-2 and rm != 4 - else - { - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break; - case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break; - default: assert(0); return NULL; - } - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - Operand->Flags |= OP_ADDRESS | OP_REG; - X86_SET_SEG(rex_modrm.rm); - X86_SET_ADDR(); - - switch (modrm.mod) - { - case 0: // no displacement - //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (no displacement, reg_rm = %d)\n", rex_modrm.rm)); - break; - case 1: // 8-bit signed displacement - //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (displacement = 0x%02X, reg_rm = %d)\n", *(S8 *)Address, rex_modrm.rm)); - X86Instruction->Displacement = (S64)(*((S8 *)Address)); - INSTR_INC(1); // increment Instruction->Length and address - break; - case 2: // 32-bit displacement - //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (displacement = 0x%08lX, reg_rm = %d)\n", *(S32 *)Address, rex_modrm.rm)); - X86Instruction->Displacement = (S64)*((S32 *)Address); - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - Operand->Flags |= OP_GLOBAL; - X86Instruction->HasFullDisplacement = TRUE; - } - INSTR_INC(4); // increment Instruction->Length and address - break; - } - } - - return Address; -} - -// NOTE: Address points at SIB -INTERNAL U8 *SetSIB(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors) -{ - REX rex; - SIB sib; - REX_SIB rex_sib; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - - X86Instruction->sib_b = *Address; - SET_SIB(X86Instruction->sib, *Address); - sib = X86Instruction->sib; - rex = X86Instruction->rex; - SET_REX_SIB(X86Instruction->rex_sib, rex, sib); - rex_sib = X86Instruction->rex_sib; - - //if (!X86Instruction->rex_b) DISASM_OUTPUT(("[0x%08I64X] SIB = 0x%02X (scale=%d, index=%d, base=%d)\n", VIRTUAL_ADDRESS, *Address, sib.scale, sib.index, sib.base)); \ - //else DISASM_OUTPUT(("[0x%08I64X] SIB = 0x%02X (scale=%d, index=%d, base=%d)\n", VIRTUAL_ADDRESS, *Address, sib.scale, rex_sib.index, rex_sib.base)); \ - //DISASM_OUTPUT(("[SetSIB] Current instruction length = %d\n", Instruction->Length)); - - Operand->Flags |= OP_ADDRESS; - X86_SET_ADDR(); - INSTR_INC(1); // increment Instruction->Length and address - - if (sib.base == 5) - { - switch (X86Instruction->modrm.mod) - { - case 0: - X86Instruction->Displacement = (S64)*((S32 *)Address); - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - X86Instruction->HasFullDisplacement = TRUE; - X86_SET_TARGET(); - Operand->Flags |= OP_GLOBAL; - } - INSTR_INC(4); - break; - case 1: - X86Instruction->Displacement = (S64)(*((S8 *)Address)); - if (rex_sib.base == 5) - { - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_REG_RBP; break; - case 4: Operand->Register = X86_REG_EBP; break; - default: assert(0); return NULL; - } - X86_SET_SEG(REG_EBP); - } - else - { - Operand->Register = AMD64_REG_R13; - } - - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - Operand->Flags |= OP_REG; - INSTR_INC(1); - break; - case 2: - X86Instruction->Displacement = (S64)*((S32 *)Address); - if (rex_sib.base == 5) - { - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_REG_RBP; break; - case 4: Operand->Register = X86_REG_EBP; break; - default: assert(0); return NULL; - } - X86_SET_SEG(REG_EBP); - } - else - { - Operand->Register = AMD64_REG_R13; - } - - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - Operand->Flags |= OP_GLOBAL; - X86Instruction->HasFullDisplacement = TRUE; - } - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - Operand->Flags |= OP_REG; - INSTR_INC(4); - break; - } - } - else - { - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_sib.base; break; - case 4: Operand->Register = X86_32BIT_OFFSET + rex_sib.base; CHECK_AMD64_REG(); break; - default: assert(0); return NULL; - } - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - X86_SET_SEG(rex_sib.base); - Operand->Flags |= OP_REG; - } - - if (rex_sib.index != 4) - { - switch (X86Instruction->AddressSize) - { - case 8: - X86Instruction->IndexRegister = AMD64_64BIT_OFFSET + rex_sib.index; - break; - case 4: - X86Instruction->IndexRegister = X86_32BIT_OFFSET + rex_sib.index; - break; - default: - fflush(stdout); - assert(0); - return NULL; - } - - Operand->TargetAddress = 0; - X86Instruction->HasIndexRegister = TRUE; - //DISASM_OUTPUT(("[SetSIB] Index register = %s\n", X86_Registers[X86_32BIT_OFFSET + rex_sib.index])); - - switch (sib.scale) - { - case 0: X86Instruction->Scale = 1; break; - case 1: X86Instruction->Scale = 2; break; - case 2: X86Instruction->Scale = 4; break; - case 3: X86Instruction->Scale = 8; break; - } - //DISASM_OUTPUT(("[SetSIB] Scale = %d\n", X86Instruction->Scale)); - } - - return Address; -} - -INTERNAL U64 ApplyDisplacement(U64 Address, INSTRUCTION *Instruction) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - -#ifdef SUPPORT_WRAPAROUND - U64 VirtualAddress = Address + Instruction->VirtualAddressDelta; - switch (X86Instruction->OperandSize) - { - case 8: - { - U64 PreAddr = VirtualAddress; - U64 PostAddr = PreAddr + X86Instruction->Displacement; - return Address + (PostAddr - PreAddr); - } - case 4: - { - // We have to do this carefully... - // If EIP = FFFFF000 and Displacement=2000 then the final IP should be 1000 - // due to wraparound - U32 PreAddr = (U32)VirtualAddress; - U32 PostAddr = PreAddr + (S32)X86Instruction->Displacement; - return Address + (PostAddr - PreAddr); - } - case 2: - { - // We have to do this carefully... - // If IP = F000 and Displacement=2000 then the final IP should be 1000 - // due to wraparound - U16 PreAddr = (U16)VirtualAddress; - U16 PostAddr = PreAddr + (S16)X86Instruction->Displacement; - return Address + (PostAddr - PreAddr); - } - default: - assert(0); - return 0; - } -#else - return (Address + X86Instruction->Displacement); -#endif -} - - - -INTERNAL BOOL IsValidLockPrefix(X86_INSTRUCTION *X86Instruction, U8 Opcode, U32 OpcodeLength, U8 Group, U8 OpcodeExtension) -{ - switch (OpcodeLength) - { - case 1: - switch (X86_LockPrefix_1[Opcode]) - { - case 0: // instruction can't be locked - return FALSE; - case 1: // instruction can be locked - break; - case GR: - assert(Group); - if (!X86_LockPrefix_Groups[Group-1][OpcodeExtension]) return FALSE; - break; - default: - assert(0); - return FALSE; - } - break; - - case 2: - case 3: - switch (X86_LockPrefix_2[Opcode]) - { - case 0: // lock prefix is not acceptable - return FALSE; - case 1: // lock prefix allowed - break; - case GR: - assert(Group); - if (!X86_LockPrefix_Groups[Group-1][OpcodeExtension]) return FALSE; - break; - default: - assert(0); - return FALSE; - } - break; - - default: - assert(0); - return FALSE; - } - - if (!X86Instruction->HasModRM || X86Instruction->modrm.mod == 3 || !X86Instruction->HasDstAddressing) - { - DISASM_OUTPUT(("[0x%08I64X] ERROR: Instruction \"%s\" with LOCK prefix has invalid ModRM addressing\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic, X86Instruction->Instruction->Address)); - return FALSE; - } - - return TRUE; -} diff --git a/renderdoc/3rdparty/mhook/disasm-lib/disasm_x86.h b/renderdoc/3rdparty/mhook/disasm-lib/disasm_x86.h deleted file mode 100644 index 7a9f0d75a..000000000 --- a/renderdoc/3rdparty/mhook/disasm-lib/disasm_x86.h +++ /dev/null @@ -1,839 +0,0 @@ -// Copyright (C) 2004, Matt Conover (mconover@gmail.com) -#ifndef X86_DISASM_H -#define X86_DISASM_H -#ifdef __cplusplus -extern "C" { -#endif - -#pragma warning(disable: 4201) - -// NOTE: the processor may actually accept less than this amount (officially 15) -// #define AMD64_MAX_INSTRUCTION_LEN 15 // theoretical max 25=5+2+1+1+8+8 -#define AMD64_MAX_PREFIX_LENGTH 5 // 4 legacy + 1 rex -#define AMD64_MAX_ADDRESS_LENGTH 18 // modrm + sib + 8 byte displacement + 8 byte immediate value - -// NOTE: the processor may actually accept less than this amount (officially 15) -#define X86_MAX_INSTRUCTION_LEN 15 // theoretical 16=4+2+1+1+4+4 -#define X86_MAX_PREFIX_LENGTH 4 -#define X86_MAX_OPCODE_LENGTH 3 // third byte is either a suffix or prefix -#define X86_MAX_ADDRESS_LENGTH 10 // modrm + sib + 4 byte displacement + 4 byte immediate value -#define X86_MAX_OPERANDS 3 - -#define X86_PREFIX(a) ((a)->MnemonicFlags == ITYPE_EXT_PREFIX) -#define X86_SPECIAL_EXTENSION(a) ((a)->MnemonicFlags & (ITYPE_EXT_MODRM|ITYPE_EXT_FPU|ITYPE_EXT_SUFFIX|ITYPE_EXT_64)) -#define X86_EXTENDED_OPCODE(a) ((a)->Table) -#define X86_INVALID(a) (!(a)->MnemonicFlags && !(a)->Table) -#define X86_OPERAND_COUNT(a) ((a)->OperandFlags[0] ? ((a)->OperandFlags[1] ? ((a)->OperandFlags[2] ? 3 : 2) : 1) : 0) -#define X86_GET_CATEGORY(p) ((p)->MnemonicFlags & ITYPE_GROUP_MASK) -#define X86_GET_TYPE(p) ((p)->MnemonicFlags & ITYPE_TYPE_MASK) - -// Various instructions being specially decoded -#define X86_TWO_BYTE_OPCODE 0x0f -#define PREFIX_SEGMENT_OVERRIDE_ES 0x26 -#define PREFIX_SEGMENT_OVERRIDE_CS 0x2e -#define PREFIX_BRANCH_NOT_TAKEN 0x2e // used only with conditional jumps -#define PREFIX_SEGMENT_OVERRIDE_SS 0x36 -#define PREFIX_SEGMENT_OVERRIDE_DS 0x3e -#define PREFIX_BRANCH_TAKEN 0x3e // used only with conditional jumps -#define PREFIX_SEGMENT_OVERRIDE_FS 0x64 -#define PREFIX_SEGMENT_OVERRIDE_GS 0x65 -#define PREFIX_OPERAND_SIZE 0x66 -#define PREFIX_ADDRESS_SIZE 0x67 -#define PREFIX_LOCK 0xf0 -#define PREFIX_REPNE 0xf2 -#define PREFIX_REP 0xf3 - -////////////////////////////////////////////////////////////////// -// Implicit operand handling -////////////////////////////////////////////////////////////////// - -#define X86_AMODE_MASK 0x00FF0000 // bits 16-23 (AMODE_*) -#define X86_OPFLAGS_MASK 0x0000FF80 // bits 7-15 (OPTYPE_*) -#define X86_OPTYPE_MASK 0xFF0000FF // bits 0-7 (OPTYPE_* below + OP_REG) and 24-31 (OPTYPE_* above) - -#define OPTYPE_0 0x01 -#define OPTYPE_1 0x02 -#define OPTYPE_FF 0x03 -//... -#define OPTYPE_CS 0x10 -#define OPTYPE_DS 0x11 -#define OPTYPE_ES 0x12 -#define OPTYPE_FS 0x13 -#define OPTYPE_GS 0x14 -#define OPTYPE_SS 0x15 -#define OPTYPE_CR0 0x16 -#define OPTYPE_TSC 0x17 // time stamp counter -//... -#define OPTYPE_FLAGS 0x20 -#define OPTYPE_xFLAGS 0x21 // RFLAGS/EFLAGS (depending on operand size) -#define OPTYPE_xCX_HI_xBX_LO 0x22 // represented by 2 registers CX:BX or ECX:EBX (depending on operand size) -#define OPTYPE_xDX_HI_xAX_LO 0x23 // DX:AX or EDX:EAX (depending on operand size) -#define OPTYPE_EDX_HI_EAX_LO 0x24 // DX:AX or EDX:EAX (depending on operand size) -#define OPTYPE_EDX_ECX_EBX_EAX 0x25 // all registers are set -//... -#define OPTYPE_STx 0x30 -#define OPTYPE_ST0 0x31 -#define OPTYPE_ST1 0x32 -#define OPTYPE_FPU_STATUS 0x33 -#define OPTYPE_FPU_CONTROL 0x34 -#define OPTYPE_FPU_TAG 0x35 -#define OPTYPE_FLDZ 0x36 // 0 -#define OPTYPE_FLD1 0x37 // 1 -#define OPTYPE_FLDPI 0x38 // pi -#define OPTYPE_FLDL2T 0x39 // lg 10 -#define OPTYPE_FLDL2E 0x3A // lg e -#define OPTYPE_FLDLG2 0x3B // log_10 2 -#define OPTYPE_FLDLN2 0x3C // log_e 2 -//... -#define OPTYPE_CS_MSR 0x40 -#define OPTYPE_EIP_MSR 0x41 -#define OPTYPE_ESP_MSR 0x42 -#define OPTYPE_KERNELBASE_MSR 0x43 -#define OPTYPE_FMASK_MSR 0x44 -#define OPTYPE_STAR_MSR 0x45 -#define OPTYPE_CSTAR_MSR 0x46 // 32-bit mode -#define OPTYPE_LSTAR_MSR 0x47 // 64-bit mode - - -// NOTE: OPTYPES >= 0x80 reserved for registers (OP_REG+XX) -#define OPTYPE_REG_AL OP_REG+0x01 -#define OPTYPE_REG_CL OP_REG+0x02 -#define OPTYPE_REG_AH OP_REG+0x03 -#define OPTYPE_REG_AX OP_REG+0x04 -#define OPTYPE_REG_DX OP_REG+0x05 -#define OPTYPE_REG_ECX OP_REG+0x06 -#define OPTYPE_REG8 OP_REG+0x07 - -// If address size is 2, use BP -// If address size is 4, use EBP -// If address size is 8, use RBP -#define OPTYPE_REG_xBP OP_REG+0x08 - -// If address size is 2, use BP -// If address size is 4, use EBP -// If address size is 8, use RBP -#define OPTYPE_REG_xSP OP_REG+0x09 - -// If operand size is 2, take 8-bit register -// If operand size is 4, take 16-bit register -// If operand size is 8, take 32-bit register -#define OPTYPE_REG_xAX_SMALL OP_REG+0x0a - -// If operand size is 2, take 16-bit register -// If operand size is 4, take 32-bit register -// If operand size is 8, take 64-bit register -#define OPTYPE_REG_xAX_BIG OP_REG+0x0b - -typedef enum _CPU_TYPE -{ - CPU_UNKNOWN=0, - - /////////////////////////////////////// - // 1st generation - /////////////////////////////////////// - // 1978 - //CPU_8086 = 1MB address limit, 16-bit registers - // 1982 - //CPU_i186 - - /////////////////////////////////////// - // 2nd generation - /////////////////////////////////////// - // 1982 - //CPU_I286 // 16MB limit, 16-bit registers, added protected mode - CPU_I287, // CPU_I286 + math coprocessor - - /////////////////////////////////////// - // 3rd generation - /////////////////////////////////////// - // 1985 - CPU_I386, // 32-bit registers, 4GB memory limit - // 1988 - CPU_I387, // CPU_I386 + math coprocessor - - /////////////////////////////////////// - // 4th generation (1989) - /////////////////////////////////////// - CPU_I486, - - /////////////////////////////////////// - // 5th generation - /////////////////////////////////////// - // 1993 - CPU_PENTIUM, // superscalar architecture - // 1997 - //CPU_PENTIUM_MMX - - /////////////////////////////////////// - // 6th generation (1995) - /////////////////////////////////////// - CPU_PENTIUM_PRO, // P6 architecture, no MMX, out-of-order execution, speculative execution - //CPU_CYRIX_6X86, - //CPU_AMD_K5 // RISC processor - // 1997 - CPU_PENTIUM2, // Pentium Pro architecture + MMX - //CPU_AMD_K6, - //CPU_CYRIX_6X86MX, // Cyrix 6x86 + MMX - // 1998 - CPU_AMD_K6_2, // added 3DNow! (MMX) - // 1999 - // CPU_AMD_K6_3 // added SSE - - /////////////////////////////////////// - // 7th generation - /////////////////////////////////////// - // 1999 - CPU_PENTIUM3, // introduced SSE - // CPU_AMD_K7 // aka Athlon - // 2000 - CPU_PENTIUM4, // introduced SSE2 and hyperthreading - - // 2004? 2005? - CPU_PRESCOTT, // introduced SSE3 - - /////////////////////////////////////// - // 8th generation (X86-64) - // IA32 instruction set with 64-bit extensions, >4GB RAM - /////////////////////////////////////// - - // 2003 - CPU_AMD64, // includes Athlon 64 and Opteron aka X86-64 - - // 2004? - //CPU_EMD64 // Intel's version of AMD64 - CPU_IA64 // aka Itanium: new instruction set -- adds JMPE to IA32 mode to return to IA64 native code - -} CPU_TYPE; - -////////////////////////////////////////////////////////////////// -// Conditions (these can be OR'd) -////////////////////////////////////////////////////////////////// - -// Used for Flags.Preconditions -#define COND_O (1<<0) // overflow (signed) -#define COND_C (1<<1) // below (unsigned) -#define COND_Z (1<<2) // equal (unsigned) -#define COND_S (1<<3) // sign set (signed) -#define COND_P (1<<4) // parity even -#define COND_BE (1<<5) // CF or ZF is set (unsigned) -#define COND_L (1<<6) // (SF && !OF) || (OF && !SF) -#define COND_LE (1<<7) // ZF || (SF && !OF) || (OF && !SF) (signed) -#define COND_NO (1<<8) // !O -#define COND_NC (1<<9) // !C (not below, above or equal to) -#define COND_NZ (1<<10) // !Z (not equal) -#define COND_NS (1<<11) // !S -#define COND_NP (1<<12) // !P (parity odd) -#define COND_NL (1<<13) // (!SF && !OF) || (SF && OF) -#define COND_G (1<<14) // !ZF && ((!SF && !OF) || (SF && OF)) -#define COND_D (1<<15) // DF -#define COND_REG_xCX_BIG_Z (1<<16) // CX/ECX/RCX (depending on address size) == 0 -#define COND_REG_xCX_BIG_NZ (1<<17) // CX/ECX/RCX (depending on address size) != 0 -#define COND_OP1_EQ_OP2 (1<<18) -#define COND_OP1_EQ_OP3 (1<<19) -#define COND_B COND_C -#define COND_NAE COND_C -#define COND_E COND_Z -#define COND_NA COND_BE -#define COND_PE COND_P -#define COND_U COND_P -#define COND_NGE COND_L -#define COND_NG COND_LE -#define COND_PO COND_NP -#define COND_NU COND_NP -#define COND_NE COND_NZ -#define COND_NB COND_NC -#define COND_AE COND_NC -#define COND_NE COND_NZ -#define COND_A (COND_NC|COND_NZ) -#define COND_NBE COND_A -#define COND_GE COND_NL -#define COND_NLE COND_G - -// Used for Opcode.FlagsChanged -#define FLAG_CF_SET (1<<0) -#define FLAG_DF_SET (1<<1) -#define FLAG_IF_SET (1<<2) -#define FLAG_SET_MASK (FLAG_CF_SET|FLAG_DF_SET|FLAG_IF_SET) - -#define FLAG_SF_CLR (1<<3) -#define FLAG_ZF_CLR (1<<4) -#define FLAG_AF_CLR (1<<5) -#define FLAG_CF_CLR (1<<6) -#define FLAG_DF_CLR (1<<7) -#define FLAG_IF_CLR (1<<8) -#define FLAG_OF_CLR (1<<9) -#define FPU_C0_CLR (1<<19) -#define FPU_C1_CLR (1<<20) -#define FPU_C2_CLR (1<<21) -#define FPU_C3_CLR (1<<22) -#define FPU_ALL_CLR (FPU_C0_CLR|FPU_C1_CLR|FPU_C2_CLR|FPU_C3_CLR) -#define FLAG_CLR_MASK (FLAG_SF_CLR|FLAG_ZF_CLR|FLAG_AF_CLR|FLAG_CF_CLR|FLAG_DF_CLR|FLAG_IF_CLR|FLAG_OF_CLR|FPU_ALL_CLR) - -#define FLAG_OF_MOD (1<<10) -#define FLAG_SF_MOD (1<<11) -#define FLAG_ZF_MOD (1<<12) -#define FLAG_AF_MOD (1<<13) -#define FLAG_PF_MOD (1<<14) -#define FLAG_CF_MOD (1<<15) -#define FLAG_DF_MOD (1<<16) -#define FLAG_IF_MOD (1<<17) -#define FLAG_ALL_MOD (FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD|FLAG_CF_MOD|FLAG_DF_MOD|FLAG_IF_MOD) -#define FLAG_COMMON_MOD (FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD|FLAG_CF_MOD) -#define FPU_C0_MOD (1<<23) -#define FPU_C1_MOD (1<<24) -#define FPU_C2_MOD (1<<25) -#define FPU_C3_MOD (1<<26) -#define FPU_ALL_MOD (FPU_C0_MOD|FPU_C1_MOD|FPU_C2_MOD|FPU_C3_MOD) -#define FLAG_MOD_MASK (FLAG_ALL_MOD|FPU_ALL_MOD) - -#define FLAG_CF_TOG (1<<18) -#define FLAG_TOG_MASK FLAG_CF_TOG - -// Used for Opcode.ResultsIfTrue and Opcode.ResultsIfFalse -#define OP1_DST (1<<0) -#define OP2_DST (1<<1) -#define OP3_DST (1<<2) -#define OP1_SRC (1<<3) -#define OP2_SRC (1<<4) -#define OP3_SRC (1<<5) -#define FPU_STACK_INC (1<<6) -#define FPU_STACK_INC2 (1<<7) -#define FPU_STACK_DEC (1<<8) -#define SERIALIZE_WRITE (1<<9) -#define SERIALIZE_READ (1<<10) -#define xCX_DEC (1<<11) -#define xCX_REP_DEC (1<<12) -#define xDI_DEC (1<<13) -#define xDI_INC (1<<14) -#define xSI_DEC (1<<15) -#define xSI_INC (1<<16) -#define xDI_DECx (1<<17) -#define xDI_INCx (1<<18) -#define xSI_DECx (1<<19) -#define xSI_INCx (1<<20) -#define FPU_STACK_PUSH FPU_STACK_DEC -#define FPU_STACK_POP FPU_STACK_INC -#define FPU_STACK_POP2 FPU_STACK_INC2 -#define SERIALIZE_ALL (SERIALIZE_WRITE|SERIALIZE_READ) - -#define X86_SEGMENT_OFFSET 0x00 -#define X86_TEST_OFFSET 0x10 -#define X86_CONTROL_OFFSET 0x20 -#define X86_DEBUG_OFFSET 0x30 -#define X86_FPU_OFFSET 0x40 -#define X86_MMX_OFFSET 0x50 -#define X86_XMM_OFFSET 0x60 -#define X86_8BIT_OFFSET 0x70 -#define X86_16BIT_OFFSET 0x80 -#define X86_32BIT_OFFSET 0x90 -#define AMD64_8BIT_OFFSET 0xA0 -#define AMD64_16BIT_OFFSET 0xB0 -#define AMD64_32BIT_OFFSET 0xC0 -#define AMD64_64BIT_OFFSET 0xD0 - -typedef enum _X86_REGISTER -{ - // Segments - X86_SEG_ES = X86_SEGMENT_OFFSET, - X86_SEG_CS, - X86_SEG_SS, - X86_SEG_DS, - X86_SEG_FS, - X86_SEG_GS, - - // Miscellaneous - X86_REG_FLAGS, - X86_REG_EFLAGS, - AMD64_REG_RFLAGS, - X86_REG_IP, - X86_REG_EIP, - AMD64_REG_RIP, - - // Test registers - X86_REG_TR0 = X86_TEST_OFFSET, - X86_REG_TR1, - X86_REG_TR2, - X86_REG_TR3, - X86_REG_TR4, - X86_REG_TR5, - X86_REG_TR6, - X86_REG_TR7, - X86_REG_TR8, - X86_REG_TR9, - X86_REG_TR10, - X86_REG_TR11, - X86_REG_TR12, - X86_REG_TR13, - X86_REG_TR14, - X86_REG_TR15, - - // Control registers - X86_REG_CR0=X86_CONTROL_OFFSET, - X86_REG_CR1, - X86_REG_CR2, - X86_REG_CR3, - X86_REG_CR4, - X86_REG_CR5, - X86_REG_CR6, - X86_REG_CR7, - X86_REG_CR8, - X86_REG_CR9, - X86_REG_CR10, - X86_REG_CR11, - X86_REG_CR12, - X86_REG_CR13, - X86_REG_CR14, - X86_REG_CR15, - - // Debug registers - X86_REG_DR0=X86_DEBUG_OFFSET, - X86_REG_DR1, - X86_REG_DR2, - X86_REG_DR3, - X86_REG_DR4, - X86_REG_DR5, - X86_REG_DR6, - X86_REG_DR7, - X86_REG_DR8, - X86_REG_DR9, - X86_REG_DR10, - X86_REG_DR11, - X86_REG_DR12, - X86_REG_DR13, - X86_REG_DR14, - X86_REG_DR15, - - // FPU registers - X86_REG_ST0=X86_FPU_OFFSET, - X86_REG_ST1, - X86_REG_ST2, - X86_REG_ST3, - X86_REG_ST4, - X86_REG_ST5, - X86_REG_ST6, - X86_REG_ST7, - - // MMX registers - X86_REG_MM0=X86_MMX_OFFSET, - X86_REG_MM1, - X86_REG_MM2, - X86_REG_MM3, - X86_REG_MM4, - X86_REG_MM5, - X86_REG_MM6, - X86_REG_MM7, - - // XMM registers - X86_REG_XMM0=X86_XMM_OFFSET, - X86_REG_XMM1, - X86_REG_XMM2, - X86_REG_XMM3, - X86_REG_XMM4, - X86_REG_XMM5, - X86_REG_XMM6, - X86_REG_XMM7, - - // 8-bit registers - X86_REG_AL=X86_8BIT_OFFSET, - X86_REG_CL, - X86_REG_DL, - X86_REG_BL, - X86_REG_AH, - X86_REG_CH, - X86_REG_DH, - X86_REG_BH, - - // 16-bit registers - X86_REG_AX=X86_16BIT_OFFSET, - X86_REG_CX, - X86_REG_DX, - X86_REG_BX, - X86_REG_SP, - X86_REG_BP, - X86_REG_SI, - X86_REG_DI, - - // 32-bit registers - X86_REG_EAX=X86_32BIT_OFFSET, - X86_REG_ECX, - X86_REG_EDX, - X86_REG_EBX, - X86_REG_ESP, - X86_REG_EBP, - X86_REG_ESI, - X86_REG_EDI, - - // AMD64 8-bit registers - AMD64_REG_AL=AMD64_8BIT_OFFSET, - AMD64_REG_CL, - AMD64_REG_DL, - AMD64_REG_BL, - AMD64_REG_SPL, - AMD64_REG_BPL, - AMD64_REG_SIL, - AMD64_REG_DIL, - AMD64_REG_R8B, - AMD64_REG_R9B, - AMD64_REG_R10B, - AMD64_REG_R11B, - AMD64_REG_R12B, - AMD64_REG_R13B, - AMD64_REG_R14B, - AMD64_REG_R15B, - - // AMD64 16-bit registers - AMD64_REG_AX=AMD64_16BIT_OFFSET, - AMD64_REG_CX, - AMD64_REG_DX, - AMD64_REG_BX, - AMD64_REG_SP, - AMD64_REG_BP, - AMD64_REG_SI, - AMD64_REG_DI, - AMD64_REG_R8W, - AMD64_REG_R9W, - AMD64_REG_R10W, - AMD64_REG_R11W, - AMD64_REG_R12W, - AMD64_REG_R13W, - AMD64_REG_R14W, - AMD64_REG_R15W, - - // AMD64 32-bit registers - AMD64_REG_EAX=AMD64_32BIT_OFFSET, - AMD64_REG_ECX, - AMD64_REG_EDX, - AMD64_REG_EBX, - AMD64_REG_ESP, - AMD64_REG_EBP, - AMD64_REG_ESI, - AMD64_REG_EDI, - AMD64_REG_R8D, - AMD64_REG_R9D, - AMD64_REG_R10D, - AMD64_REG_R11D, - AMD64_REG_R12D, - AMD64_REG_R13D, - AMD64_REG_R14D, - AMD64_REG_R15D, - - // AMD64 64-bit registers - AMD64_REG_RAX=AMD64_64BIT_OFFSET, - AMD64_REG_RCX, - AMD64_REG_RDX, - AMD64_REG_RBX, - AMD64_REG_RSP, - AMD64_REG_RBP, - AMD64_REG_RSI, - AMD64_REG_RDI, - AMD64_REG_R8, - AMD64_REG_R9, - AMD64_REG_R10, - AMD64_REG_R11, - AMD64_REG_R12, - AMD64_REG_R13, - AMD64_REG_R14, - AMD64_REG_R15 -} X86_REGISTER; - -typedef enum _X86_TEST_REGISTER -{ - REG_TR0=0, - REG_TR1, - REG_TR2, - REG_TR3, - REG_TR4, - REG_TR5, - REG_TR6, - REG_TR7, - REG_TR8, - REG_TR9, - REG_TR10, - REG_TR11, - REG_TR12, - REG_TR13, - REG_TR14, - REG_TR15 -} X86_TEST_REGISTER; - -typedef enum _X86_CONTROL_REGISTER -{ - REG_CR0, - REG_CR1, - REG_CR2, - REG_CR3, - REG_CR4, - REG_CR5, - REG_CR6, - REG_CR7, - REG_CR8, - REG_CR9, - REG_CR10, - REG_CR11, - REG_CR12, - REG_CR13, - REG_CR14, - REG_CR15 -} X86_CONTROL_REGISTER; - -typedef enum _X86_DEBUG_REGISTER -{ - REG_DR0, - REG_DR1, - REG_DR2, - REG_DR3, - REG_DR4, - REG_DR5, - REG_DR6, - REG_DR7, - REG_DR8, - REG_DR9, - REG_DR10, - REG_DR11, - REG_DR12, - REG_DR13, - REG_DR14, - REG_DR15 -} X86_DEBUG_REGISTER; - -typedef enum _X86_MMX_REGISTER -{ - REG_MM0=0, - REG_MM1=1, - REG_MM2=2, - REG_MM3=3, - REG_MM4=4, - REG_MM5=5, - REG_MM6=6, - REG_MM7=7 -} X86_MMX_REGISTER; - -typedef enum _X86_SSE_REGISTER -{ - REG_XMM0=0, - REG_XMM1=1, - REG_XMM2=2, - REG_XMM3=3, - REG_XMM4=4, - REG_XMM5=5, - REG_XMM6=6, - REG_XMM7=7 -} X86_SSE_REGISTER; - -typedef enum _X86_FPU_REGISTER -{ - REG_ST0=0, - REG_ST1=1, - REG_ST2=2, - REG_ST3=3, - REG_ST4=4, - REG_ST5=5, - REG_ST6=6, - REG_ST7=7 -} X86_FPU_REGISTER; - -typedef enum _X86_8BIT_REGISTER -{ - REG_AL = 0, - REG_CL = 1, - REG_DL = 2, - REG_BL = 3, - REG_AH = 4, - REG_CH = 5, - REG_DH = 6, - REG_BH = 7 -} X86_8BIT_REGISTER; - -typedef enum _X86_16BIT_REGISTER -{ - REG_AX = 0, - REG_CX = 1, - REG_DX = 2, - REG_BX = 3, - REG_SP = 4, - REG_BP = 5, - REG_SI = 6, - REG_DI = 7 -} X86_16BIT_REGISTER; - -typedef enum _X86_32BIT_REGISTER -{ - REG_EAX = 0, - REG_ECX = 1, - REG_EDX = 2, - REG_EBX = 3, - REG_ESP = 4, - REG_EBP = 5, - REG_ESI = 6, - REG_EDI = 7 -} X86_32BIT_REGISTER; - -typedef enum _X86_SEGMENT -{ - SEG_ES = 0, - SEG_CS = 1, - SEG_SS = 2, - SEG_DS = 3, - SEG_FS = 4, - SEG_GS = 5, - SEG_MAX = 6 -} X86_SEGMENT; - -extern char *X86_Registers[]; - -#pragma pack(push,1) -typedef struct _MODRM -{ - U8 mod : 2; - U8 reg : 3; - U8 rm : 3; -} MODRM; -typedef struct _SIB -{ - U8 scale : 2; - U8 index : 3; - U8 base : 3; -} SIB; -typedef struct _REX -{ - U8 unused : 4; // bits 4,5,6,7 - U8 w : 1; // bit 3 - U8 r : 1; // bit 2 - U8 x : 1; // bit 1 - U8 b : 1; // bit 0 -} REX; -typedef struct _REX_MODRM -{ - U8 reg : 4; - U8 rm : 4; -} REX_MODRM; -typedef struct _REX_SIB -{ - U8 index : 4; - U8 base : 4; -} REX_SIB; -#pragma pack(pop) - -// -// Properties: -// If an operand is OP_COND_EXEC, it means that it is executed only if the pre-conditions are met. -// -// If if an instruction has one or more OP_COND_DST operands, then the actions are determined by -// whether the Opcode.Preconditions are met or not. If all the COND_* flags in Opcode.Preconditions -// are true, then the results are determined by ResultsIfTrue. If the preconditions are not met, then -// the results are determined by ResultsIfFalse. -// -// If Preconditions == NOCOND, then results in ResultsIfTrue are unconditional and ResultsIfFalse -// is ignored -// -typedef struct _X86_OPCODE -{ - struct _X86_OPCODE *Table; - CPU_TYPE CPU; // minimum CPU (starting with i386) - U32 MnemonicFlags; - char Mnemonic[X86_MAX_INSTRUCTION_LEN+1]; - U32 OperandFlags[X86_MAX_OPERANDS]; - U32 Preconditions; - U32 FlagsChanged; // changes in flags - U32 ResultsIfTrue; // results if Preconditions are met - U32 ResultsIfFalse; // results if Preconditions are not met -} X86_OPCODE; - -typedef struct _X86_INSTRUCTION -{ - struct _INSTRUCTION *Instruction; // the generic instruction format representing this instruction - - X86_OPCODE Opcode; - - U8 sib_b; - U8 modrm_b; - MODRM modrm; - SIB sib; - U8 rex_b; - REX rex; - REX_MODRM rex_modrm; - REX_SIB rex_sib; - - X86_SEGMENT DstSegment; - union - { - X86_SEGMENT Segment; - DWORD Selector; - }; - - // NOTE: these are for internal use, use Instruction->Operands[] - // - // If DstRegAddressing or SrcRegAddressing = TRUE then BaseRegister is the base register - // It is the operand represented by SIBOperand - // - // The operand indices of the destination operands is in DstOpIndex[0 to DstOpCount-1] - // The operand indices of the source operands is in SrcOpIndex[0 to SrcOpCount-1] - // - // These are used both for instructions like xadd/xchg (where both operands are source/destination) - // and to represent implicit registers (e.g., cmpxchg) - - U8 SrcOpIndex[3]; - U8 DstOpIndex[3]; - - // Addressing mode: - // If DstRegAddressing = TRUE, then these apply to DstReg - // If SrcRegAddressing = TRUE, then this applies to SrcReg[AddressIndex] - // If both are false, then SrcReg and DstReg are not addresses - X86_REGISTER BaseRegister; - X86_REGISTER IndexRegister; - - U8 Scale; - U8 HasDefault64Operand : 1; - U8 HasOperandSizePrefix : 1; - U8 HasAddressSizePrefix : 1; - U8 HasSegmentOverridePrefix : 1; - U8 HasLockPrefix : 1; - U8 HasRepeatWhileEqualPrefix : 1; - U8 HasRepeatWhileNotEqualPrefix : 1; - U8 HasBranchTakenPrefix : 1; - U8 HasBranchNotTakenPrefix : 1; - U8 HasDstAddressing : 1; - U8 HasSrcAddressing : 1; - U8 HasModRM : 1; - U8 HasBaseRegister : 1; - U8 HasIndexRegister : 1; - U8 HasFullDisplacement : 1; - U8 HasDstSegment : 1; // used for ins/cmps/scas/movs/etc which have 2 segments - U8 DstAddressIndex : 2; // DstOpIndex[DstAddressIndex] - U8 SrcAddressIndex : 2; // SrcOpIndex[SrcAddressIndex] - U8 DstOpCount : 2; - U8 SrcOpCount : 2; - U8 OperandSize : 4; - U8 AddressSize : 4; - U8 Relative : 1; - U8 HasSelector : 1; // segment is actually a selector - U8 Group : 5; - - S64 Displacement; - -} X86_INSTRUCTION; - -//////////////////////////////////////////////////////////////////////////////////// -// Exported functions -//////////////////////////////////////////////////////////////////////////////////// - -extern ARCHITECTURE_FORMAT_FUNCTIONS X86; - -// Instruction setup -BOOL X86_InitInstruction(struct _INSTRUCTION *Instruction); -void X86_CloseInstruction(struct _INSTRUCTION *Instruction); - -// Instruction translator -BOOL X86_TranslateInstruction(struct _INSTRUCTION *Instruction, BOOL Verbose); - -// Instruction decoder -BOOL X86_GetInstruction(struct _INSTRUCTION *Instruction, U8 *Address, DWORD Flags); - -// Function finding -U8 *X86_FindFunctionByPrologue(struct _INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, DWORD Flags); - -#ifdef __cplusplus -} -#endif -#endif // X86_DISASM_H - diff --git a/renderdoc/3rdparty/mhook/disasm-lib/disasm_x86_tables.h b/renderdoc/3rdparty/mhook/disasm-lib/disasm_x86_tables.h deleted file mode 100644 index 170bcc912..000000000 --- a/renderdoc/3rdparty/mhook/disasm-lib/disasm_x86_tables.h +++ /dev/null @@ -1,3656 +0,0 @@ -// Copyright (C) 2004, Matt Conover (mconover@gmail.com) -// -// The opcode tables in this file are based off the Intel Instruction Set Reference -// and an assortment of disassemblers, primarily libdisasm (by mammon) - -#ifndef DISASM_X86_TABLES -#define DISASM_X86_TABLES - -#pragma warning(disable: 4245) - -#define X86_GET_REG(val) ((val) & 7) -#define X86_GET_REG64(val) ((GET_REX_B(X86Instruction->rex_b) << 3) | ((val) & 7)) - -#define GET_MODRM_MOD(a) (((a) >> 6) & 3) // bits 6, 7 -#define GET_MODRM_REG(a) (((a) >> 3) & 7) // bits 3, 4, 5 -#define GET_MODRM_EXT(a) (((a) >> 3) & 7) // bits 3, 4, 5 -#define GET_MODRM_RM(a) ((a) & 7) // bits 0, 1, 2 - -#define GET_SIB_SCALE(a) (((a) >> 6) & 3) // bits 6, 7 -#define GET_SIB_INDEX(a) (((a) >> 3) & 7) // bits 3, 4, 5 -#define GET_SIB_BASE(a) ((a) & 7) // bits 0, 1, 2 - -#define REX_PREFIX_START 0x40 -#define REX_PREFIX_END 0x4F -#define GET_REX_W(r) (((r) & 8) >> 3) // bit 3 -#define GET_REX_R(r) (((r) & 4) >> 2) // bit 2 -#define GET_REX_X(r) (((r) & 2) >> 1) // bit 1 -#define GET_REX_B(r) ((r) & 1) // bit 0 -#define REX_MASK(n) ((n >> 16) & 0x0F) // bits 0-3 - -// Groupings to make the opcode table more readible -#define NOARGS { 0, 0, 0 } -#define NOCOND 0 -#define NOGROUP NULL -#define NOACTION 0 -#define NOCHANGE 0 -#define IGNORED 0 -#define NOINSTR NOGROUP, CPU_UNKNOWN, 0, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED -#define GROUP CPU_UNKNOWN, 0, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED -#define PREFIX NOGROUP, CPU_UNKNOWN, ITYPE_EXT_PREFIX, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED -#define EXT_FPU CPU_UNKNOWN, ITYPE_EXT_FPU, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED -#define EXT_64 CPU_UNKNOWN, ITYPE_EXT_64, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED -#define EXT_SUFFIX(a, b, c) CPU_UNKNOWN, ITYPE_EXT_SUFFIX, "", { a, b, c }, NOCOND, NOCHANGE, NOACTION, IGNORED -#define EXT_MODRM CPU_UNKNOWN, ITYPE_EXT_MODRM, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED - -#define SET_MODRM(modrm, src) \ -{ \ - (modrm).mod = GET_MODRM_MOD(src); \ - (modrm).reg = GET_MODRM_REG(src); \ - (modrm).rm = GET_MODRM_RM(src); \ -} - -#define SET_REX_MODRM(rex_modrm, rex, modrm) \ -{ \ - (rex_modrm).rm = ((rex).b << 3) | (modrm).rm; \ - (rex_modrm).reg = ((rex).r << 3) | (modrm).reg; \ -} - -#define SET_SIB(sib, src) \ -{ \ - (sib).scale = GET_SIB_SCALE(src); \ - (sib).index = GET_SIB_INDEX(src); \ - (sib).base = GET_SIB_BASE(src); \ -} - -#define SET_REX_SIB(rex_sib, rex, sib) \ -{ \ - (rex_sib).index = ((rex).x << 3) | (sib).index; \ - (rex_sib).base = ((rex).b << 3) | (sib).base; \ -} - -#define SET_REX(rex, src) \ -{ \ - (rex).w = GET_REX_W(src); \ - (rex).r = GET_REX_R(src); \ - (rex).x = GET_REX_X(src); \ - (rex).b = GET_REX_B(src); \ -} - -// Addressing modes -#define AMODE_A 0x00010000 -#define AMODE_C 0x00020000 -#define AMODE_D 0x00030000 -#define AMODE_E 0x00040000 -#define AMODE_G 0x00050000 -#define AMODE_I 0x00060000 -#define AMODE_J 0x00070000 -#define AMODE_M 0x00080000 -#define AMODE_O 0x00090000 -#define AMODE_P 0x000A0000 -#define AMODE_Q 0x000B0000 -#define AMODE_R 0x000C0000 -#define AMODE_S 0x000D0000 -#define AMODE_T 0x000E0000 -#define AMODE_V 0x000F0000 -#define AMODE_W 0x00100000 -#define AMODE_X 0x00110000 -#define AMODE_Y 0x00120000 -#define AMODE_PR 0x00130000 -#define AMODE_VR 0x00140000 -#define AMODE_xlat 0x00150000 - -// Operand types -#define OPTYPE_a 0x01000000 -#define OPTYPE_b 0x02000000 -#define OPTYPE_d 0x03000000 -#define OPTYPE_p 0x04000000 -#define OPTYPE_q 0x05000000 -#define OPTYPE_dt 0x06000000 -#define OPTYPE_v 0x07000000 -#define OPTYPE_w 0x08000000 -#define OPTYPE_ps 0x09000000 // packed 128-bit single real -#define OPTYPE_pd 0x0A000000 // packed 128-bit double real -#define OPTYPE_pb 0x0B000000 // packed BCD (10 bytes, 18-bit precision) -#define OPTYPE_ss 0x0C000000 // scalar single real -#define OPTYPE_sd 0x0D000000 // scalar double real -#define OPTYPE_se 0x0E000000 // scalar extended real -#define OPTYPE_fev 0x0F000000 // FPU environment (28 bytes if 32-bit modes, 14 bytes in 16-bit mode) -#define OPTYPE_fst1 0x10000000 // FPU state (108 bytes in 32-bit modes, 94 bytes in 16-bit real mode) -#define OPTYPE_fst2 0x11000000 // FPU/MMX/XMM/MXCSR state (512 bytes) -#define OPTYPE_z 0x12000000 -#define OPTYPE_o 0x13000000 -#define OPTYPE_dq 0x14000000 // OPTYPE_d or OPTYPE_o -#define OPTYPE_mw 0x15000000 // word if memory, register size otherwise -#define OPTYPE_sso 0x16000000 // OPTYPE_ss or OPTYPE_o -#define OPTYPE_sdo 0x17000000 // OPTYPE_ss or OPTYPE_o -#define OPTYPE_cpu 0x18000000 // pointer to CPU state structure -#define OPTYPE_lea 0x19000000 // size set by other operand -// NOTE: if you change this, you must also update OptypeHandlers[] in disasm_x86.c -// Be sure to preserve the ordering - -////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Registers -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -static char *Addressing16[8] = {"bx+si","bx+di","bp+si","bp+di","si","di","bp","bx"}; -static char *MMX_Registers[8] = {"mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"}; -static char *SSE_Registers[8] = {"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"}; -static char *DR_Registers[8] = {"dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7"}; -static char *CR_Registers[8] = {"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7"}; -static char *TR_Registers[8] = {"tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7"}; -static char *FPU_Registers[8] = {"st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"}; -static char *Segments[8] = {"es", "cs", "ss", "ds", "fs", "gs", "ERROR", "ERROR"}; -static char *Registers8[8] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" }; -static char *Registers16[8] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di" }; -static char *Registers32[8] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" }; -static char *REX_Registers8[16] = {"al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }; -static char *REX_Registers16[16] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" }; -static char *REX_Registers32[16] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" }; -static char *REX_Registers64[16] = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" }; -static char *DataSizes[8+1] = {"byte ptr", "word ptr", "dword ptr", "6_byte ptr", "qword ptr", "10_byte ptr", "INVALID PTR", "INVALID PTR", "oword ptr"}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// FPU constants -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -BYTE float_0[10] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -BYTE float_1[10] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x3F }; -BYTE float_l2t[10] = { 0xFE, 0x8A, 0x1B, 0xCD, 0x4B, 0x78, 0x9A, 0xD4, 0x00, 0x40 }; -BYTE float_l2e[10] = { 0xBC, 0xF0, 0x17, 0x5C, 0x29, 0x3B, 0xAA, 0xB8, 0xFF, 0x3F }; -BYTE float_pi[10] = { 0x35, 0xC2, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9, 0x00, 0x40 }; -BYTE float_lg2[10] = { 0x99, 0xF7, 0xCF, 0xFB, 0x84, 0x9A, 0x20, 0x9A, 0xFD, 0x3F }; -BYTE float_ln2[10] = { 0xAC, 0x79, 0xCF, 0xD1, 0xF7, 0x17, 0x72, 0xB1, 0xFE, 0x3F }; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Tables -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -extern X86_OPCODE X86_Opcodes_2[0x100]; -extern X86_OPCODE X86_Group_1_80[8], X86_Group_1_81[8], X86_Group_1_82[8], X86_Group_1_83[8], X86_Group_2_C0[8], X86_Group_2_C1[8], X86_Group_2_D0[8], X86_Group_2_D1[8], X86_Group_2_D2[8], X86_Group_2_D3[8], X86_Group_3_F6[8], X86_Group_3_F7[8], X86_Group_4[8], X86_Group_5[8], X86_Group_6[8], X86_Group_7[8], X86_Group_8[8], X86_Group_9[8], X86_Group_10[8], X86_Group_11[8], X86_Group_12_C6[8], X86_Group_12_C7[8], X86_Group_13[8], X86_Group_14[8], X86_Group_15[8], X86_Group_16[8], X86_Group_17[8], X86_Group_P[8]; -extern X86_OPCODE X86_SSE[0x300], X86_SSE2_Group_13[24], X86_SSE2_Group_14[24], X86_SSE2_Group_15[24]; -extern X86_OPCODE X86_ESC_0[0x48], X86_ESC_1[0x48], X86_ESC_2[0x48], X86_ESC_3[0x48], X86_ESC_3[0x48], X86_ESC_4[0x48], X86_ESC_5[0x48], X86_ESC_6[0x48], X86_ESC_7[0x48]; -extern X86_OPCODE X86_3DNOW_0F[0x100]; -extern X86_OPCODE X86_0F01_ModRM[0x100]; -extern X86_OPCODE X86_Opcode_63[2], X86_Opcode_0F05[2]; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Opcode tables -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -X86_OPCODE X86_Opcodes_1[0x100] = // 1 byte opcodes -{ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_ES | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_ES | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x08 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x09 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0A */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0B */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0C */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0D */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_CS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x0E */ - { X86_Opcodes_2, GROUP }, /* 0x0F */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x10 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x11 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x12 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x13 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x14 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x15 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_SS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x16 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_SS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x17 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x18 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x19 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1A */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1B */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1C */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1D */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_DS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x1E */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_DS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x1F */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x20 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x21 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x22 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x23 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x24 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x25 */ - { PREFIX }, /* 0x26 */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "daa", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_AF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x27 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x28 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x29 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2A */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2B */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2C */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2D */ - { PREFIX }, /* 0x2E */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "das", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_AF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x2F */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x30 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x31 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x32 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x33 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x34 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x35 */ - { PREFIX }, /* 0x36 */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aaa", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_AF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x37 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x38 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x39 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_G | OPTYPE_b | OP_SRC, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3A */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3B */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { OPTYPE_REG_AL | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3C */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { OPTYPE_REG_xAX_BIG | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_z | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3D */ - { PREFIX }, /* 0x3E */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aas", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_AF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x3F */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x40 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x41 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x42 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x43 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x44 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x45 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x46 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x47 */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x48 */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x49 */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4A */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4B */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4C */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4D */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4E */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4F */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x50 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x51 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x52 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x53 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x54 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x55 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x56 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x57 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x58 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x59 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5A */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5B */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5C */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5D */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5E */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5F */ - { NOGROUP, CPU_I386, ITYPE_PUSHA, "pushad", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x60 */ - { NOGROUP, CPU_I386, ITYPE_POPA, "popad", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x61 */ - { NOGROUP, CPU_I386, ITYPE_BOUNDS, "bound", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_M | OPTYPE_a | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x62 */ - { X86_Opcode_63, EXT_64 }, /* 0x63 */ - { PREFIX }, /* 0x64 */ - { PREFIX }, /* 0x65 */ - { PREFIX }, /* 0x66 */ - { PREFIX }, /* 0x67 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { AMODE_I | OPTYPE_z | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x68 */ - { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_z | OP_SIGNED | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x69 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6A */ - { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x6B */ - { NOGROUP, CPU_I386, ITYPE_IN, "insb", { AMODE_Y | OPTYPE_b | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DEC | xCX_REP_DEC, xDI_INC | xCX_REP_DEC }, /* 0x6C */ - { NOGROUP, CPU_I386, ITYPE_IN, "insd", { AMODE_Y | OPTYPE_z | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DECx | xCX_REP_DEC, xDI_INCx | xCX_REP_DEC }, /* 0x6D */ - { NOGROUP, CPU_I386, ITYPE_OUT, "outsb", { OPTYPE_REG_DX | OP_SYS | OP_DST, AMODE_X | OPTYPE_b | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DEC | xCX_REP_DEC, xSI_INC | xCX_REP_DEC }, /* 0x6E */ - { NOGROUP, CPU_I386, ITYPE_OUT, "outsd", { OPTYPE_REG_DX | OP_SYS | OP_DST, AMODE_X | OPTYPE_z | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DECx | xCX_REP_DEC, xSI_INCx | xCX_REP_DEC}, /* 0x6F */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jo", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_O, NOCHANGE, OP1_DST, NOACTION }, /* 0x70 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jno", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NO, NOCHANGE, OP1_DST, NOACTION }, /* 0x71 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jb", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_C, NOCHANGE, OP1_DST, NOACTION }, /* 0x72 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnb", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NC, NOCHANGE, OP1_DST, NOACTION }, /* 0x73 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_Z, NOCHANGE, OP1_DST, NOACTION }, /* 0x74 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NZ, NOCHANGE, OP1_DST, NOACTION }, /* 0x75 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jbe", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_BE, NOCHANGE, OP1_DST, NOACTION }, /* 0x76 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "ja", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_A, NOCHANGE, OP1_DST, NOACTION }, /* 0x77 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "js", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_S, NOCHANGE, OP1_DST, NOACTION }, /* 0x78 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jns", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NS, NOCHANGE, OP1_DST, NOACTION }, /* 0x79 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpe", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PE, NOCHANGE, OP1_DST, NOACTION }, /* 0x7A */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpo", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PO, NOCHANGE, OP1_DST, NOACTION }, /* 0x7B */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jl", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_L, NOCHANGE, OP1_DST, NOACTION }, /* 0x7C */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jge", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_GE, NOCHANGE, OP1_DST, NOACTION }, /* 0x7D */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jle", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_LE, NOCHANGE, OP1_DST, NOACTION }, /* 0x7E */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jg", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_G, NOCHANGE, OP1_DST, NOACTION }, /* 0x7F */ - { X86_Group_1_80, GROUP }, /* 0x80 Eb Ib */ - { X86_Group_1_81, GROUP }, /* 0x81 Ev Iz */ - { X86_Group_1_82, GROUP }, /* 0x82 Eb Ib */ - { X86_Group_1_83, GROUP }, /* 0x83 Ev Ib */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x84 */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x85 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, AMODE_G | OPTYPE_b | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x86 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_G | OPTYPE_v | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x87 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x88 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x89 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8A */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8B */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_mw | OP_DST, AMODE_S | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8C */ - { NOGROUP, CPU_I386, ITYPE_LEA, "lea", { AMODE_G | OPTYPE_v | OP_DST, AMODE_M | OPTYPE_lea | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8D */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_S | OPTYPE_w | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8E */ - { X86_Group_10, GROUP }, /* 0x8F */ - { NOGROUP, CPU_I386, ITYPE_NOP, "nop", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x90 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x91 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x92 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x93 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x94 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x95 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x96 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x97 */ - { NOGROUP, CPU_I386, ITYPE_SZCONV, "cwde", { OPTYPE_REG_xAX_BIG | OP_SIGNED | OP_DST, OPTYPE_REG_xAX_SMALL | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x98 */ - { NOGROUP, CPU_I386, ITYPE_SZCONV, "cdq", { OPTYPE_xDX_HI_xAX_LO | OP_SIGNED | OP_DST, OPTYPE_REG_xAX_BIG | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x99 */ - { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_A | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9A */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "wait", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9B */ - { NOGROUP, CPU_I386, ITYPE_PUSHF, "pushf", { OPTYPE_xFLAGS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9C */ - { NOGROUP, CPU_I386, ITYPE_POPF, "popf", { OPTYPE_xFLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_ALL_MOD, NOACTION, IGNORED }, /* 0x9D */ - { NOGROUP, CPU_I386, ITYPE_MOV, "sahf", { OPTYPE_FLAGS | OP_DST, OPTYPE_REG_AH | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_AF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x9E */ - { NOGROUP, CPU_I386, ITYPE_MOV, "lahf", { OPTYPE_REG_AH | OP_DST, OPTYPE_FLAGS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9F */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG_AL | OP_DST, AMODE_O | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA0 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_O | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA1 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_O | OPTYPE_b | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA2 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_O | OPTYPE_v | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA3 */ - { NOGROUP, CPU_I386, ITYPE_STRMOV, "movsb", { AMODE_Y | OPTYPE_b | OP_DST, AMODE_X | OPTYPE_b | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DEC | xSI_DEC | xCX_REP_DEC, xDI_INC | xSI_INC | xCX_REP_DEC}, /* 0xA4 */ - { NOGROUP, CPU_I386, ITYPE_STRMOV, "movsd", { AMODE_Y | OPTYPE_z | OP_DST, AMODE_X | OPTYPE_z | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DECx | xSI_DECx| xCX_REP_DEC, xDI_INCx | xSI_INCx | xCX_REP_DEC }, /* 0xA5 */ - { NOGROUP, CPU_I386, ITYPE_STRCMP, "cmpsb", { AMODE_X | OPTYPE_b | OP_SRC, AMODE_Y | OPTYPE_b | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DEC | xSI_DEC | xCX_REP_DEC, xDI_INC | xSI_INC | xCX_REP_DEC }, /* 0xA6 */ - { NOGROUP, CPU_I386, ITYPE_STRCMP, "cmpsd", { AMODE_X | OPTYPE_z | OP_SRC, AMODE_Y | OPTYPE_z | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DECx | xSI_DECx | xCX_REP_DEC, xDI_INCx | xSI_INCx | xCX_REP_DEC}, /* 0xA7 */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { OPTYPE_REG_AL | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0xA8 */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { OPTYPE_REG_xAX_BIG | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0xA9 */ - { NOGROUP, CPU_I386, ITYPE_STRSTOR, "stosb", { AMODE_Y | OPTYPE_b | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DEC | xSI_DEC | xCX_REP_DEC, xDI_INC | xSI_INC | xCX_REP_DEC }, /* 0xAA */ - { NOGROUP, CPU_I386, ITYPE_STRSTOR, "stosd", { AMODE_Y | OPTYPE_z | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DECx | xSI_DECx | xCX_REP_DEC, xDI_INCx | xSI_INCx | xCX_REP_DEC }, /* 0xAB */ - { NOGROUP, CPU_I386, ITYPE_STRLOAD, "lodsb", { OPTYPE_REG_AL | OP_DST, AMODE_X | OPTYPE_b | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DEC | xCX_REP_DEC, xSI_INC | xCX_REP_DEC }, /* 0xAC */ - { NOGROUP, CPU_I386, ITYPE_STRLOAD, "lodsd", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_X | OPTYPE_z | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DECx | xCX_REP_DEC, xSI_INCx | xCX_REP_DEC }, /* 0xAD */ - { NOGROUP, CPU_I386, ITYPE_STRCMP, "scasb", { OPTYPE_REG_AL | OP_SRC, AMODE_Y | OPTYPE_b | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DEC | xCX_REP_DEC, xDI_INC | xCX_REP_DEC }, /* 0xAE */ - { NOGROUP, CPU_I386, ITYPE_STRCMP, "scasd", { OPTYPE_REG_xAX_BIG | OP_SRC, AMODE_Y | OPTYPE_z | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DECx, xDI_INCx }, /* 0xAF */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB0 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB1 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB2 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB3 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB4 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB5 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB6 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB7 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB8 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB9 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBA */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBB */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBC */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBD */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBE */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBF */ - { X86_Group_2_C0, GROUP }, /* 0xC0 Eb Ib */ - { X86_Group_2_C1, GROUP }, /* 0xC1 Ev Ib */ - { NOGROUP, CPU_I386, ITYPE_RET, "ret", { AMODE_I | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC2 */ - { NOGROUP, CPU_I386, ITYPE_RET, "ret", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC3 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "les", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC4 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "lds", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC5 */ - { X86_Group_12_C6, GROUP }, /* 0xC6 Eb Ib */ - { X86_Group_12_C7, GROUP }, /* 0xC7 Ev Iz */ - { NOGROUP, CPU_I386, ITYPE_ENTER, "enter", { OPTYPE_REG_xBP | OP_SRC | OP_DST, AMODE_I | OPTYPE_w | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC8 */ - { NOGROUP, CPU_I386, ITYPE_LEAVE, "leave", { OPTYPE_REG_xBP | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC9 */ - { NOGROUP, CPU_I386, ITYPE_RET, "retf", { AMODE_I | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCA */ - { NOGROUP, CPU_I386, ITYPE_RET, "retf", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCB */ - { NOGROUP, CPU_I386, ITYPE_DEBUG, "int3", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCC */ - { NOGROUP, CPU_I386, ITYPE_TRAP, "int", { AMODE_I | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCD */ - { NOGROUP, CPU_I386, ITYPE_OFLOW, "into", NOARGS, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xCE */ - { NOGROUP, CPU_I386, ITYPE_TRAPRET, "iret", NOARGS, NOCOND, FLAG_ALL_MOD, NOACTION, IGNORED }, /* 0xCF */ - { X86_Group_2_D0, GROUP }, /* 0xD0 Eb, 1 */ - { X86_Group_2_D1, GROUP }, /* 0xD1 Ev, 1 */ - { X86_Group_2_D2, GROUP }, /* 0xD2 Eb, CL */ - { X86_Group_2_D3, GROUP }, /* 0xD3 Ev, CL */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aam", { OPTYPE_REG_AX | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD, NOACTION, IGNORED }, /* 0xD4 */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aad", { OPTYPE_REG_AX | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD, NOACTION, IGNORED }, /* 0xD5 */ - { NOGROUP, CPU_I386, ITYPE_ARITH, "salc", { OPTYPE_REG_AL | OP_DST, OPTYPE_FF | OP_SRC, OPTYPE_0 | OP_SRC }, COND_C, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0xD6 */ - { NOGROUP, CPU_I386, ITYPE_XLAT, "xlat", { OPTYPE_REG_AL | OP_DST, AMODE_xlat | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD7 */ - { X86_ESC_0, EXT_FPU }, /* 0xD8 */ - { X86_ESC_1, EXT_FPU }, /* 0xD9 */ - { X86_ESC_2, EXT_FPU }, /* 0xDA */ - { X86_ESC_3, EXT_FPU }, /* 0xDB */ - { X86_ESC_4, EXT_FPU }, /* 0xDC */ - { X86_ESC_5, EXT_FPU }, /* 0xDD */ - { X86_ESC_6, EXT_FPU }, /* 0xDE */ - { X86_ESC_7, EXT_FPU }, /* 0xDF */ - { NOGROUP, CPU_I386, ITYPE_LOOPCC, "loopnz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_NZ | COND_NZ, NOCHANGE, OP1_DST | xCX_DEC, NOACTION }, /* 0xE0 */ - { NOGROUP, CPU_I386, ITYPE_LOOPCC, "loopz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_NZ | COND_Z, NOCHANGE, OP1_DST | xCX_DEC, NOACTION }, /* 0xE1 */ - { NOGROUP, CPU_I386, ITYPE_LOOPCC, "loop", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_NZ, NOCHANGE, OP1_DST | xCX_DEC, NOACTION }, /* 0xE2 */ - { NOGROUP, CPU_I386, ITYPE_LOOPCC, "jecxz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_Z, NOCHANGE, OP1_DST, NOACTION }, /* 0xE3 */ - { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE4 */ - { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_b | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE5 */ - { NOGROUP, CPU_I386, ITYPE_OUT, "out", { AMODE_I | OPTYPE_b | OP_SYS | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE6 */ - { NOGROUP, CPU_I386, ITYPE_OUT, "out", { AMODE_I | OPTYPE_b | OP_SYS | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE7 */ - { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_J | OPTYPE_z | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE8 */ - { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_J | OPTYPE_z | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE9 */ - { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_A | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEA */ - { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_J | OPTYPE_b | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEB */ - { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_AL | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEC */ - { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_xAX_BIG | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xED */ - { NOGROUP, CPU_I386, ITYPE_OUT, "out", { OPTYPE_REG_DX | OP_SYS | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEE */ - { NOGROUP, CPU_I386, ITYPE_OUT, "out", { OPTYPE_REG_DX | OP_SYS | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEF */ - { PREFIX }, /* 0xF0 */ - { NOGROUP, CPU_I386, ITYPE_DEBUG, "int1", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, // aka icebp /* 0xF1 */ - { PREFIX }, /* 0xF2 */ - { PREFIX }, /* 0xF3 */ - { NOGROUP, CPU_I386, ITYPE_HALT, "hlt", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF4 */ - { NOGROUP, CPU_I386, ITYPE_TOGCF, "cmc", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_CF_TOG, IGNORED }, /* 0xF5 */ - { X86_Group_3_F6, GROUP }, /* 0xF6 Eb */ - { X86_Group_3_F7, GROUP }, /* 0xF7 Ev */ - { NOGROUP, CPU_I386, ITYPE_CLEARCF, "clc", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_CF_CLR, NOACTION, IGNORED }, /* 0xF8 */ - { NOGROUP, CPU_I386, ITYPE_SETCF, "stc", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_CF_SET, NOACTION, IGNORED }, /* 0xF9 */ - { NOGROUP, CPU_I386, ITYPE_CLEARIF, "cli", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_IF_CLR, NOACTION, IGNORED }, /* 0xFA */ - { NOGROUP, CPU_I386, ITYPE_SETIF, "sti", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_IF_SET, NOACTION, IGNORED }, /* 0xFB */ - { NOGROUP, CPU_I386, ITYPE_CLEARDF, "cld", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_DF_CLR, NOACTION, IGNORED }, /* 0xFC */ - { NOGROUP, CPU_I386, ITYPE_SETDF, "std", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_DF_SET, NOACTION, IGNORED }, /* 0xFD */ - { X86_Group_4, GROUP }, /* 0xFE */ - { X86_Group_5, GROUP }, /* 0xFF */ -}; - -X86_OPCODE X86_Opcodes_2[0x100] = // 2 byte opcodes -{ - { X86_Group_6, GROUP }, /* 0x00 */ - { X86_0F01_ModRM, EXT_MODRM }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lar", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lsl", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { X86_Opcode_0F05, EXT_64 }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "clts", { OPTYPE_CR0 | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_SYSCALLRET, "sysret", { OPTYPE_STAR_MSR | OP_MSR | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ - // 0F 07 could also be this undocumented instruction on older CPUs: - // { NOGROUP, CPU_I386, ITYPE_SYSTEM, "loadall", { AMODE_Y | OPTYPE_cpu | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ - { NOGROUP, CPU_I486, ITYPE_SYSTEM, "invd", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x08 */ - { NOGROUP, CPU_I486, ITYPE_SYSTEM, "wbinvd", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x09 */ - { NOINSTR }, /* 0x0A */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_INVALID, "undef" /* aka UD2 */, NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x0B */ - { NOINSTR }, /* 0x0C */ - { X86_Group_P, GROUP }, /* 0x0D */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "femms", { OPTYPE_FPU_TAG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x0E */ - { X86_3DNOW_0F, EXT_SUFFIX(AMODE_P | OPTYPE_q, AMODE_Q | OPTYPE_q, 0) }, /* 0x0F */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movups", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x10 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movups", { AMODE_W | OPTYPE_ps | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x11 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movlps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x12 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movlps", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x13 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "unpcklps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x14 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "unpckhps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x15 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movhps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x16 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movhps", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x17 */ - { X86_Group_17, GROUP }, /* 0x18 */ - { NOINSTR }, /* 0x19 */ - { NOINSTR }, /* 0x1A */ - { NOINSTR }, /* 0x1B */ - { NOINSTR }, /* 0x1C */ - { NOINSTR }, /* 0x1D */ - { NOINSTR }, /* 0x1E */ - { NOINSTR }, /* 0x1F */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_R | OPTYPE_dq | OP_DST, AMODE_C | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x20 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_R | OPTYPE_dq | OP_DST, AMODE_D | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x21 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_C | OPTYPE_dq | OP_DST, AMODE_R | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x22 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_D | OPTYPE_dq | OP_DST, AMODE_R | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x23 */ - { NOINSTR }, /* 0x24 */ - //{ NOGROUP, CPU_I486, ITYPE_MOV, "mov", { AMODE_R | OPTYPE_d | OP_DST, AMODE_T | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x24 */ - { NOINSTR }, /* 0x25 */ - { NOINSTR }, /* 0x26 */ - //{ NOGROUP, CPU_I486, ITYPE_MOV, "mov", { AMODE_T | OPTYPE_d | OP_DST, AMODE_R | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x26 */ - { NOINSTR }, /* 0x27 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movaps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x28 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movaps", { AMODE_W | OPTYPE_ps | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x29 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtpi2ps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2A */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movntps", { AMODE_M | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2B */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvttps2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2C */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtps2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2D */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "ucomiss", { AMODE_V | OPTYPE_ss | OP_SRC, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, /* 0x2E */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "comiss", { AMODE_V | OPTYPE_ps | OP_SRC, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, /* 0x2F */ - { NOGROUP, CPU_PENTIUM, ITYPE_SYSTEM, "wrmsr", { OPTYPE_REG_ECX | OP_MSR | OP_DST, OPTYPE_EDX_HI_EAX_LO | OP_SRC, 0 } , NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x30 */ - { NOGROUP, CPU_PENTIUM, ITYPE_SYSTEM, "rdtsc", { OPTYPE_EDX_HI_EAX_LO | OP_DST, OPTYPE_TSC | OP_MSR | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x31 */ - { NOGROUP, CPU_PENTIUM, ITYPE_SYSTEM, "rdmsr", { OPTYPE_EDX_HI_EAX_LO | OP_DST, OPTYPE_REG_ECX | OP_MSR | OP_SRC, 0 } , NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x32 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_OTHER, "rdpmc", { OPTYPE_EDX_HI_EAX_LO | OP_DST, OPTYPE_REG_ECX | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x33 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSCALL, "sysenter", { OPTYPE_CS_MSR | OP_MSR | OP_SRC, OPTYPE_EIP_MSR | OP_MSR | OP_SRC, OPTYPE_ESP_MSR | OP_MSR | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x34 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSCALLRET, "sysexit", { OPTYPE_CS_MSR | OP_MSR | OP_SRC, OPTYPE_EIP_MSR | OP_MSR | OP_SRC, OPTYPE_ESP_MSR | OP_MSR | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x35 */ - { NOINSTR }, /* 0x36 */ - { NOINSTR }, /* 0x37 */ - { NOINSTR }, /* 0x38 */ - { NOINSTR }, /* 0x39 */ - { NOINSTR }, /* 0x3A */ - { NOINSTR }, /* 0x3B */ - { NOINSTR }, /* 0x3C */ - { NOINSTR }, /* 0x3D */ - { NOINSTR }, /* 0x3E */ - { NOINSTR }, /* 0x3F */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovo", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_O, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x40 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovno", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NO, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x41 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovc", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_C, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x42 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovnc", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NC, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x43 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovz", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_Z, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x44 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovnz", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NZ, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x45 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovbe", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_BE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x46 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmova", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_A, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x47 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovs", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_S, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x48 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovns", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NS, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x49 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovpe", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_PE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4A */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovpo", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_PO, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4B */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovl", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_L, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4C */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovge", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_GE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4D */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovle", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_LE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4E */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovg", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_G, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4F */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "movmskps", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR | OPTYPE_ps| OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x50 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "sqrtps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x51 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "rsqrtps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x52 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "rcpps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x53 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_AND, "andps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x54 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_AND, "andnps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x55 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_OR, "orps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x56 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_XOR, "xorps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x57 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_ADD, "addps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x58 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MUL, "mulps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x59 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtps2pd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5A */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtdq2ps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5B */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_SUB, "subps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5C */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "minps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5D */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_DIV, "divps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5E */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "maxps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5F */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpcklbw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x60 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpcklwd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x61 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckldq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x62 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "packsswb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x63 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpgtb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x64 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpgtw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x65 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpgtd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x66 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "packuswb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x67 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckhbw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x68 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckhwd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x69 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckhdq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6A */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "packssdw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6B */ - { NOINSTR }, /* 0x6C */ - { NOINSTR }, /* 0x6D */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6E */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6F */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pshufw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x70 */ - { X86_Group_13, GROUP }, /* 0x71 */ - { X86_Group_14, GROUP }, /* 0x72 */ - { X86_Group_15, GROUP }, /* 0x73 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpeqb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x74 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpeqw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x75 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpeqd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x76 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "emms", { OPTYPE_FPU_TAG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x77 */ - { NOINSTR }, /* 0x78 */ - { NOINSTR }, /* 0x79 */ - { NOINSTR }, /* 0x7A */ - { NOINSTR }, /* 0x7B */ - { NOINSTR }, /* 0x7C */ - { NOINSTR }, /* 0x7D */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movd", { AMODE_E | OPTYPE_dq | OP_DST, AMODE_P | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x7E */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movq", { AMODE_Q | OPTYPE_q | OP_DST, AMODE_P | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x7F */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jo", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_O, NOCHANGE, OP1_DST, NOACTION }, /* 0x80 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jno", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NO, NOCHANGE, OP1_DST, NOACTION }, /* 0x81 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jb", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_C, NOCHANGE, OP1_DST, NOACTION }, /* 0x82 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnb", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NC, NOCHANGE, OP1_DST, NOACTION }, /* 0x83 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jz", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_Z, NOCHANGE, OP1_DST, NOACTION }, /* 0x84 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnz", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NZ, NOCHANGE, OP1_DST, NOACTION }, /* 0x85 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jbe", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_BE, NOCHANGE, OP1_DST, NOACTION }, /* 0x86 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "ja", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_A, NOCHANGE, OP1_DST, NOACTION }, /* 0x87 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "js", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_S, NOCHANGE, OP1_DST, NOACTION }, /* 0x88 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jns", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NS, NOCHANGE, OP1_DST, NOACTION }, /* 0x89 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpe", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PE, NOCHANGE, OP1_DST, NOACTION }, /* 0x8A */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpo", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PO, NOCHANGE, OP1_DST, NOACTION }, /* 0x8B */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jl", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_L, NOCHANGE, OP1_DST, NOACTION }, /* 0x8C */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jge", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_GE, NOCHANGE, OP1_DST, NOACTION }, /* 0x8D */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jle", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_LE, NOCHANGE, OP1_DST, NOACTION }, /* 0x8E */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jg", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_G, NOCHANGE, OP1_DST, NOACTION }, /* 0x8F */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "seto", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_O, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x90 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setno", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NO, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x91 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setb", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_C, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x92 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setnb", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NC, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x93 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "sete", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_Z, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x94 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setne", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NZ, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x95 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setbe", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_BE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x96 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "seta", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_A, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x97 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "sets", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_S, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x98 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setns", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NS, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x99 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setpe", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_PE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9A */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setpo", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_PO, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9B */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setl", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_L, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9C */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setge", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_GE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9D */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setle", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_LE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9E */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setg", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_G, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9F */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_FS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA0 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_FS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA1 */ - { NOGROUP, CPU_PENTIUM, ITYPE_CPUID, "cpuid", { OPTYPE_EDX_ECX_EBX_EAX | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA2 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bt", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xA3 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shld", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xA4 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shld", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, OPTYPE_REG_CL | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xA5 */ - { NOINSTR }, /* 0xA6 */ - { NOINSTR }, /* 0xA7 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_GS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA8 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_GS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA9 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "rsm", NOARGS, NOCOND, FLAG_ALL_MOD, NOACTION, IGNORED }, /* 0xAA */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bts", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAB */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shrd", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAC */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shrd", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, OPTYPE_REG_CL | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAD */ - { X86_Group_16, GROUP }, /* 0xAE */ - { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAF */ - { NOGROUP, CPU_I486, ITYPE_XCHGCC, "cmpxchg", { AMODE_E | OPTYPE_b | OP_SRC | OP_COND_DST, OPTYPE_REG_AL | OP_SRC | OP_COND_DST, AMODE_G | OPTYPE_b | OP_COND_SRC }, COND_OP1_EQ_OP2, FLAG_COMMON_MOD, OP1_DST | OP3_SRC, OP2_DST | OP1_SRC }, /* 0xB0 */ - { NOGROUP, CPU_I486, ITYPE_XCHGCC, "cmpxchg", { AMODE_E | OPTYPE_v | OP_SRC | OP_COND_DST, OPTYPE_REG_xAX_BIG | OP_SRC | OP_COND_DST, AMODE_G | OPTYPE_v | OP_COND_SRC }, COND_OP1_EQ_OP2, FLAG_COMMON_MOD, OP1_DST | OP3_SRC, OP2_DST | OP1_SRC }, /* 0xB1 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "lss", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB2 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "btr", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xB3 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "lfs", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB4 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "lgs", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB5 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "movzx", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB6 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "movzx", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB7 */ - { NOINSTR }, /* 0xB8 */ - { X86_Group_11, GROUP }, /* 0xB9 */ - { X86_Group_8, GROUP }, /* 0xBA */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "btc", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xBB */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bsf", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0xBC */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bsr", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0xBD */ - { NOGROUP, CPU_I386, ITYPE_MOV, "movsx", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBE */ - { NOGROUP, CPU_I386, ITYPE_MOV, "movsx", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBF */ - { NOGROUP, CPU_I486, ITYPE_XCHGADD, "xadd", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, AMODE_G | OPTYPE_b | OP_SRC | OP_DST, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0xC0 */ - { NOGROUP, CPU_I486, ITYPE_XCHGADD, "xadd", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_G | OPTYPE_v | OP_SRC | OP_DST, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0xC1 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "cmpps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0xC2 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movnti", { AMODE_M | OPTYPE_dq | OP_DST, AMODE_G | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC3 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pinsrw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC4 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pextrw", { AMODE_G | OPTYPE_d | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC5 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "shufps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC6 */ - { X86_Group_9, GROUP }, /* 0xC7 */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC8 */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC9 */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCA */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCB */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCC */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCD */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCE */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCF */ - { NOINSTR }, /* 0xD0 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD1 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrld", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD2 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD3 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_ADD, "paddq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD4 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MUL, "pmullw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD5 */ - { NOINSTR }, /* 0xD6 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pmovmskb", { AMODE_G | OPTYPE_d | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD7 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubusb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD8 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubusw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD9 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pminub", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDA */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_AND, "pand", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDB */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddusb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDC */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddusw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDD */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pmaxub", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDE */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_AND, "pandn", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDF */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pavgb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE0 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psraw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE1 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrad", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE2 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pavgw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE3 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MUL, "pmulhuw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE4 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MUL, "pmulhw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE5 */ - { NOINSTR }, /* 0xE6 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movntq", { AMODE_M | OPTYPE_q | OP_DST, AMODE_P | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE7 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubsb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE8 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE9 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pminsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEA */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_OR, "por", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEB */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddsb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEC */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xED */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pmaxsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEE */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_XOR, "pxor", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEF */ - { NOINSTR }, /* 0xF0 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF1 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pslld", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF2 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF3 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MUL, "pmuludq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF4 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "pmaddwd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF5 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "psadbw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF6 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "maskmovq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF7 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF8 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF9 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFA */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_SUB, "psubq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFB */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFC */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFD */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFE */ - { NOINSTR } /* 0xFF */, -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Groups -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -X86_OPCODE X86_Group_1_80[8] = // 80 -{ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_1_81[8] = // 81 -{ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_1_82[8] = // 82 -{ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_1_83[8] = // 83 -{ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_C0[8] = // C0 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_C1[8] = // C1 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_D0[8] = // D0 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_D1[8] = // D1 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_D2[8] = // D2 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_D3[8] = // D3 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_3_F6[8] = // F6 -{ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_NOT, "not", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_NEG, "neg", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_MUL, "mul", { OPTYPE_REG_AX | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, OPTYPE_REG_AL | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { OPTYPE_REG_AX | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_b | OP_SIGNED | OP_SRC, OPTYPE_REG_AL | OP_SIGNED | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_DIV, "div", { OPTYPE_REG_AX | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, OPTYPE_REG_AX | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_DIV, "idiv", { OPTYPE_REG_AX | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_b | OP_SIGNED | OP_SRC, OPTYPE_REG_AX | OP_SIGNED | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED } /* 0x07 */, -}; - -X86_OPCODE X86_Group_3_F7[8] = // F7 -{ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_NOT, "not", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_NEG, "neg", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_MUL, "mul", { OPTYPE_xDX_HI_xAX_LO | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { OPTYPE_xDX_HI_xAX_LO | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_DIV, "div", { OPTYPE_xDX_HI_xAX_LO | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_DIV, "idiv", { OPTYPE_xDX_HI_xAX_LO | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_4[8] = // FE -{ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR } /* 0x07 */ -}; - -X86_OPCODE X86_Group_5[8] = // FF -{ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_E | OPTYPE_v | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_E | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_E | OPTYPE_v | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_E | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { AMODE_E | OPTYPE_v | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_6[8] = // 0F 00 -{ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "sldt", { AMODE_E | OPTYPE_mw | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "str", { AMODE_E | OPTYPE_mw | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lldt", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "ltr", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "verr", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "verw", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_IA64, ITYPE_BRANCH, "jmpe", { AMODE_E | OPTYPE_v | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR } /* 0x07 */ -}; - -X86_OPCODE X86_Group_7[8] = // 0F 01 -{ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "sgdt", { AMODE_M | OPTYPE_dt | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "sidt", { AMODE_M | OPTYPE_dt | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lgdt", { AMODE_M | OPTYPE_dt | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lidt", { AMODE_M | OPTYPE_dt | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "smsw", { AMODE_E | OPTYPE_mw | OP_DST, OPTYPE_CR0 | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lmsw", { OPTYPE_CR0 | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I486, ITYPE_SYSTEM, "invlpg", { AMODE_M | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_8[8] = // 0F BA -{ - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bt", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bts", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "btr", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "btc", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_9[8] = // 0F C7 -{ - { NOINSTR }, /* 0x00 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_XCHGCC, "cmpxchg8b", { AMODE_M | OPTYPE_q | OP_SRC | OP_COND_DST, OPTYPE_xDX_HI_xAX_LO | OP_SRC | OP_COND_DST, OPTYPE_xCX_HI_xBX_LO | OP_COND_SRC }, COND_OP1_EQ_OP2, FLAG_ZF_MOD, OP1_DST | OP3_SRC, OP2_DST | OP1_SRC }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_10[8] = // 8F (NOTE: AMD64 labels this Group 1A) -{ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { AMODE_E | OPTYPE_v | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_11[8] = // 0F B9 (NOTE: AMD64 labels this Group 10) -{ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED } /* 0x07 */ -}; - -X86_OPCODE X86_Group_12_C6[8] = // C6 (NOTE: AMD64 labels this Group 11) -{ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC6 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_12_C7[8] = // C7 (NOTE: AMD64 labels this Group 11) -{ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -// NOTE: the X86_SSE2_* is only followed if it is a 3-byte opcode (e.g., prefix is 66, F2, or F3) -X86_OPCODE X86_Group_13[8] = // 0F 71 (NOTE: AMD64 labels this Group 12) -{ - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlw", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psraw", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllw", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_14[8] = // 0F 72 (NOTE: AMD64 labels this Group 13) -{ - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrld", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrad", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pslld", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_15[8] = // 0F 73 (NOTE: AMD64 labels this Group 14) -{ - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrldq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pslldq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED } /* 0x07 */ -}; - -X86_OPCODE X86_Group_16[8] = // 0F AE (NOTE: AMD64 labels this Group 15) -{ - { NOGROUP, CPU_PENTIUM2, ITYPE_FPU, "fxsave", { AMODE_M | OPTYPE_fst2 | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_FPU, "fxrstor", { AMODE_M | OPTYPE_fst2 | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "ldmxcsr", { AMODE_M | OPTYPE_d | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "stmxcsr", { AMODE_M | OPTYPE_d | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "lfence", NOARGS, NOCOND, NOCHANGE, SERIALIZE_READ, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "mfence", NOARGS, NOCOND, NOCHANGE, SERIALIZE_ALL, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "sfence", NOARGS, NOCOND, NOCHANGE, SERIALIZE_WRITE, IGNORED } /* 0x07 */ -}; - -X86_OPCODE X86_Group_17[8] = // 0F 18 (NOTE: AMD64 labels this Group 16) -{ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetchnta", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetcht0", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetcht1", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetcht2", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_P[8] = // 0F 0D -{ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "prefetch", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "prefetchw", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// FPU (ESC) opcodes -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - - -X86_OPCODE X86_ESC_0[0x48] = // D8 -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x00 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { AMODE_M | OPTYPE_ss | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { AMODE_M | OPTYPE_ss | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x05 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x07 - - // - // ModRM >= C0: ST(0) <- ST(0) + ST(i) - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // C8-CF - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - // D0-D7 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x7 - // D8-DF - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xF - // E0-E7 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // E8-EF - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF - // F0-F7 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // F8-FF - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED } // xF -}; - - -X86_OPCODE X86_ESC_1[0x48] = // D9 -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { AMODE_M | OPTYPE_ss | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x00 - { NOINSTR }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { AMODE_M | OPTYPE_ss | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { AMODE_M | OPTYPE_ss | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOGROUP, CPU_I287, ITYPE_FLOADENV, "fldenv", { AMODE_M | OPTYPE_fev | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldcw", { OPTYPE_FPU_CONTROL | OP_DST, AMODE_M | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // 0x05 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstenv", { AMODE_M | OPTYPE_fev | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fnstcw", { AMODE_M | OPTYPE_w | OP_DST, OPTYPE_FPU_CONTROL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // 0x07 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x7 - // C8-CF - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF - // D0-D7 - { NOGROUP, CPU_I287, ITYPE_FPU, "fnop", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // D8-DF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // E0-E7 - { NOGROUP, CPU_I287, ITYPE_FPU, "fchs", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FPU, "fabs", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOGROUP, CPU_I287, ITYPE_FPU, "ftst", { OPTYPE_ST0 | OP_SRC, OPTYPE_FLDZ | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FPU, "fxam", { OPTYPE_ST0 | OP_SRC, 0, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // E8-EF - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld1", { OPTYPE_FLD1 | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldl2t", { OPTYPE_FLDL2T | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldl2e", { OPTYPE_FLDL2E | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldpi", { OPTYPE_FLDPI | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldlg2", { OPTYPE_FLDLG2| OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldln2", { OPTYPE_FLDLN2 | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldz", { OPTYPE_FLDZ | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xE - { NOINSTR }, // xF - // F0-F7 - { NOGROUP, CPU_I287, ITYPE_FPU, "f2xm1", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FPU, "fyl2x", { OPTYPE_ST1 | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FPU, "fptan", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, FPU_STACK_PUSH, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FPU, "fpatan", { OPTYPE_ST1 | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC , 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FPU, "fxtract", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_DST, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x4 - { NOGROUP, CPU_I387, ITYPE_FPU, "fprem1", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FPU, "fdecstp", NOARGS, NOCOND, FPU_C1_MOD, FPU_STACK_DEC, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FPU, "fincstp", NOARGS, NOCOND, FPU_C1_MOD, FPU_STACK_INC, IGNORED }, // x7 - // F8-FF - { NOGROUP, CPU_I287, ITYPE_FPU, "fprem", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FPU, "fyl2xp1", { OPTYPE_ST1 | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FPU, "fsqrt", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FPU, "fsincos", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, FPU_STACK_PUSH, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FPU, "frndint", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FPU, "fscale", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FPU, "fsin", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FPU, "fcos", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, NOACTION, IGNORED } // xF -}; - - -X86_OPCODE X86_ESC_2[0x48] = // DA -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FADD, "fiadd", { OPTYPE_ST0 | OP_SIGNED | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fimul", { OPTYPE_ST0 | OP_SIGNED | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficom", { AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC | OP_DST, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficomp", { AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC | OP_DST, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fisub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fisubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fidiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fidivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7 - // C8-CF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF - // D0-D7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7 - // D8-DF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF - // E0-E7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // E8-EF - { NOINSTR }, // x8 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucompp", { OPTYPE_ST1 | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP2, IGNORED }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // F0-F7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // F8-FF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR } // xF -}; - - - -X86_OPCODE X86_ESC_3[0x48] = // DB -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fild", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x00 - { NOGROUP, CPU_PENTIUM4, ITYPE_FSTORE, "fisttp", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fist", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fistp", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOINSTR }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { AMODE_M | OPTYPE_se | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x05 - { NOINSTR }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { AMODE_M | OPTYPE_se | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x07 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7 - // C8-CF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF - // D0-D7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7 - // D8-DF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF - // E0-E7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOGROUP, CPU_I287, ITYPE_FPU, "fnclex", { OPTYPE_FPU_STATUS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FPU, "finit", { OPTYPE_FPU_STATUS | OP_DST, 0, 0 }, NOCOND, FPU_ALL_CLR, NOACTION, IGNORED }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // E8-EF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xF - // F0-F7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x7 - // F8-FF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR } // xF -}; - -X86_OPCODE X86_ESC_4[0x48] = // DC -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x00 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x05 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x07 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // C8-CF - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF - // D0-D7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // D8-DF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // E0-E7 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // E8-EF - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF - // F0-F7 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // F8-FF - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED } // xF -}; - - -X86_OPCODE X86_ESC_5[0x48] = // DD -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - // - - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { AMODE_M | OPTYPE_sd | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_FSTORE, "fisttp", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FRESTORE, "frstor", { AMODE_M | OPTYPE_fst1 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_I287, ITYPE_FSAVE, "fsave", { AMODE_M | OPTYPE_fst1 | OP_DST, 0 }, NOCOND, FPU_ALL_CLR, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fnstsw", { AMODE_M | OPTYPE_w | OP_DST, OPTYPE_FPU_STATUS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - // C8-CF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // D0-D7 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // D8-DF - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xF - // E0-E7 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x7 - // E8-EF - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xF - // F0-F7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // F8-FF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR } // xF -}; - - -X86_OPCODE X86_ESC_6[0x48] = // DE -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FADD, "fiadd", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x00 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fimul", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficom", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficomp", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fisub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fisubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x05 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fidiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fidivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x07 - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x7 - // C8-CF - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xF - // D0-D7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // D8-DF - { NOINSTR }, // x8 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcompp", { OPTYPE_ST1 | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP2, IGNORED }, // x9 - { NOINSTR }, // 0xA - { NOINSTR }, // 0xB - { NOINSTR }, // 0xC - { NOINSTR }, // 0xD - { NOINSTR }, // 0xE - { NOINSTR }, // 0xF - // E0-E7 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x7 - // E8-EF - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xF - // F0-F7 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x7 - // F8-FF - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED } // xF -}; - - -X86_OPCODE X86_ESC_7[0x48] = // DF -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fild", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0, 0}, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x00 - { NOGROUP, CPU_PENTIUM4, ITYPE_FSTORE, "fisttp", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fist", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fistp", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fbld", { AMODE_M | OPTYPE_pb | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fild", { AMODE_M | OPTYPE_q | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x05 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fbstp", { AMODE_M | OPTYPE_pb | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fistp", { AMODE_M | OPTYPE_q | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0}, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x07 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - // C0-C7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // C8-CF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // D0-D7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // D8-DF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // E0-E7 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fnstsw", { OPTYPE_REG_AX | OP_DST, OPTYPE_FPU_STATUS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // E8-EF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xF - // F0-F7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x7 - // F8-FF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR } // xF -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// SSE opcodes -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -X86_OPCODE X86_SSE[0x300] = -{ - // prefix 0x66 (operand size) - /* 0x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 1x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movupd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movupd", { AMODE_W | OPTYPE_pd | OP_DST, AMODE_V | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movlpd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_M | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movlpd", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "unpcklpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "unpckhpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movhpd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_M | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "mpvhpd", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 2x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movapd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movapd", { AMODE_W | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpi2pd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movntpd", { AMODE_M | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttpd2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpd2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "ucomisd", { AMODE_V | OPTYPE_sd | OP_SRC, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "comisd", { AMODE_V | OPTYPE_pd | OP_SRC, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, // xF - - /* 3x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 4x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 5x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "movmskpd", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "sqrtpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "andpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "andnpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_OR, "orpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_XOR, "xorpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "addpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "mulpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpd2ps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtps2dq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "subpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "minpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_DIV, "divpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maxpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 6x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpcklbw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpcklwd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckldq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "packsswb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pcmpgtb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pcmpgtw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pcmpgtd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "packuswb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhbw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhwd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhdq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "packssdw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpcklqdq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhqdq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqa", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 7x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pshufd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { X86_SSE2_Group_13, GROUP }, // x1 - { X86_SSE2_Group_14, GROUP }, // x2 - { X86_SSE2_Group_15, GROUP }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "pcmpeqb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "pcmpeqw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "pcmpeqd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_ADD, "haddpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_SUB, "hsubpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movd", { AMODE_E | OPTYPE_dq | OP_DST, AMODE_V | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqa", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 8x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 9x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Ax */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Bx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Cx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "cmppd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, // x2 - { NOINSTR }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pinsrw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pextrw", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR| OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "shufpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Dx */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3, "addsubpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrld", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmullw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movq", { AMODE_W | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pmovmskb", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR| OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubusb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubusw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pminub", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "pand", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddusb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddusw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pmaxub", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "pandn", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* Ex */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pavgb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psraw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrad", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pavgw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmulhuw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmulhw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttpd2dq", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movntdq", { AMODE_M | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubsb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubsw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pminsw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_OR, "por", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddsb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddsw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pmaxuw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_XOR, "pxor", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* Fx */ - { NOINSTR }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pslld", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmuludq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "pmaddwd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psadbw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maskmovdqu", { AMODE_V | OPTYPE_o | OP_DST, AMODE_VR| OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOINSTR }, // xF - - // prefix 0xf2 (repne) - /* 0x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 1x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movsd", { AMODE_V | OPTYPE_sdo | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movsd", { AMODE_W | OPTYPE_sd | OP_DST, AMODE_V | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_MOV, "movddup", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 2x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtsi2sd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOINSTR }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttsd2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtsd2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 3x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 4x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 5x */ - { NOINSTR }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "sqrtsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "addsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "mulsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtsd2ss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOINSTR }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "subsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "minsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_DIV, "divsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maxsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 6x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqa", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 7x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pshuflw", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_ADD, "haddps", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_SUB, "hsubps", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 8x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 9x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Ax */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Bx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Cx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "cmpsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Dx */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE3, "addsubps", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdq2q", { AMODE_P | OPTYPE_q | OP_DST, AMODE_VR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Ex */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpd2dq", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Fx */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3, "lddqu", { AMODE_V | OPTYPE_o | OP_DST, AMODE_M | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - // prefix 0xf3 (rep) - /* 0x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 1x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movss", { AMODE_V | OPTYPE_sso | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movss", { AMODE_W | OPTYPE_ss | OP_DST, AMODE_V | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_MOV, "movsldup", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_MOV, "movshdup", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 2x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtsi2ss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOINSTR }, // xB - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvttss2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtss2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 3x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 4x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 5x */ - { NOINSTR }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "sqrtss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "rsqrtss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "rcpss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "addss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "mulss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtss2sd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttps2dq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "subss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "minss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_DIV, "divss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maxss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 6x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqu", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 7x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pshufhw", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movq", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqu", { AMODE_W | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 8x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 9x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Ax */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Bx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Cx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "cmpss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Dx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movq2dq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Ex */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtdq2pd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Fx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR } // xF -}; - -X86_OPCODE X86_SSE2_Group_13[24] = // 66/F2/F3 0F 71 -{ - // prefix 0x66 (operand size) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlw", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psraw", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllw", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ - - // prefix 0xf2 (repne) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ - - // prefix 0xf3 (rep) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_SSE2_Group_14[24] = // 66/F2/F3 0F 72 -{ - // prefix 0x66 (operand size) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrld", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrad", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pslld", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ - - // prefix 0xf2 (repne) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ - - // prefix 0xf3 (rep) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_SSE2_Group_15[24] = -{ - // prefix 0x66 (operand size) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrldq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pslldq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ - - // prefix 0xf2 (repne) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ - - // prefix 0xf3 (rep) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// 3DNow opcodes -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -X86_OPCODE X86_3DNOW_0F[0x100] = -{ - { NOINSTR }, /* 00 */ - { NOINSTR }, /* 01 */ - { NOINSTR }, /* 02 */ - { NOINSTR }, /* 03 */ - { NOINSTR }, /* 04 */ - { NOINSTR }, /* 05 */ - { NOINSTR }, /* 06 */ - { NOINSTR }, /* 07 */ - { NOINSTR }, /* 08 */ - { NOINSTR }, /* 09 */ - { NOINSTR }, /* 0A */ - { NOINSTR }, /* 0B */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pi2fw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0C */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pi2fd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0D */ - { NOINSTR }, /* 0E */ - { NOINSTR }, /* 0F */ - { NOINSTR }, /* 10 */ - { NOINSTR }, /* 11 */ - { NOINSTR }, /* 12 */ - { NOINSTR }, /* 13 */ - { NOINSTR }, /* 14 */ - { NOINSTR }, /* 15 */ - { NOINSTR }, /* 16 */ - { NOINSTR }, /* 17 */ - { NOINSTR }, /* 18 */ - { NOINSTR }, /* 19 */ - { NOINSTR }, /* 1A */ - { NOINSTR }, /* 1B */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pf2iw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 1C */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pf2id", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 1D */ - { NOINSTR }, /* 1E */ - { NOINSTR }, /* 1F */ - { NOINSTR }, /* 20 */ - { NOINSTR }, /* 21 */ - { NOINSTR }, /* 22 */ - { NOINSTR }, /* 23 */ - { NOINSTR }, /* 24 */ - { NOINSTR }, /* 25 */ - { NOINSTR }, /* 26 */ - { NOINSTR }, /* 27 */ - { NOINSTR }, /* 28 */ - { NOINSTR }, /* 29 */ - { NOINSTR }, /* 2A */ - { NOINSTR }, /* 2B */ - { NOINSTR }, /* 2C */ - { NOINSTR }, /* 2D */ - { NOINSTR }, /* 2E */ - { NOINSTR }, /* 2F */ - { NOINSTR }, /* 30 */ - { NOINSTR }, /* 31 */ - { NOINSTR }, /* 32 */ - { NOINSTR }, /* 33 */ - { NOINSTR }, /* 34 */ - { NOINSTR }, /* 35 */ - { NOINSTR }, /* 36 */ - { NOINSTR }, /* 37 */ - { NOINSTR }, /* 38 */ - { NOINSTR }, /* 39 */ - { NOINSTR }, /* 3A */ - { NOINSTR }, /* 3B */ - { NOINSTR }, /* 3C */ - { NOINSTR }, /* 3D */ - { NOINSTR }, /* 3E */ - { NOINSTR }, /* 3F */ - { NOINSTR }, /* 40 */ - { NOINSTR }, /* 41 */ - { NOINSTR }, /* 42 */ - { NOINSTR }, /* 43 */ - { NOINSTR }, /* 44 */ - { NOINSTR }, /* 45 */ - { NOINSTR }, /* 46 */ - { NOINSTR }, /* 47 */ - { NOINSTR }, /* 48 */ - { NOINSTR }, /* 49 */ - { NOINSTR }, /* 4A */ - { NOINSTR }, /* 4B */ - { NOINSTR }, /* 4C */ - { NOINSTR }, /* 4D */ - { NOINSTR }, /* 4E */ - { NOINSTR }, /* 4F */ - { NOINSTR }, /* 50 */ - { NOINSTR }, /* 51 */ - { NOINSTR }, /* 52 */ - { NOINSTR }, /* 53 */ - { NOINSTR }, /* 54 */ - { NOINSTR }, /* 55 */ - { NOINSTR }, /* 56 */ - { NOINSTR }, /* 57 */ - { NOINSTR }, /* 58 */ - { NOINSTR }, /* 59 */ - { NOINSTR }, /* 5A */ - { NOINSTR }, /* 5B */ - { NOINSTR }, /* 5C */ - { NOINSTR }, /* 5D */ - { NOINSTR }, /* 5E */ - { NOINSTR }, /* 5F */ - { NOINSTR }, /* 60 */ - { NOINSTR }, /* 61 */ - { NOINSTR }, /* 62 */ - { NOINSTR }, /* 63 */ - { NOINSTR }, /* 64 */ - { NOINSTR }, /* 65 */ - { NOINSTR }, /* 66 */ - { NOINSTR }, /* 67 */ - { NOINSTR }, /* 68 */ - { NOINSTR }, /* 69 */ - { NOINSTR }, /* 6A */ - { NOINSTR }, /* 6B */ - { NOINSTR }, /* 6C */ - { NOINSTR }, /* 6D */ - { NOINSTR }, /* 6E */ - { NOINSTR }, /* 6F */ - { NOINSTR }, /* 70 */ - { NOINSTR }, /* 71 */ - { NOINSTR }, /* 72 */ - { NOINSTR }, /* 73 */ - { NOINSTR }, /* 74 */ - { NOINSTR }, /* 75 */ - { NOINSTR }, /* 76 */ - { NOINSTR }, /* 77 */ - { NOINSTR }, /* 78 */ - { NOINSTR }, /* 79 */ - { NOINSTR }, /* 7A */ - { NOINSTR }, /* 7B */ - { NOINSTR }, /* 7C */ - { NOINSTR }, /* 7D */ - { NOINSTR }, /* 7E */ - { NOINSTR }, /* 7F */ - { NOINSTR }, /* 80 */ - { NOINSTR }, /* 81 */ - { NOINSTR }, /* 82 */ - { NOINSTR }, /* 83 */ - { NOINSTR }, /* 84 */ - { NOINSTR }, /* 85 */ - { NOINSTR }, /* 86 */ - { NOINSTR }, /* 87 */ - { NOINSTR }, /* 88 */ - { NOINSTR }, /* 89 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfnacc", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 8A */ - { NOINSTR }, /* 8B */ - { NOINSTR }, /* 8C */ - { NOINSTR }, /* 8D */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfpnacc", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 8E */ - { NOINSTR }, /* 8F */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_CMP, "pfcmpge", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 90 */ - { NOINSTR }, /* 91 */ - { NOINSTR }, /* 92 */ - { NOINSTR }, /* 93 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfmin", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 94 */ - { NOINSTR }, /* 95 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrcp", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 96 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrsqrt", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 97 */ - { NOINSTR }, /* 98 */ - { NOINSTR }, /* 99 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_SUB, "pfsub", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 9A */ - { NOINSTR }, /* 9B */ - { NOINSTR }, /* 9C */ - { NOINSTR }, /* 9D */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_ADD, "pfadd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 9E */ - { NOINSTR }, /* 9F */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_CMP, "pfcmpgt", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A0 */ - { NOINSTR }, /* A1 */ - { NOINSTR }, /* A2 */ - { NOINSTR }, /* A3 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfmax", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A4 */ - { NOINSTR }, /* A5 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrcpit1", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A6 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrsqit1", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A7 */ - { NOINSTR }, /* A8 */ - { NOINSTR }, /* A9 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_SUB, "pfsubr", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* AA */ - { NOINSTR }, /* AB */ - { NOINSTR }, /* AC */ - { NOINSTR }, /* AD */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfacc", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* AE */ - { NOINSTR }, /* AF */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_CMP, "pfcmpeq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B0 */ - { NOINSTR }, /* B1 */ - { NOINSTR }, /* B2 */ - { NOINSTR }, /* B3 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_MUL, "pfmul", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B4 */ - { NOINSTR }, /* B5 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrcpit2", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B6 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_MUL, "pmulhrw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B7 */ - { NOINSTR }, /* B8 */ - { NOINSTR }, /* B9 */ - { NOINSTR }, /* BA */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_XCHG, "pswapd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* BB */ - { NOINSTR }, /* BC */ - { NOINSTR }, /* BD */ - { NOINSTR }, /* BE */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pavgb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* BF */ - { NOINSTR }, /* C0 */ - { NOINSTR }, /* C1 */ - { NOINSTR }, /* C2 */ - { NOINSTR }, /* C3 */ - { NOINSTR }, /* C4 */ - { NOINSTR }, /* C5 */ - { NOINSTR }, /* C6 */ - { NOINSTR }, /* C7 */ - { NOINSTR }, /* C8 */ - { NOINSTR }, /* C9 */ - { NOINSTR }, /* CA */ - { NOINSTR }, /* CB */ - { NOINSTR }, /* CC */ - { NOINSTR }, /* CD */ - { NOINSTR }, /* CE */ - { NOINSTR }, /* CF */ - { NOINSTR }, /* D0 */ - { NOINSTR }, /* D1 */ - { NOINSTR }, /* D2 */ - { NOINSTR }, /* D3 */ - { NOINSTR }, /* D4 */ - { NOINSTR }, /* D5 */ - { NOINSTR }, /* D6 */ - { NOINSTR }, /* D7 */ - { NOINSTR }, /* D8 */ - { NOINSTR }, /* D9 */ - { NOINSTR }, /* DA */ - { NOINSTR }, /* DB */ - { NOINSTR }, /* DC */ - { NOINSTR }, /* DD */ - { NOINSTR }, /* DE */ - { NOINSTR }, /* DF */ - { NOINSTR }, /* E0 */ - { NOINSTR }, /* E1 */ - { NOINSTR }, /* E2 */ - { NOINSTR }, /* E3 */ - { NOINSTR }, /* E4 */ - { NOINSTR }, /* E5 */ - { NOINSTR }, /* E6 */ - { NOINSTR }, /* E7 */ - { NOINSTR }, /* E8 */ - { NOINSTR }, /* E9 */ - { NOINSTR }, /* EA */ - { NOINSTR }, /* EB */ - { NOINSTR }, /* EC */ - { NOINSTR }, /* ED */ - { NOINSTR }, /* EE */ - { NOINSTR }, /* EF */ - { NOINSTR }, /* F0 */ - { NOINSTR }, /* F1 */ - { NOINSTR }, /* F2 */ - { NOINSTR }, /* F3 */ - { NOINSTR }, /* F4 */ - { NOINSTR }, /* F5 */ - { NOINSTR }, /* F6 */ - { NOINSTR }, /* F7 */ - { NOINSTR }, /* F8 */ - { NOINSTR }, /* F9 */ - { NOINSTR }, /* FA */ - { NOINSTR }, /* FB */ - { NOINSTR }, /* FC */ - { NOINSTR }, /* FD */ - { NOINSTR }, /* FE */ - { NOINSTR } /* FF */ -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// 64-bit replacement opcodes -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -X86_OPCODE X86_Opcode_63[2] = -{ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "arpl", { AMODE_E | OPTYPE_w | OP_SRC, AMODE_G | OPTYPE_w | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, // !ARCH_AMD64 - { NOGROUP, CPU_AMD64, ITYPE_MOV, "movsxd", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_d | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED } // ARCH_AMD64 -}; - -X86_OPCODE X86_Opcode_0F05[2] = -{ - { NOGROUP, CPU_AMD_K6_2, ITYPE_SYSCALL, "syscall", { OPTYPE_STAR_MSR | OP_MSR | OP_SRC, OPTYPE_CSTAR_MSR | OP_MSR | OP_SRC, OPTYPE_FMASK_MSR | OP_MSR | OP_SRC }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, // !ARCH_AMD64 - { NOGROUP, CPU_AMD64, ITYPE_SYSCALL, "syscall", { OPTYPE_STAR_MSR | OP_MSR | OP_SRC, OPTYPE_LSTAR_MSR | OP_MSR | OP_SRC, OPTYPE_FMASK_MSR | OP_MSR | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED } // ARCH_AMD64 -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Other 3 byte opcodes -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -// Three byte opcodes where the third opcode byte is ModRM -X86_OPCODE X86_0F01_ModRM[0x100] = -{ - /* 0x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 1x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 2x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 3x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 4x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 5x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 6x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 7x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 8x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 9x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Ax */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Bx */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Cx */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { NOGROUP, CPU_PRESCOTT, ITYPE_SYSTEM, "monitor", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PRESCOTT, ITYPE_SYSTEM, "mwait", NOARGS, NOCOND, NOCHANGE, SERIALIZE_ALL, IGNORED }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Dx */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Ex */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Fx */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { NOGROUP, CPU_AMD64, ITYPE_SYSTEM, "swapgs", { OPTYPE_KERNELBASE_MSR | OP_MSR | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP } // xF -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Sanity checking tables -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -#define S2 1 // SSE2 -#define S3 2 // SSE3 -BYTE X86_ModRM_1[0x100] = -{ - // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF - /* 0x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 1x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 2x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 3x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 6x */ 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 8x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Cx */ 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - /* Dx */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Fx */ 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 -}; -BYTE X86_ModRM_2[0x100] = -{ - // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF - /* 0x */ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, - /* 1x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, - /* 2x */ 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 4x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 6x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 7x */ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 9x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* Ax */ 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, - /* Bx */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, - /* Cx */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - /* Dx */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* Ex */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* Fx */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 -}; - -BYTE X86_SSE_2[0x100] = -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 1x */ 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 5x */ 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, - /* 7x */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Cx */ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Dx */ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ex */ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Fx */ 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -// Indicates if a LOCK prefix is allowed -// The following are allowed: -// add, adc, and, btc, btr, bts, cmpxchg, cmpxchg8, dec, inc, -// neg, not, or, sbb, sub, xor, xadd, xchg -#define GR 2 -BYTE X86_LockPrefix_1[0x100] = -{ - // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF - /* 0x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 1x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 2x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 3x */ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 8x */ GR, GR, GR, GR, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Fx */ 0, 0, 0, 0, 0, 0, GR, GR, 0, 0, 0, 0, 0, 0, GR, GR -}; - -BYTE X86_LockPrefix_2[0x100] = -{ - // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - /* Bx */ 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, GR, 1, 0, 0, 0, 0, - /* Cx */ 1, 1, 0, 0, 0, 0, 0, GR, 0, 0, 0, 0, 0, 0, 0, 0, - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -BYTE X86_LockPrefix_Groups[17][8] = -{ -// x0 x1 x2 x3 x4 x5 x6 x7 - { 1, 1, 1, 1, 1, 1, 1, 0 }, // group 1 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 2 - { 0, 0, 1, 1, 0, 0, 0, 0 }, // group 3 - { 1, 1, 0, 0, 0, 0, 0, 0 }, // group 4 - { 1, 1, 0, 0, 0, 0, 0, 0 }, // group 5 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 6 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 7 - { 0, 0, 0, 0, 1, 1, 1, 1 }, // group 8 - { 0, 1, 0, 0, 0, 0, 0, 0 }, // group 9 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 10 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 11 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 12 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 13 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 14 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 15 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 16 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 17 -}; - -#define X86_MAX_GROUP 19 -BYTE X86_Groups_1[0x100] = // one-byte opcodes -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 2, 2, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */ - /* Dx */ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 4, 5 /* Fx */ -}; - -// 19 = Group P -// 20 = 3DNow -BYTE X86_Groups_2[0x100] = // two-byte opcodes -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 19, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 8, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */ - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */ -}; - -// Indicate which 1-byte opcodes are invalid with a 16-bit operand size -BYTE X86_Invalid_Op16_1[0x100] = -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */ - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */ -}; - -// Indicate which 2-byte opcodes are invalid with a 16-bit operand size -BYTE X86_Invalid_Op16_2[0x100] = -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* Cx */ - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */ -}; - -// Indicate which 1-byte opcodes are invalid with a 64-bit address size -BYTE X86_Invalid_Addr64_1[0x100] = -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, /* 2x */ - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* Cx */ - /* Dx */ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */ -}; - -// Indicate which 2-byte opcodes are invalid with a 64-bit address size -BYTE X86_Invalid_Addr64_2[0x100] = -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - /* 3x */ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */ - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */ -}; - -#endif // DISASM_X86_TABLES \ No newline at end of file diff --git a/renderdoc/3rdparty/mhook/disasm-lib/misc.c b/renderdoc/3rdparty/mhook/disasm-lib/misc.c deleted file mode 100644 index c5b0ac61a..000000000 --- a/renderdoc/3rdparty/mhook/disasm-lib/misc.c +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (C) 2002, Matt Conover (mconover@gmail.com) -#include "misc.h" - -BOOL IsHexChar(BYTE ch) -{ - switch (ch) - { - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': - case 'A': case 'a': case 'B': case 'b': - case 'C': case 'c': case 'D': case 'd': - case 'E': case 'e': case 'F': case 'f': - return TRUE; - default: - return FALSE; - } -} - -// NOTE: caller must free the buffer returned -BYTE *HexToBinary(char *Input, DWORD InputLength, DWORD *OutputLength) -{ - DWORD i, j, ByteCount = 0; - char temp_byte[3]; - BYTE *p, *ByteString = NULL; - - if (!InputLength || !OutputLength) return NULL; - else *OutputLength = 0; - - while (*Input && isspace(*Input)) { Input++; InputLength--; } - if (!*Input) return NULL; - if (Input[0] == '\"') { Input++; InputLength--; } - p = (BYTE *)strchr(Input, '\"'); - if (p) InputLength--; - - if (InputLength > 2 && Input[2] == ' ') // assume spaces - { - for (i = 0; i < InputLength; i += 3) - { - while (i < InputLength && isspace(Input[i])) i++; // skip over extra space, \r, and \n - if (i >= InputLength) break; - - if (!IsHexChar(Input[i])) - { - //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); - goto abort; - } - - if (i+1 >= InputLength || !Input[i+1]) - { - //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1); - goto abort; - } - - if (i+2 < InputLength && Input[i+2] && !isspace(Input[i+2])) - { - //fprintf(stderr, "ERROR: Hex string is malformed at offset %lu (0x%04x)\n", i, i); - //fprintf(stderr, "Found '%c' (0x%02x) instead of space\n", Input[i+2], Input[i+2]); - goto abort; - } - - ByteCount++; - } - - if (!ByteCount) - { - //fprintf(stderr, "Error: no input (byte count = 0)\n"); - goto abort; - } - - ByteString = malloc(ByteCount+1); - if (!ByteString) - { - //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount); - goto abort; - } - - memset(ByteString, 0, ByteCount+1); - for (i = 0, j = 0; j < ByteCount; i += 3, j++) - { - while (isspace(Input[i])) i++; // skip over extra space, \r, and \n - temp_byte[0] = Input[i]; - temp_byte[1] = Input[i+1]; - temp_byte[2] = 0; - ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16); - } - } - else if (InputLength > 2 && Input[0] == '\\') - { - for (i = 0; i < InputLength; i += 2) - { - if (Input[i] != '\\' || (Input[i+1] != 'x' && Input[i+1] != '0')) - { - //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); - goto abort; - } - i += 2; - - if (!IsHexChar(Input[i])) - { - //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); - goto abort; - } - if (i+1 >= InputLength || !Input[i+1]) - { - //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1); - goto abort; - } - - ByteCount++; - } - - if (!ByteCount) - { - //fprintf(stderr, "Error: no input (byte count = 0)\n"); - goto abort; - } - - ByteString = malloc(ByteCount+1); - if (!ByteString) - { - //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount); - goto abort; - } - - memset(ByteString, 0, ByteCount+1); - for (i = j = 0; j < ByteCount; i += 2, j++) - { - i += 2; - temp_byte[0] = Input[i]; - temp_byte[1] = Input[i+1]; - temp_byte[2] = 0; - ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16); - } - } - else // assume it is a hex string with no spaces with 2 bytes per character - { - for (i = 0; i < InputLength; i += 2) - { - if (!IsHexChar(Input[i])) - { - //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); - goto abort; - } - if (i+1 >= InputLength || !Input[i+1]) - { - //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1); - goto abort; - } - - ByteCount++; - } - - if (!ByteCount) - { - //fprintf(stderr, "Error: no input (byte count = 0)\n"); - goto abort; - } - - ByteString = malloc(ByteCount+1); - if (!ByteString) - { - //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount); - goto abort; - } - - memset(ByteString, 0, ByteCount+1); - for (i = 0, j = 0; j < ByteCount; i += 2, j++) - { - temp_byte[0] = Input[i]; - temp_byte[1] = Input[i+1]; - temp_byte[2] = 0; - ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16); - } - } - - *OutputLength = ByteCount; - return ByteString; - -abort: - if (OutputLength) *OutputLength = 0; - if (ByteString) free(ByteString); - return NULL; -} - diff --git a/renderdoc/3rdparty/mhook/disasm-lib/misc.h b/renderdoc/3rdparty/mhook/disasm-lib/misc.h deleted file mode 100644 index b3f585b75..000000000 --- a/renderdoc/3rdparty/mhook/disasm-lib/misc.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2002, Matt Conover (mconover@gmail.com) -#ifndef MISC_H -#define MISC_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) - -// NOTE: start is inclusive, end is exclusive (as in start <= x < end) -#define IS_IN_RANGE(x, s, e) \ -( \ - ((ULONG_PTR)(x) == (ULONG_PTR)(s) && (ULONG_PTR)(x) == (ULONG_PTR)(e)) || \ - ((ULONG_PTR)(x) >= (ULONG_PTR)(s) && (ULONG_PTR)(x) < (ULONG_PTR)(e)) \ -) - -#if _MSC_VER >= 1400 -#pragma warning(disable:4996) -#endif - -#if defined(_WIN64) - #define VALID_ADDRESS_MAX 0x7FFEFFFFFFFFFFFF // Win64 specific - typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; -#else - #define VALID_ADDRESS_MAX 0x7FFEFFFF // Win32 specific - typedef unsigned long ULONG_PTR, *PULONG_PTR; -#endif - -#ifndef DECLSPEC_ALIGN - #if (_MSC_VER >= 1300) && !defined(MIDL_PASS) - #define DECLSPEC_ALIGN(x) __declspec(align(x)) - #else - #define DECLSPEC_ALIGN(x) - #endif -#endif - -#define VALID_ADDRESS_MIN 0x10000 // Win32 specific -#define IS_VALID_ADDRESS(a) IS_IN_RANGE(a, VALID_ADDRESS_MIN, VALID_ADDRESS_MAX+1) - -BOOL IsHexChar(BYTE ch); -BYTE *HexToBinary(char *Input, DWORD InputLength, DWORD *OutputLength); - -#ifdef __cplusplus -} -#endif -#endif // MISC_H diff --git a/renderdoc/3rdparty/mhook/mhook-lib/mhook.cpp b/renderdoc/3rdparty/mhook/mhook-lib/mhook.cpp deleted file mode 100644 index c4018c0c3..000000000 --- a/renderdoc/3rdparty/mhook/mhook-lib/mhook.cpp +++ /dev/null @@ -1,936 +0,0 @@ -//Copyright (c) 2007-2008, Marton Anka -// -//Permission is hereby granted, free of charge, to any person obtaining a -//copy of this software and associated documentation files (the "Software"), -//to deal in the Software without restriction, including without limitation -//the rights to use, copy, modify, merge, publish, distribute, sublicense, -//and/or sell copies of the Software, and to permit persons to whom the -//Software is furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included -//in all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -//OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -//THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -//IN THE SOFTWARE. - -#include -#include -#include -#include "mhook.h" -#include "../disasm-lib/disasm.h" - -#pragma warning(disable:4706 4310) - -//========================================================================= -#ifndef cntof -#define cntof(a) (sizeof(a)/sizeof(a[0])) -#endif - -//========================================================================= -#ifndef GOOD_HANDLE -#define GOOD_HANDLE(a) ((a!=INVALID_HANDLE_VALUE)&&(a!=NULL)) -#endif - -//========================================================================= -#ifndef gle -#define gle GetLastError -#endif - -//========================================================================= -#ifndef ODPRINTF - -#ifdef _DEBUG -#define ODPRINTF(a) odprintf a -#else -#define ODPRINTF(a) -#endif - -inline void __cdecl odprintf(PCSTR format, ...) { - va_list args; - va_start(args, format); - int len = _vscprintf(format, args); - if (len > 0) { - len += (1 + 2); - PSTR buf = (PSTR) malloc(len); - if (buf) { - len = vsprintf_s(buf, len, format, args); - if (len > 0) { - while (len && isspace(buf[len-1])) len--; - buf[len++] = '\r'; - buf[len++] = '\n'; - buf[len] = 0; - OutputDebugStringA(buf); - } - free(buf); - } - va_end(args); - } -} - -inline void __cdecl odprintf(PCWSTR format, ...) { - va_list args; - va_start(args, format); - int len = _vscwprintf(format, args); - if (len > 0) { - len += (1 + 2); - PWSTR buf = (PWSTR) malloc(sizeof(WCHAR)*len); - if (buf) { - len = vswprintf_s(buf, len, format, args); - if (len > 0) { - while (len && iswspace(buf[len-1])) len--; - buf[len++] = L'\r'; - buf[len++] = L'\n'; - buf[len] = 0; - OutputDebugStringW(buf); - } - free(buf); - } - va_end(args); - } -} - -#endif //#ifndef ODPRINTF - -//========================================================================= -#define MHOOKS_MAX_CODE_BYTES 32 -#define MHOOKS_MAX_RIPS 4 - -//========================================================================= -// The trampoline structure - stores every bit of info about a hook -struct MHOOKS_TRAMPOLINE { - PBYTE pSystemFunction; // the original system function - DWORD cbOverwrittenCode; // number of bytes overwritten by the jump - PBYTE pHookFunction; // the hook function that we provide - BYTE codeJumpToHookFunction[MHOOKS_MAX_CODE_BYTES]; // placeholder for code that jumps to the hook function - BYTE codeTrampoline[MHOOKS_MAX_CODE_BYTES]; // placeholder for code that holds the first few - // bytes from the system function and a jump to the remainder - // in the original location - BYTE codeUntouched[MHOOKS_MAX_CODE_BYTES]; // placeholder for unmodified original code - // (we patch IP-relative addressing) - MHOOKS_TRAMPOLINE* pPrevTrampoline; // When in the free list, thess are pointers to the prev and next entry. - MHOOKS_TRAMPOLINE* pNextTrampoline; // When not in the free list, this is a pointer to the prev and next trampoline in use. -}; - -//========================================================================= -// The patch data structures - store info about rip-relative instructions -// during hook placement -struct MHOOKS_RIPINFO -{ - DWORD dwOffset; - S64 nDisplacement; -}; - -struct MHOOKS_PATCHDATA -{ - S64 nLimitUp; - S64 nLimitDown; - DWORD nRipCnt; - MHOOKS_RIPINFO rips[MHOOKS_MAX_RIPS]; -}; - -//========================================================================= -// Global vars -static BOOL g_bVarsInitialized = FALSE; -static CRITICAL_SECTION g_cs; -static MHOOKS_TRAMPOLINE* g_pHooks = NULL; -static MHOOKS_TRAMPOLINE* g_pFreeList = NULL; -static DWORD g_nHooksInUse = 0; -static BOOL g_bThreadsSuspended = FALSE; -static HANDLE* g_hThreadHandles = NULL; -static DWORD g_nThreadHandles = 0; -#define MHOOK_JMPSIZE 5 -#define MHOOK_MINALLOCSIZE 4096 - -//========================================================================= -// Toolhelp defintions so the functions can be dynamically bound to -typedef HANDLE (WINAPI * _CreateToolhelp32Snapshot)( - DWORD dwFlags, - DWORD th32ProcessID - ); - -typedef BOOL (WINAPI * _Thread32First)( - HANDLE hSnapshot, - LPTHREADENTRY32 lpte - ); - -typedef BOOL (WINAPI * _Thread32Next)( - HANDLE hSnapshot, - LPTHREADENTRY32 lpte - ); - -//========================================================================= -// Bring in the toolhelp functions from kernel32 -_CreateToolhelp32Snapshot fnCreateToolhelp32Snapshot = (_CreateToolhelp32Snapshot) GetProcAddress(GetModuleHandle(L"kernel32"), "CreateToolhelp32Snapshot"); -_Thread32First fnThread32First = (_Thread32First) GetProcAddress(GetModuleHandle(L"kernel32"), "Thread32First"); -_Thread32Next fnThread32Next = (_Thread32Next) GetProcAddress(GetModuleHandle(L"kernel32"), "Thread32Next"); - -//========================================================================= -// Internal function: -// -// Remove the trampoline from the specified list, updating the head pointer -// if necessary. -//========================================================================= -static VOID ListRemove(MHOOKS_TRAMPOLINE** pListHead, MHOOKS_TRAMPOLINE* pNode) { - if (pNode->pPrevTrampoline) { - pNode->pPrevTrampoline->pNextTrampoline = pNode->pNextTrampoline; - } - - if (pNode->pNextTrampoline) { - pNode->pNextTrampoline->pPrevTrampoline = pNode->pPrevTrampoline; - } - - if ((*pListHead) == pNode) { - (*pListHead) = pNode->pNextTrampoline; - assert((*pListHead)->pPrevTrampoline == NULL); - } - - pNode->pPrevTrampoline = NULL; - pNode->pNextTrampoline = NULL; -} - -//========================================================================= -// Internal function: -// -// Prepend the trampoline from the specified list and update the head pointer. -//========================================================================= -static VOID ListPrepend(MHOOKS_TRAMPOLINE** pListHead, MHOOKS_TRAMPOLINE* pNode) { - pNode->pPrevTrampoline = NULL; - pNode->pNextTrampoline = (*pListHead); - if ((*pListHead)) { - (*pListHead)->pPrevTrampoline = pNode; - } - (*pListHead) = pNode; -} - -//========================================================================= -static VOID EnterCritSec() { - if (!g_bVarsInitialized) { - InitializeCriticalSection(&g_cs); - g_bVarsInitialized = TRUE; - } - EnterCriticalSection(&g_cs); -} - -//========================================================================= -static VOID LeaveCritSec() { - LeaveCriticalSection(&g_cs); -} - -//========================================================================= -// Internal function: -// -// Skip over jumps that lead to the real function. Gets around import -// jump tables, etc. -//========================================================================= -static PBYTE SkipJumps(PBYTE pbCode) { - PBYTE pbOrgCode = pbCode; -#ifdef _M_IX86_X64 -#ifdef _M_IX86 - //mov edi,edi: hot patch point - if (pbCode[0] == 0x8b && pbCode[1] == 0xff) - pbCode += 2; - // push ebp; mov ebp, esp; pop ebp; - // "collapsed" stackframe generated by MSVC - if (pbCode[0] == 0x55 && pbCode[1] == 0x8b && pbCode[2] == 0xec && pbCode[3] == 0x5d) - pbCode += 4; -#endif - if (pbCode[0] == 0xff && pbCode[1] == 0x25) { -#ifdef _M_IX86 - // on x86 we have an absolute pointer... - PBYTE pbTarget = *(PBYTE *)&pbCode[2]; - // ... that shows us an absolute pointer. - return SkipJumps(*(PBYTE *)pbTarget); -#elif defined _M_X64 - // on x64 we have a 32-bit offset... - INT32 lOffset = *(INT32 *)&pbCode[2]; - // ... that shows us an absolute pointer - return SkipJumps(*(PBYTE*)(pbCode + 6 + lOffset)); - } else if (pbCode[0] == 0x48 && pbCode[1] == 0xff && pbCode[2] == 0x25) { - // or we can have the same with a REX prefix - INT32 lOffset = *(INT32 *)&pbCode[3]; - // ... that shows us an absolute pointer - return SkipJumps(*(PBYTE*)(pbCode + 7 + lOffset)); -#endif - } else if (pbCode[0] == 0xe9) { - // here the behavior is identical, we have... - // ...a 32-bit offset to the destination. - return SkipJumps(pbCode + 5 + *(INT32 *)&pbCode[1]); - } else if (pbCode[0] == 0xeb) { - // and finally an 8-bit offset to the destination - return SkipJumps(pbCode + 2 + *(CHAR *)&pbCode[1]); - } -#else -#error unsupported platform -#endif - return pbOrgCode; -} - -//========================================================================= -// Internal function: -// -// Writes code at pbCode that jumps to pbJumpTo. Will attempt to do this -// in as few bytes as possible. Important on x64 where the long jump -// (0xff 0x25 ....) can take up 14 bytes. -//========================================================================= -static PBYTE EmitJump(PBYTE pbCode, PBYTE pbJumpTo) { -#ifdef _M_IX86_X64 - PBYTE pbJumpFrom = pbCode + 5; - SIZE_T cbDiff = pbJumpFrom > pbJumpTo ? pbJumpFrom - pbJumpTo : pbJumpTo - pbJumpFrom; - ODPRINTF((L"mhooks: EmitJump: Jumping from %p to %p, diff is %p", pbJumpFrom, pbJumpTo, cbDiff)); - if (cbDiff <= 0x7fff0000) { - pbCode[0] = 0xe9; - pbCode += 1; - *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbJumpTo - pbJumpFrom); - pbCode += sizeof(DWORD); - } else { - pbCode[0] = 0xff; - pbCode[1] = 0x25; - pbCode += 2; -#ifdef _M_IX86 - // on x86 we write an absolute address (just behind the instruction) - *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbCode + sizeof(DWORD)); -#elif defined _M_X64 - // on x64 we write the relative address of the same location - *((PDWORD)pbCode) = (DWORD)0; -#endif - pbCode += sizeof(DWORD); - *((PDWORD_PTR)pbCode) = (DWORD_PTR)(pbJumpTo); - pbCode += sizeof(DWORD_PTR); - } -#else -#error unsupported platform -#endif - return pbCode; -} - - -//========================================================================= -// Internal function: -// -// Round down to the next multiple of rndDown -//========================================================================= -static size_t RoundDown(size_t addr, size_t rndDown) -{ - return (addr / rndDown) * rndDown; -} - -//========================================================================= -// Internal function: -// -// Will attempt allocate a block of memory within the specified range, as -// near as possible to the specified function. -//========================================================================= -static MHOOKS_TRAMPOLINE* BlockAlloc(PBYTE pSystemFunction, PBYTE pbLower, PBYTE pbUpper) { - SYSTEM_INFO sSysInfo = {0}; - ::GetSystemInfo(&sSysInfo); - - // Always allocate in bulk, in case the system actually has a smaller allocation granularity than MINALLOCSIZE. - const ptrdiff_t cAllocSize = max(sSysInfo.dwAllocationGranularity, MHOOK_MINALLOCSIZE); - - MHOOKS_TRAMPOLINE* pRetVal = NULL; - PBYTE pModuleGuess = (PBYTE) RoundDown((size_t)pSystemFunction, cAllocSize); - int loopCount = 0; - for (PBYTE pbAlloc = pModuleGuess; pbLower < pbAlloc && pbAlloc < pbUpper; ++loopCount) { - // determine current state - MEMORY_BASIC_INFORMATION mbi; - ODPRINTF((L"mhooks: BlockAlloc: Looking at address %p", pbAlloc)); - if (!VirtualQuery(pbAlloc, &mbi, sizeof(mbi))) - break; - // free & large enough? - if (mbi.State == MEM_FREE && mbi.RegionSize >= (unsigned)cAllocSize) { - // and then try to allocate it - pRetVal = (MHOOKS_TRAMPOLINE*) VirtualAlloc(pbAlloc, cAllocSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (pRetVal) { - size_t trampolineCount = cAllocSize / sizeof(MHOOKS_TRAMPOLINE); - ODPRINTF((L"mhooks: BlockAlloc: Allocated block at %p as %d trampolines", pRetVal, trampolineCount)); - - pRetVal[0].pPrevTrampoline = NULL; - pRetVal[0].pNextTrampoline = &pRetVal[1]; - - // prepare them by having them point down the line at the next entry. - for (size_t s = 1; s < trampolineCount; ++s) { - pRetVal[s].pPrevTrampoline = &pRetVal[s - 1]; - pRetVal[s].pNextTrampoline = &pRetVal[s + 1]; - } - - // last entry points to the current head of the free list - pRetVal[trampolineCount - 1].pNextTrampoline = g_pFreeList; - break; - } - } - - // This is a spiral, should be -1, 1, -2, 2, -3, 3, etc. (* cAllocSize) - ptrdiff_t bytesToOffset = (cAllocSize * (loopCount + 1) * ((loopCount % 2 == 0) ? -1 : 1)); - pbAlloc = pbAlloc + bytesToOffset; - } - - return pRetVal; -} - -//========================================================================= -// Internal function: -// -// Will try to allocate a big block of memory inside the required range. -//========================================================================= -static MHOOKS_TRAMPOLINE* FindTrampolineInRange(PBYTE pLower, PBYTE pUpper) { - if (!g_pFreeList) { - return NULL; - } - - // This is a standard free list, except we're doubly linked to deal with soem return shenanigans. - MHOOKS_TRAMPOLINE* curEntry = g_pFreeList; - while (curEntry) { - if ((MHOOKS_TRAMPOLINE*) pLower < curEntry && curEntry < (MHOOKS_TRAMPOLINE*) pUpper) { - ListRemove(&g_pFreeList, curEntry); - - return curEntry; - } - - curEntry = curEntry->pNextTrampoline; - } - - return NULL; -} - -//========================================================================= -// Internal function: -// -// Will try to allocate the trampoline structure within 2 gigabytes of -// the target function. -//========================================================================= -static MHOOKS_TRAMPOLINE* TrampolineAlloc(PBYTE pSystemFunction, S64 nLimitUp, S64 nLimitDown) { - - MHOOKS_TRAMPOLINE* pTrampoline = NULL; - - // determine lower and upper bounds for the allocation locations. - // in the basic scenario this is +/- 2GB but IP-relative instructions - // found in the original code may require a smaller window. - PBYTE pLower = pSystemFunction + nLimitUp; - pLower = pLower < (PBYTE)(DWORD_PTR)0x0000000080000000 ? - (PBYTE)(0x1) : (PBYTE)(pLower - (PBYTE)0x7fff0000); - PBYTE pUpper = pSystemFunction + nLimitDown; - pUpper = pUpper < (PBYTE)(DWORD_PTR)0xffffffff80000000 ? - (PBYTE)(pUpper + (DWORD_PTR)0x7ff80000) : (PBYTE)(DWORD_PTR)0xfffffffffff80000; - ODPRINTF((L"mhooks: TrampolineAlloc: Allocating for %p between %p and %p", pSystemFunction, pLower, pUpper)); - - // try to find a trampoline in the specified range - pTrampoline = FindTrampolineInRange(pLower, pUpper); - if (!pTrampoline) { - // if it we can't find it, then we need to allocate a new block and - // try again. Just fail if that doesn't work - g_pFreeList = BlockAlloc(pSystemFunction, pLower, pUpper); - pTrampoline = FindTrampolineInRange(pLower, pUpper); - } - - // found and allocated a trampoline? - if (pTrampoline) { - ListPrepend(&g_pHooks, pTrampoline); - } - - return pTrampoline; -} - -//========================================================================= -// Internal function: -// -// Return the internal trampoline structure that belongs to a hooked function. -//========================================================================= -static MHOOKS_TRAMPOLINE* TrampolineGet(PBYTE pHookedFunction) { - MHOOKS_TRAMPOLINE* pCurrent = g_pHooks; - - while (pCurrent) { - if (pCurrent->pHookFunction == pHookedFunction) { - return pCurrent; - } - - pCurrent = pCurrent->pNextTrampoline; - } - - return NULL; -} - -//========================================================================= -// Internal function: -// -// Free a trampoline structure. -//========================================================================= -static VOID TrampolineFree(MHOOKS_TRAMPOLINE* pTrampoline, BOOL bNeverUsed) { - ListRemove(&g_pHooks, pTrampoline); - - // If a thread could feasinbly have some of our trampoline code - // on its stack and we yank the region from underneath it then it will - // surely crash upon returning. So instead of freeing the - // memory we just let it leak. Ugly, but safe. - if (bNeverUsed) { - ListPrepend(&g_pFreeList, pTrampoline); - } - - g_nHooksInUse--; -} - -//========================================================================= -// Internal function: -// -// Suspend a given thread and try to make sure that its instruction -// pointer is not in the given range. -//========================================================================= -static HANDLE SuspendOneThread(DWORD dwThreadId, PBYTE pbCode, DWORD cbBytes) { - // open the thread - HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId); - if (GOOD_HANDLE(hThread)) { - // attempt suspension - DWORD dwSuspendCount = SuspendThread(hThread); - if (dwSuspendCount != -1) { - // see where the IP is - CONTEXT ctx; - ctx.ContextFlags = CONTEXT_CONTROL; - int nTries = 0; - while (GetThreadContext(hThread, &ctx)) { -#ifdef _M_IX86 - PBYTE pIp = (PBYTE)(DWORD_PTR)ctx.Eip; -#elif defined _M_X64 - PBYTE pIp = (PBYTE)(DWORD_PTR)ctx.Rip; -#endif - if (pbCode != NULL && pIp >= pbCode && pIp < (pbCode + cbBytes)) { - if (nTries < 3) { - // oops - we should try to get the instruction pointer out of here. - ODPRINTF((L"mhooks: SuspendOneThread: suspended thread %d - IP is at %p - IS COLLIDING WITH CODE", dwThreadId, pIp)); - ResumeThread(hThread); - Sleep(100); - SuspendThread(hThread); - nTries++; - } else { - // we gave it all we could. (this will probably never - // happen - unless the thread has already been suspended - // to begin with) - ODPRINTF((L"mhooks: SuspendOneThread: suspended thread %d - IP is at %p - IS COLLIDING WITH CODE - CAN'T FIX", dwThreadId, pIp)); - ResumeThread(hThread); - CloseHandle(hThread); - hThread = NULL; - break; - } - } else { - // success, the IP is not conflicting - ODPRINTF((L"mhooks: SuspendOneThread: Successfully suspended thread %d - IP is at %p", dwThreadId, pIp)); - break; - } - } - } else { - // couldn't suspend - CloseHandle(hThread); - hThread = NULL; - } - } - return hThread; -} - -//========================================================================= -// Internal function: -// -// Resumes all previously suspended threads in the current process. -//========================================================================= -static VOID ResumeOtherThreads() { - // make sure things go as fast as possible - INT nOriginalPriority = GetThreadPriority(GetCurrentThread()); - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - // go through our list - for (DWORD i=0; inRipCnt; i++) { - DWORD dwNewDisplacement = (DWORD)(pdata->rips[i].nDisplacement - diff); - ODPRINTF((L"mhooks: fixing up RIP instruction operand for code at 0x%p: " - L"old displacement: 0x%8.8x, new displacement: 0x%8.8x", - pbNew + pdata->rips[i].dwOffset, - (DWORD)pdata->rips[i].nDisplacement, - dwNewDisplacement)); - *(PDWORD)(pbNew + pdata->rips[i].dwOffset) = dwNewDisplacement; - } -#endif -} - -//========================================================================= -// Examine the machine code at the target function's entry point, and -// skip bytes in a way that we'll always end on an instruction boundary. -// We also detect branches and subroutine calls (as well as returns) -// at which point disassembly must stop. -// Finally, detect and collect information on IP-relative instructions -// that we can patch. -static DWORD DisassembleAndSkip(PVOID pFunction, DWORD dwMinLen, MHOOKS_PATCHDATA* pdata) { - DWORD dwRet = 0; - pdata->nLimitDown = 0; - pdata->nLimitUp = 0; - pdata->nRipCnt = 0; -#ifdef _M_IX86 - ARCHITECTURE_TYPE arch = ARCH_X86; -#elif defined _M_X64 - ARCHITECTURE_TYPE arch = ARCH_X64; -#else - #error unsupported platform -#endif - DISASSEMBLER dis; - if (InitDisassembler(&dis, arch)) { - INSTRUCTION* pins = NULL; - U8* pLoc = (U8*)pFunction; - DWORD dwFlags = DISASM_DECODE | DISASM_DISASSEMBLE | DISASM_ALIGNOUTPUT; - - ODPRINTF((L"mhooks: DisassembleAndSkip: Disassembling %p", pLoc)); - while ( (dwRet < dwMinLen) && (pins = GetInstruction(&dis, (ULONG_PTR)pLoc, pLoc, dwFlags)) ) { - ODPRINTF(("mhooks: DisassembleAndSkip: %p:(0x%2.2x) %s", pLoc, pins->Length, pins->String)); - if (pins->Type == ITYPE_RET ) break; - if (pins->Type == ITYPE_BRANCH ) break; - if (pins->Type == ITYPE_BRANCHCC) break; - if (pins->Type == ITYPE_CALL ) break; - if (pins->Type == ITYPE_CALLCC ) break; - - #if defined _M_X64 - BOOL bProcessRip = FALSE; - // mov or lea to register from rip+imm32 - if ((pins->Type == ITYPE_MOV || pins->Type == ITYPE_LEA) && (pins->X86.Relative) && - (pins->X86.OperandSize == 8) && (pins->OperandCount == 2) && - (pins->Operands[1].Flags & OP_IPREL) && (pins->Operands[1].Register == AMD64_REG_RIP)) - { - // rip-addressing "mov reg, [rip+imm32]" - ODPRINTF((L"mhooks: DisassembleAndSkip: found OP_IPREL on operand %d with displacement 0x%x (in memory: 0x%x)", 1, pins->X86.Displacement, *(PDWORD)(pLoc+3))); - bProcessRip = TRUE; - } - // mov or lea to rip+imm32 from register - else if ((pins->Type == ITYPE_MOV || pins->Type == ITYPE_LEA) && (pins->X86.Relative) && - (pins->X86.OperandSize == 8) && (pins->OperandCount == 2) && - (pins->Operands[0].Flags & OP_IPREL) && (pins->Operands[0].Register == AMD64_REG_RIP)) - { - // rip-addressing "mov [rip+imm32], reg" - ODPRINTF((L"mhooks: DisassembleAndSkip: found OP_IPREL on operand %d with displacement 0x%x (in memory: 0x%x)", 0, pins->X86.Displacement, *(PDWORD)(pLoc+3))); - bProcessRip = TRUE; - } - else if ( (pins->OperandCount >= 1) && (pins->Operands[0].Flags & OP_IPREL) ) - { - // unsupported rip-addressing - ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 0)); - // dump instruction bytes to the debug output - for (DWORD i=0; iLength; i++) { - ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i])); - } - break; - } - else if ( (pins->OperandCount >= 2) && (pins->Operands[1].Flags & OP_IPREL) ) - { - // unsupported rip-addressing - ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 1)); - // dump instruction bytes to the debug output - for (DWORD i=0; iLength; i++) { - ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i])); - } - break; - } - else if ( (pins->OperandCount >= 3) && (pins->Operands[2].Flags & OP_IPREL) ) - { - // unsupported rip-addressing - ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 2)); - // dump instruction bytes to the debug output - for (DWORD i=0; iLength; i++) { - ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i])); - } - break; - } - // follow through with RIP-processing if needed - if (bProcessRip) { - // calculate displacement relative to function start - S64 nAdjustedDisplacement = pins->X86.Displacement + (pLoc - (U8*)pFunction); - // store displacement values furthest from zero (both positive and negative) - if (nAdjustedDisplacement < pdata->nLimitDown) - pdata->nLimitDown = nAdjustedDisplacement; - if (nAdjustedDisplacement > pdata->nLimitUp) - pdata->nLimitUp = nAdjustedDisplacement; - // store patch info - if (pdata->nRipCnt < MHOOKS_MAX_RIPS) { - pdata->rips[pdata->nRipCnt].dwOffset = dwRet + 3; - pdata->rips[pdata->nRipCnt].nDisplacement = pins->X86.Displacement; - pdata->nRipCnt++; - } else { - // no room for patch info, stop disassembly - break; - } - } - #endif - - dwRet += pins->Length; - pLoc += pins->Length; - } - - CloseDisassembler(&dis); - } - - return dwRet; -} - -//========================================================================= -void Mhook_SuspendOtherThreads() { - SuspendOtherThreads(NULL, 0); - g_bThreadsSuspended = TRUE; -} -void Mhook_ResumeOtherThreads() { - ResumeOtherThreads(); - g_bThreadsSuspended = FALSE; -} -//========================================================================= - -//========================================================================= -bool Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction) { - MHOOKS_TRAMPOLINE* pTrampoline = NULL; - PVOID pSystemFunction = *ppSystemFunction; - // ensure thread-safety - EnterCritSec(); - ODPRINTF((L"mhooks: Mhook_SetHook: Started on the job: %p / %p", pSystemFunction, pHookFunction)); - // find the real functions (jump over jump tables, if any) - pSystemFunction = SkipJumps((PBYTE)pSystemFunction); - pHookFunction = SkipJumps((PBYTE)pHookFunction); - ODPRINTF((L"mhooks: Mhook_SetHook: Started on the job: %p / %p", pSystemFunction, pHookFunction)); - // figure out the length of the overwrite zone - MHOOKS_PATCHDATA patchdata = {0}; - DWORD dwInstructionLength = DisassembleAndSkip(pSystemFunction, MHOOK_JMPSIZE, &patchdata); - if (dwInstructionLength >= MHOOK_JMPSIZE) { - ODPRINTF((L"mhooks: Mhook_SetHook: disassembly signals %d bytes", dwInstructionLength)); - // suspend every other thread in this process, and make sure their IP - // is not in the code we're about to overwrite. - SuspendOtherThreads((PBYTE)pSystemFunction, dwInstructionLength); - // allocate a trampoline structure (TODO: it is pretty wasteful to get - // VirtualAlloc to grab chunks of memory smaller than 100 bytes) - pTrampoline = TrampolineAlloc((PBYTE)pSystemFunction, patchdata.nLimitUp, patchdata.nLimitDown); - if (pTrampoline) { - ODPRINTF((L"mhooks: Mhook_SetHook: allocated structure at %p", pTrampoline)); - DWORD dwOldProtectSystemFunction = 0; - DWORD dwOldProtectTrampolineFunction = 0; - // set the system function to PAGE_EXECUTE_READWRITE - if (VirtualProtect(pSystemFunction, dwInstructionLength, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) { - ODPRINTF((L"mhooks: Mhook_SetHook: readwrite set on system function")); - // mark our trampoline buffer to PAGE_EXECUTE_READWRITE - if (VirtualProtect(pTrampoline, sizeof(MHOOKS_TRAMPOLINE), PAGE_EXECUTE_READWRITE, &dwOldProtectTrampolineFunction)) { - ODPRINTF((L"mhooks: Mhook_SetHook: readwrite set on trampoline structure")); - - // create our trampoline function - PBYTE pbCode = pTrampoline->codeTrampoline; - // save original code.. - for (DWORD i = 0; icodeUntouched[i] = pbCode[i] = ((PBYTE)pSystemFunction)[i]; - } - pbCode += dwInstructionLength; - // plus a jump to the continuation in the original location - pbCode = EmitJump(pbCode, ((PBYTE)pSystemFunction) + dwInstructionLength); - ODPRINTF((L"mhooks: Mhook_SetHook: updated the trampoline")); - - // fix up any IP-relative addressing in the code - FixupIPRelativeAddressing(pTrampoline->codeTrampoline, (PBYTE)pSystemFunction, &patchdata); - - DWORD_PTR dwDistance = (PBYTE)pHookFunction < (PBYTE)pSystemFunction ? - (PBYTE)pSystemFunction - (PBYTE)pHookFunction : (PBYTE)pHookFunction - (PBYTE)pSystemFunction; - if (dwDistance > 0x7fff0000) { - // create a stub that jumps to the replacement function. - // we need this because jumping from the API to the hook directly - // will be a long jump, which is 14 bytes on x64, and we want to - // avoid that - the API may or may not have room for such stuff. - // (remember, we only have 5 bytes guaranteed in the API.) - // on the other hand we do have room, and the trampoline will always be - // within +/- 2GB of the API, so we do the long jump in there. - // the API will jump to the "reverse trampoline" which - // will jump to the user's hook code. - pbCode = pTrampoline->codeJumpToHookFunction; - pbCode = EmitJump(pbCode, (PBYTE)pHookFunction); - ODPRINTF((L"mhooks: Mhook_SetHook: created reverse trampoline")); - FlushInstructionCache(GetCurrentProcess(), pTrampoline->codeJumpToHookFunction, - pbCode - pTrampoline->codeJumpToHookFunction); - - // update the API itself - pbCode = (PBYTE)pSystemFunction; - pbCode = EmitJump(pbCode, pTrampoline->codeJumpToHookFunction); - } else { - // the jump will be at most 5 bytes so we can do it directly - // update the API itself - pbCode = (PBYTE)pSystemFunction; - pbCode = EmitJump(pbCode, (PBYTE)pHookFunction); - } - - // update data members - pTrampoline->cbOverwrittenCode = dwInstructionLength; - pTrampoline->pSystemFunction = (PBYTE)pSystemFunction; - pTrampoline->pHookFunction = (PBYTE)pHookFunction; - - // flush instruction cache and restore original protection - FlushInstructionCache(GetCurrentProcess(), pTrampoline->codeTrampoline, dwInstructionLength); - VirtualProtect(pTrampoline, sizeof(MHOOKS_TRAMPOLINE), dwOldProtectTrampolineFunction, &dwOldProtectTrampolineFunction); - } else { - ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtect 2: %d", gle())); - } - // flush instruction cache and restore original protection - FlushInstructionCache(GetCurrentProcess(), pSystemFunction, dwInstructionLength); - VirtualProtect(pSystemFunction, dwInstructionLength, dwOldProtectSystemFunction, &dwOldProtectSystemFunction); - } else { - ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtect 1: %d", gle())); - } - if (pTrampoline->pSystemFunction) { - // this is what the application will use as the entry point - // to the "original" unhooked function. - *ppSystemFunction = pTrampoline->codeTrampoline; - ODPRINTF((L"mhooks: Mhook_SetHook: Hooked the function!")); - } else { - // if we failed discard the trampoline (forcing VirtualFree) - TrampolineFree(pTrampoline, TRUE); - pTrampoline = NULL; - } - } - // resume everybody else - ResumeOtherThreads(); - } else { - ODPRINTF((L"mhooks: disassembly signals %d bytes (unacceptable)", dwInstructionLength)); - } - LeaveCritSec(); - return (pTrampoline != NULL); -} - -//========================================================================= -bool Mhook_Unhook(PVOID *ppHookedFunction) { - ODPRINTF((L"mhooks: Mhook_Unhook: %p", *ppHookedFunction)); - bool bRet = false; - EnterCritSec(); - // get the trampoline structure that corresponds to our function - MHOOKS_TRAMPOLINE* pTrampoline = TrampolineGet((PBYTE)*ppHookedFunction); - if (pTrampoline) { - // make sure nobody's executing code where we're about to overwrite a few bytes - SuspendOtherThreads(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode); - ODPRINTF((L"mhooks: Mhook_Unhook: found struct at %p", pTrampoline)); - DWORD dwOldProtectSystemFunction = 0; - // make memory writable - if (VirtualProtect(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) { - ODPRINTF((L"mhooks: Mhook_Unhook: readwrite set on system function")); - PBYTE pbCode = (PBYTE)pTrampoline->pSystemFunction; - for (DWORD i = 0; icbOverwrittenCode; i++) { - pbCode[i] = pTrampoline->codeUntouched[i]; - } - // flush instruction cache and make memory unwritable - FlushInstructionCache(GetCurrentProcess(), pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode); - VirtualProtect(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode, dwOldProtectSystemFunction, &dwOldProtectSystemFunction); - // return the original function pointer - *ppHookedFunction = pTrampoline->pSystemFunction; - bRet = true; - ODPRINTF((L"mhooks: Mhook_Unhook: sysfunc: %p", *ppHookedFunction)); - // free the trampoline while not really discarding it from memory - TrampolineFree(pTrampoline, FALSE); - ODPRINTF((L"mhooks: Mhook_Unhook: unhook successful")); - } else { - ODPRINTF((L"mhooks: Mhook_Unhook: failed VirtualProtect 1: %d", gle())); - } - // make the other guys runnable - ResumeOtherThreads(); - } - LeaveCritSec(); - return bRet; -} - -//========================================================================= diff --git a/renderdoc/3rdparty/mhook/mhook-lib/mhook.h b/renderdoc/3rdparty/mhook/mhook-lib/mhook.h deleted file mode 100644 index a0acfa6ac..000000000 --- a/renderdoc/3rdparty/mhook/mhook-lib/mhook.h +++ /dev/null @@ -1,40 +0,0 @@ -//Copyright (c) 2007-2008, Marton Anka -// -//Permission is hereby granted, free of charge, to any person obtaining a -//copy of this software and associated documentation files (the "Software"), -//to deal in the Software without restriction, including without limitation -//the rights to use, copy, modify, merge, publish, distribute, sublicense, -//and/or sell copies of the Software, and to permit persons to whom the -//Software is furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included -//in all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -//OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -//THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -//IN THE SOFTWARE. - -#ifdef _M_IX86 -#define _M_IX86_X64 -#elif defined _M_X64 -#define _M_IX86_X64 -#endif - -bool Mhook_SetHook(void **ppSystemFunction, void *pHookFunction); -bool Mhook_Unhook(void **ppHookedFunction); - -// optimisation - when setting many hooks CreateToolHelp32Snapshot to enumerate threads -// can become a bottleneck, allow apps to suspend threads across multiple hooks -// -// note - it's the responsibility of user code to ensure that the threads don't have -// their instruction pointer near any of the hooks - as this would normally be handled -// on a per-hook basis. -// -// these functions are also not thread safe. -void Mhook_SuspendOtherThreads(); -void Mhook_ResumeOtherThreads(); - diff --git a/renderdoccmd/miniz.c b/renderdoc/3rdparty/miniz/miniz.c similarity index 100% rename from renderdoccmd/miniz.c rename to renderdoc/3rdparty/miniz/miniz.c diff --git a/renderdoccmd/miniz.h b/renderdoc/3rdparty/miniz/miniz.h similarity index 100% rename from renderdoccmd/miniz.h rename to renderdoc/3rdparty/miniz/miniz.h diff --git a/renderdoc/core/crash_handler.h b/renderdoc/core/crash_handler.h index 234f71de0..721605fe4 100644 --- a/renderdoc/core/crash_handler.h +++ b/renderdoc/core/crash_handler.h @@ -29,8 +29,8 @@ #define CRASH_HANDLER_ENABLED // breakpad -#include "client/windows/handler/exception_handler.h" -#include "client/windows/common/ipc_protocol.h" +#include "breakpad/client/windows/handler/exception_handler.h" +#include "breakpad/client/windows/common/ipc_protocol.h" class CrashHandler : public ICrashHandler { diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 1f51f7452..6678be869 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -24,7 +24,7 @@ #include "replay_proxy.h" -#include "3rdparty/lz4/lz4.h" +#include "lz4/lz4.h" template<> string ToStrHelper::Get(const SystemAttribute &el) diff --git a/renderdoc/data/resource.h b/renderdoc/data/resource.h index 0ac4ca753..b4bfe186c 100644 --- a/renderdoc/data/resource.h +++ b/renderdoc/data/resource.h @@ -25,7 +25,7 @@ #endif #define GIT_COMMIT_HASH "NO_GIT_COMMIT_HASH_DEFINED" -//#define RENDERDOC_OFFICIAL_BUILD // used to determine whether to submit auto crash reports +#define RENDERDOC_OFFICIAL_BUILD // used to determine whether to submit auto crash reports // Next default values for new objects // diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index f691e585a..dd928eed8 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -35,7 +35,7 @@ #include "driver/d3d11/d3d11_renderstate.h" #include "driver/d3d11/d3d11_context.h" -#include "3rdparty/jpeg-compressor/jpge.h" +#include "jpeg-compressor/jpge.h" #if defined(INCLUDE_D3D_11_1) #include diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index baa620f49..725baf5a0 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -32,7 +32,7 @@ #include "maths/vec.h" -#include "3rdparty/jpeg-compressor/jpge.h" +#include "jpeg-compressor/jpge.h" const char *GLChunkNames[] = { diff --git a/renderdoc/hooks/d3d11_hooks.cpp b/renderdoc/hooks/d3d11_hooks.cpp index 1cf744a57..d105b6dd5 100644 --- a/renderdoc/hooks/d3d11_hooks.cpp +++ b/renderdoc/hooks/d3d11_hooks.cpp @@ -39,15 +39,6 @@ public: { bool success = true; -#if USE_MHOOK - // require dxgi.dll hooked as well for proper operation - if(GetModuleHandleA("dxgi.dll") == NULL) - { - RDCWARN("Failed to load dxgi.dll - not inserting D3D11 hooks."); - return false; - } -#endif - // also require d3dcompiler_??.dll if(GetD3DCompiler() == NULL) { @@ -60,19 +51,6 @@ public: if(!success) return false; -#if USE_MHOOK - // FRAPS compatibility. Save out the first 16 bytes (arbitrary number) of the 'real' function code. - // this should be - // jmp D3D11CreateDeviceAndSwapChain_hook - // push r12 <- this is where our trampoline jumps back to - // push r13 - // - // FRAPS stomps over this with its own hook that we detect and handle later. - void *hooked_func_ptr = GetProcAddress(GetModuleHandleA("d3d11.dll"), "D3D11CreateDeviceAndSwapChain"); - if(hooked_func_ptr == NULL) return false; - memcpy(CreateDeviceAndSwapChain_ident, hooked_func_ptr, 16); -#endif - m_HasHooks = true; m_EnabledHooks = true; @@ -192,32 +170,6 @@ private: PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN createFunc = (PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN)GetProcAddress(GetModuleHandleA("d3d11.dll"), "D3D11CreateDeviceAndSwapChain"); -#if USE_MHOOK - if(createFunc) - { - byte ident[16]; - memcpy(ident, createFunc, 16); - - // FRAPS compatibility. If FRAPS has come in and modified the real code to something like - // mov rax, [ptrintofraps] - // jmp rax - // then we just jump straight there. If we jump to the trampoline, we'll come in half way through - // those instructions and things will go boom very quickly. - // - // Note that when we call this function FRAPS then restores the asm from before it got here, which is our - // trampolined code, so FRAPS is going to call back into this function. We detect this re-entrancy - // at the top and just go straight into the real d3d function now that FRAPS has restored our trampoline, - // and return right back here - // What a headache! - // - // in the non-fraps case no-one else has messed with this code so the idents will be the same and we - // will use our trampolines. - - if(!memcmp(ident, CreateDeviceAndSwapChain_ident, 16) && m_HasHooks) - createFunc = CreateDeviceAndSwapChain(); - } -#endif - // shouldn't ever get here, we should either have it from procaddress or the trampoline, but let's be // safe. if(createFunc == NULL) diff --git a/renderdoc/hooks/dxgi_hooks.cpp b/renderdoc/hooks/dxgi_hooks.cpp index d7a5e6c5e..1238f79ed 100644 --- a/renderdoc/hooks/dxgi_hooks.cpp +++ b/renderdoc/hooks/dxgi_hooks.cpp @@ -40,11 +40,6 @@ public: { bool success = true; -#if USE_MHOOK - // require d3d11.dll hooked as well for proper operation - if(GetModuleHandleA("d3d11.dll") == NULL) return false; -#endif - success &= CreateDXGIFactory.Initialize("CreateDXGIFactory", DLL_NAME, CreateDXGIFactory_hook); success &= CreateDXGIFactory1.Initialize("CreateDXGIFactory1", DLL_NAME, CreateDXGIFactory1_hook); diff --git a/renderdoc/hooks/gl_win32_hooks.cpp b/renderdoc/hooks/gl_win32_hooks.cpp index db1ec37fd..6e17d6347 100644 --- a/renderdoc/hooks/gl_win32_hooks.cpp +++ b/renderdoc/hooks/gl_win32_hooks.cpp @@ -228,14 +228,6 @@ class OpenGLHook : LibraryHook if(!m_EnabledHooks) return false; -#if USE_MHOOK - if(GetModuleHandleA(DLL_NAME) == NULL) - { - RDCWARN("Failed to load %hs - not inserting OpenGL hooks.", DLL_NAME); - return false; - } -#endif - bool success = SetupHooks(GL); if(!success) return false; diff --git a/renderdoc/hooks/hooks.h b/renderdoc/hooks/hooks.h index e60da3b68..061004643 100644 --- a/renderdoc/hooks/hooks.h +++ b/renderdoc/hooks/hooks.h @@ -35,13 +35,7 @@ using std::map; #if defined(WIN32) -#if USE_MHOOK - #include "3rdparty/mhook/mhook-lib/mhook.h" -#elif USE_IAT_HOOK - #include "os/win32/win32_hook.h" -#else - #error "No hook method enabled" -#endif +#include "os/win32/win32_hook.h" template class Hook @@ -53,9 +47,6 @@ class Hook } ~Hook() { -#if USE_MHOOK - Mhook_Unhook(&orig_funcptr); -#endif } FuncType operator()() @@ -67,29 +58,15 @@ class Hook { orig_funcptr = Process::GetFunctionAddress(module_name, function); -#if USE_MHOOK - if(orig_funcptr == NULL) - return false; - - return Mhook_SetHook(&orig_funcptr, destination_function_ptr); -#elif USE_IAT_HOOK return Win32_IAT_Hook(&orig_funcptr, module_name, function, destination_function_ptr); -#else - #error "No hook method enabled" -#endif } private: void *orig_funcptr; }; -#if USE_MHOOK - #define HOOKS_BEGIN() Mhook_SuspendOtherThreads() - #define HOOKS_END() Mhook_ResumeOtherThreads() -#else - #define HOOKS_BEGIN() Win32_IAT_BeginHooks() - #define HOOKS_END() Win32_IAT_EndHooks() -#endif +#define HOOKS_BEGIN() Win32_IAT_BeginHooks() +#define HOOKS_END() Win32_IAT_EndHooks() #elif defined(LINUX) diff --git a/renderdoc/os/win32/win32_process.cpp b/renderdoc/os/win32/win32_process.cpp index a8aef6412..6435a4897 100644 --- a/renderdoc/os/win32/win32_process.cpp +++ b/renderdoc/os/win32/win32_process.cpp @@ -292,20 +292,6 @@ uint32_t Process::InjectIntoProcess(uint32_t pid, const wchar_t *logfile, const } #endif -#if USE_MHOOK - // misc - InjectDLL(hProcess, L"kernel32.dll"); - - // D3D11 - InjectDLL(hProcess, L"d3d9.dll"); - InjectDLL(hProcess, L"d3d11.dll"); - InjectDLL(hProcess, L"dxgi.dll"); - - // OpenGL - InjectDLL(hProcess, L"opengl32.dll"); - InjectDLL(hProcess, L"gdi32.dll"); -#endif - InjectDLL(hProcess, renderdocPath); uintptr_t loc = FindRemoteDLL(pid, L"renderdoc.dll"); diff --git a/renderdoc/os/win32/win32_shellext.cpp b/renderdoc/os/win32/win32_shellext.cpp index 804d92c72..3c4c53c66 100644 --- a/renderdoc/os/win32/win32_shellext.cpp +++ b/renderdoc/os/win32/win32_shellext.cpp @@ -32,7 +32,7 @@ #include "core/core.h" #include "serialise/serialiser.h" -#include "3rdparty/jpeg-compressor/jpgd.h" +#include "jpeg-compressor/jpgd.h" // {5D6BF029-A6BA-417A-8523-120492B1DCE3} static const GUID CLSID_RDCThumbnailProvider = { 0x5d6bf029, 0xa6ba, 0x417a, { 0x85, 0x23, 0x12, 0x4, 0x92, 0xb1, 0xdc, 0xe3 } }; diff --git a/renderdoc/os/win32_specific.h b/renderdoc/os/win32_specific.h index caa19cde7..4300aa8f8 100644 --- a/renderdoc/os/win32_specific.h +++ b/renderdoc/os/win32_specific.h @@ -47,8 +47,3 @@ namespace Threading { typedef CriticalSectionTemplate CriticalSection; }; - -// Hooking configuration -#define USE_MHOOK 0 -#define USE_IAT_HOOK 1 - diff --git a/renderdoc/renderdoc.vcxproj b/renderdoc/renderdoc.vcxproj index cbd2cdc79..a5e656288 100644 --- a/renderdoc/renderdoc.vcxproj +++ b/renderdoc/renderdoc.vcxproj @@ -69,15 +69,16 @@ false $(SolutionDir)$(Platform)\$(Configuration)\ $(ProgramFiles)\Windows Kits\8.1\Debuggers\inc;$(ProgramFiles)\Windows Kits\8.1\Include\um;$(ProgramFiles)\Windows Kits\8.1\Include\shared;$(VSInstallDir)\DIA SDK\include;$(SolutionDir)\breakpad;$(IncludePath) - $(ProgramFiles)\Windows Kits\8.1\lib\win8\um\x86;$(SolutionDir)\breakpad\$(PlatformToolset)\lib32;$(LibraryPath) + $(ProgramFiles)\Windows Kits\8.1\lib\win8\um\x86;$(LibraryPath) $(ProgramFiles)\Windows Kits\8.1\bin\x86;$(ExecutablePath) $(ProgramFiles)\Windows Kits\8.1\Include\um;$(ProgramFiles)\Windows Kits\8.1\Include\shared;$(ExcludePath) + $(Platform)\$(Configuration)\ false - $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ $(ProgramFiles)\Windows Kits\8.1\Debuggers\inc;$(ProgramFiles)\Windows Kits\8.1\Include\um;$(ProgramFiles)\Windows Kits\8.1\Include\shared;$(VSInstallDir)\DIA SDK\include;$(SolutionDir)\breakpad;$(IncludePath) - $(ProgramFiles)\Windows Kits\8.1\lib\win8\um\x64;$(SolutionDir)\breakpad\$(PlatformToolset)\lib64;$(LibraryPath) + $(ProgramFiles)\Windows Kits\8.1\lib\win8\um\x64;$(LibraryPath) $(ProgramFiles)\Windows Kits\8.1\bin;$(ExecutablePath) $(ProgramFiles)\Windows Kits\8.1\Include\um;$(ProgramFiles)\Windows Kits\8.1\Include\shared;$(ExcludePath) @@ -85,15 +86,16 @@ false $(SolutionDir)$(Platform)\$(Configuration)\ $(ProgramFiles)\Windows Kits\8.1\Debuggers\inc;$(ProgramFiles)\Windows Kits\8.1\Include\um;$(ProgramFiles)\Windows Kits\8.1\Include\shared;$(VSInstallDir)\DIA SDK\include;$(SolutionDir)\breakpad;$(IncludePath) - $(ProgramFiles)\Windows Kits\8.1\lib\win8\um\x86;$(SolutionDir)\breakpad\$(PlatformToolset)\lib32;$(LibraryPath) + $(ProgramFiles)\Windows Kits\8.1\lib\win8\um\x86;$(LibraryPath) $(ProgramFiles)\Windows Kits\8.1\bin\x86;$(ExecutablePath) $(ProgramFiles)\Windows Kits\8.1\Include\um;$(ProgramFiles)\Windows Kits\8.1\Include\shared;$(ExcludePath) + $(Platform)\$(Configuration)\ false - $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ $(ProgramFiles)\Windows Kits\8.1\Debuggers\inc;$(ProgramFiles)\Windows Kits\8.1\Include\um;$(ProgramFiles)\Windows Kits\8.1\Include\shared;$(VSInstallDir)\DIA SDK\include;$(SolutionDir)\breakpad;$(IncludePath) - $(ProgramFiles)\Windows Kits\8.1\lib\win8\um\x64;$(SolutionDir)\breakpad\$(PlatformToolset)\lib64;$(LibraryPath) + $(ProgramFiles)\Windows Kits\8.1\lib\win8\um\x64;$(LibraryPath) $(ProgramFiles)\Windows Kits\8.1\bin;$(ExecutablePath) $(ProgramFiles)\Windows Kits\8.1\Include\um;$(ProgramFiles)\Windows Kits\8.1\Include\shared;$(ExcludePath) @@ -108,7 +110,7 @@ /wd4100 /wd4189 /wd4127 /DRENDERDOC_PLATFORM=win32 %(AdditionalOptions) - $(ProjectDir) + $(ProjectDir);$(SolutionDir)renderdoc\3rdparty\ false true true @@ -119,7 +121,7 @@ true true $(ProjectDir)os\win32\comexport.def - breakpad_common.lib;exception_handler.lib;crash_generation_client.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;psapi.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\breakpad_common.lib;$(SolutionDir)\renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\crash_generation_client.lib;$(SolutionDir)\renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\exception_handler.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;psapi.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) @@ -137,7 +139,7 @@ /wd4100 /wd4189 /wd4127 /DRENDERDOC_PLATFORM=win32 %(AdditionalOptions) - $(ProjectDir) + $(ProjectDir);$(SolutionDir)renderdoc\3rdparty\ false true true @@ -148,7 +150,7 @@ true true $(ProjectDir)os\win32\comexport.def - breakpad_common.lib;exception_handler.lib;crash_generation_client.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;psapi.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\breakpad_common.lib;$(SolutionDir)\renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\crash_generation_client.lib;$(SolutionDir)\renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\exception_handler.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;psapi.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) xcopy /Y /Q /S "$(SolutionDir)\Win32\$(ConfigurationName)\pdblocate" "$(OutputPath)\pdblocate\" @@ -167,7 +169,7 @@ /wd4100 /wd4189 /wd4127 %(AdditionalOptions) false EnableFastChecks - $(ProjectDir) + $(ProjectDir);$(SolutionDir)renderdoc\3rdparty\ false false true @@ -179,7 +181,7 @@ false false $(ProjectDir)os\win32\comexport.def - breakpad_common.lib;exception_handler.lib;crash_generation_client.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;psapi.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;psapi.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Default @@ -200,7 +202,7 @@ /wd4100 /wd4189 /wd4127 /DRENDERDOC_PLATFORM=win32 %(AdditionalOptions) false EnableFastChecks - $(ProjectDir) + $(ProjectDir);$(SolutionDir)renderdoc\3rdparty\ false true true @@ -211,7 +213,7 @@ false false $(ProjectDir)os\win32\comexport.def - breakpad_common.lib;exception_handler.lib;crash_generation_client.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;psapi.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;psapi.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Default @@ -222,12 +224,6 @@ - - - - - - @@ -300,11 +296,6 @@ - - - - - diff --git a/renderdoc/renderdoc.vcxproj.filters b/renderdoc/renderdoc.vcxproj.filters index eea95cd14..ec5ae44b9 100644 --- a/renderdoc/renderdoc.vcxproj.filters +++ b/renderdoc/renderdoc.vcxproj.filters @@ -46,12 +46,6 @@ {36ccf267-d6c1-41c9-87c3-92c1dfcbe88b} - - {62242fef-51cb-419e-bbe9-3347653ece06} - - - {880a29ed-1f7d-46f2-9bcd-c4a9b73b7be5} - {dfe56374-9726-4919-8529-123cf5ba6ef5} @@ -61,9 +55,6 @@ {1d17fb69-fd1a-44a6-a530-05642d97ddc6} - - {911d2076-eaea-4783-b0c3-789e5b6eff1f} - {0ecdcd74-a30b-457e-8b22-92bd58405c56} @@ -73,9 +64,6 @@ {5e7e0e62-aba4-4256-b0ec-a1a7fbcba715} - - {f22a6629-346c-400d-9706-7f999d539f6b} - {7d6b0f22-1180-4767-b284-cc87f54ec012} @@ -88,6 +76,15 @@ {eb0686f4-bcb3-4edd-b488-937b1491909b} + + {5f5e3b49-5091-4a26-b24b-723ebb95ba78} + + + {d7a4190d-f68a-4e08-877f-04be35995e03} + + + {043f5a32-683e-4b56-bcc6-512444b40d70} + @@ -198,30 +195,6 @@ Drivers\OpenGL - - 3rdparty\mhook - - - 3rdparty\mhook - - - 3rdparty\mhook - - - 3rdparty\mhook - - - 3rdparty\mhook - - - 3rdparty\mhook - - - 3rdparty\jpeg-compressor - - - 3rdparty\jpeg-compressor - Common\Maths @@ -234,9 +207,6 @@ Core\networking - - 3rdparty\lz4 - Core @@ -279,12 +249,6 @@ Drivers\OpenGL - - 3rdparty\stb - - - 3rdparty\stb - Resources @@ -318,6 +282,21 @@ Common\File Formats + + 3rdparty\jpeg-compressor + + + 3rdparty\jpeg-compressor + + + 3rdparty\lz4 + + + 3rdparty\stb + + + 3rdparty\stb + @@ -425,27 +404,6 @@ OS\Win32 - - 3rdparty\mhook - - - 3rdparty\mhook - - - 3rdparty\mhook - - - 3rdparty\mhook - - - 3rdparty\mhook - - - 3rdparty\jpeg-compressor - - - 3rdparty\jpeg-compressor - OS\Win32 @@ -464,9 +422,6 @@ Core\networking - - 3rdparty\lz4 - Replay @@ -539,12 +494,21 @@ Drivers\OpenGL - - 3rdparty\stb - Common\File Formats + + 3rdparty\jpeg-compressor + + + 3rdparty\jpeg-compressor + + + 3rdparty\lz4 + + + 3rdparty\stb + @@ -592,4 +556,4 @@ Resources - \ No newline at end of file + diff --git a/renderdoc/replay/replay_renderer.cpp b/renderdoc/replay/replay_renderer.cpp index 9b0651584..4d9808846 100644 --- a/renderdoc/replay/replay_renderer.cpp +++ b/renderdoc/replay/replay_renderer.cpp @@ -34,10 +34,10 @@ #include "serialise/serialiser.h" -#include "3rdparty/jpeg-compressor/jpgd.h" -#include "3rdparty/jpeg-compressor/jpge.h" -#include "3rdparty/stb/stb_image.h" -#include "3rdparty/stb/stb_image_write.h" +#include "jpeg-compressor/jpgd.h" +#include "jpeg-compressor/jpge.h" +#include "stb/stb_image.h" +#include "stb/stb_image_write.h" #include "common/dds_readwrite.h" static inline float ConvertComponent(ResourceFormat fmt, byte *data) diff --git a/renderdoccmd/renderdoccmd.vcxproj b/renderdoccmd/renderdoccmd.vcxproj index 9d23312c2..fbe0c0d3d 100644 --- a/renderdoccmd/renderdoccmd.vcxproj +++ b/renderdoccmd/renderdoccmd.vcxproj @@ -64,26 +64,26 @@ true - $(SolutionDir)\breakpad;$(IncludePath) - $(SolutionDir)\breakpad\$(PlatformToolset)\lib32;$(LibraryPath) + $(IncludePath) + $(LibraryPath) $(SolutionDir)$(Platform)\$(Configuration)\ true - $(SolutionDir)\breakpad;$(IncludePath) - $(SolutionDir)\breakpad\$(PlatformToolset)\lib64;$(LibraryPath) + $(IncludePath) + $(LibraryPath) $(SolutionDir)\$(Platform)\$(Configuration)\ false - $(SolutionDir)\breakpad;$(IncludePath) - $(SolutionDir)\breakpad\$(PlatformToolset)\lib32;$(LibraryPath) + $(IncludePath) + $(LibraryPath) $(SolutionDir)$(Platform)\$(Configuration)\ false - $(SolutionDir)\breakpad;$(IncludePath) - $(SolutionDir)\breakpad\$(PlatformToolset)\lib64;$(LibraryPath) + $(IncludePath) + $(LibraryPath) $(SolutionDir)\$(Platform)\$(Configuration)\ @@ -93,14 +93,14 @@ Level3 Disabled WIN32;RENDERDOC_PLATFORM=win32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\renderdoc\api\ + ..\renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\ MultiThreadedDLL true Windows true - $(OutDir)\renderdoc.lib;breakpad_common.lib;crash_generation_server.lib;ws2_32.lib;Wininet.lib;%(AdditionalDependencies) + ws2_32.lib;Wininet.lib;%(AdditionalDependencies) @@ -110,14 +110,14 @@ Level3 Disabled WIN32;RENDERDOC_PLATFORM=win32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\renderdoc\api\ + ..\renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\ MultiThreadedDLL true Windows true - $(OutDir)\renderdoc.lib;breakpad_common.lib;crash_generation_server.lib;ws2_32.lib;Wininet.lib;%(AdditionalDependencies) + ws2_32.lib;Wininet.lib;%(AdditionalDependencies) @@ -128,8 +128,8 @@ MaxSpeed true true - WIN32;RENDERDOC_PLATFORM=win32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\renderdoc\api\ + WIN32;RENDERDOC_PLATFORM=win32;NDEBUG;RELEASE;_CONSOLE;%(PreprocessorDefinitions) + ..\renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\ true @@ -137,7 +137,7 @@ true true true - $(OutDir)\renderdoc.lib;breakpad_common.lib;crash_generation_server.lib;ws2_32.lib;Wininet.lib;%(AdditionalDependencies) + $(SolutionDir)\renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\breakpad_common.lib;$(SolutionDir)\renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\crash_generation_server.lib;ws2_32.lib;Wininet.lib;%(AdditionalDependencies) @@ -148,8 +148,8 @@ MaxSpeed true true - WIN32;RENDERDOC_PLATFORM=win32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\renderdoc\api\ + WIN32;RENDERDOC_PLATFORM=win32;NDEBUG;RELEASE;_CONSOLE;%(PreprocessorDefinitions) + ..\renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\ true @@ -157,11 +157,11 @@ true true true - $(OutDir)\renderdoc.lib;breakpad_common.lib;crash_generation_server.lib;ws2_32.lib;Wininet.lib;%(AdditionalDependencies) + $(SolutionDir)\renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\breakpad_common.lib;$(SolutionDir)\renderdoc\3rdparty\breakpad\$(Platform)\$(Configuration)\crash_generation_server.lib;ws2_32.lib;Wininet.lib;%(AdditionalDependencies) - + @@ -169,13 +169,23 @@ - + + + + {e2b46d67-90e2-40b6-9597-72930e7845e5} + false + true + false + true + false + + diff --git a/renderdoccmd/renderdoccmd.vcxproj.filters b/renderdoccmd/renderdoccmd.vcxproj.filters index 8b3124ff2..1625b4795 100644 --- a/renderdoccmd/renderdoccmd.vcxproj.filters +++ b/renderdoccmd/renderdoccmd.vcxproj.filters @@ -2,8 +2,10 @@ - + + 3rdparty + @@ -12,12 +14,17 @@ Resources - + + 3rdparty + {3979a11e-8029-4886-a51e-a2a9bb91d69f} + + {a8ca84b9-239b-4640-95e9-f9bd141ef465} + diff --git a/renderdoccmd/renderdoccmd_win32.cpp b/renderdoccmd/renderdoccmd_win32.cpp index d824a31f6..577cf201f 100644 --- a/renderdoccmd/renderdoccmd_win32.cpp +++ b/renderdoccmd/renderdoccmd_win32.cpp @@ -31,17 +31,20 @@ #include "resource.h" -// breakpad -#include "common/windows/http_upload.h" -#include "client/windows/crash_generation/client_info.h" -#include "client/windows/crash_generation/crash_generation_server.h" - -#include "miniz.h" +#include "miniz/miniz.h" using std::string; using std::wstring; using std::vector; +HINSTANCE hInstance = NULL; + +#if defined(RELEASE) +// breakpad +#include "breakpad/common/windows/http_upload.h" +#include "breakpad/client/windows/crash_generation/client_info.h" +#include "breakpad/client/windows/crash_generation/crash_generation_server.h" + using google_breakpad::ClientInfo; using google_breakpad::CrashGenerationServer; @@ -59,8 +62,6 @@ wstring dump = L""; vector customInfo; wstring logpath = L""; -HINSTANCE hInstance = NULL; - INT_PTR CALLBACK CrashHandlerProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) @@ -186,6 +187,7 @@ static void _cdecl OnClientExited(void* context, const ClientInfo* client_info) { exitServer = true; } +#endif LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -319,7 +321,8 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, { return 1; } - + +#if defined(RELEASE) CrashGenerationServer *crashServer = NULL; // special WIN32 option for launching the crash handler @@ -494,6 +497,7 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, return 0; } +#endif return renderdoccmd(argc, argv); }