diff options
Diffstat (limited to 'tools/debugserver/source/DNBDataRef.cpp')
-rw-r--r-- | tools/debugserver/source/DNBDataRef.cpp | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/tools/debugserver/source/DNBDataRef.cpp b/tools/debugserver/source/DNBDataRef.cpp new file mode 100644 index 0000000000000..53e9881dfb94e --- /dev/null +++ b/tools/debugserver/source/DNBDataRef.cpp @@ -0,0 +1,386 @@ +//===-- DNBDataRef.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Created by Greg Clayton on 1/11/06. +// +//===----------------------------------------------------------------------===// + +#include "DNBDataRef.h" +#include "DNBLog.h" +#include <assert.h> +#include <ctype.h> +#include <libkern/OSByteOrder.h> + +//---------------------------------------------------------------------- +// Constructor +//---------------------------------------------------------------------- + +DNBDataRef::DNBDataRef() : + m_start(NULL), + m_end(NULL), + m_swap(false), + m_ptrSize(0), + m_addrPCRelative(INVALID_NUB_ADDRESS), + m_addrTEXT(INVALID_NUB_ADDRESS), + m_addrDATA(INVALID_NUB_ADDRESS) +{ +} + + +//---------------------------------------------------------------------- +// Constructor +//---------------------------------------------------------------------- + +DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap) : + m_start(start), + m_end(start+size), + m_swap(swap), + m_ptrSize(0), + m_addrPCRelative(INVALID_NUB_ADDRESS), + m_addrTEXT(INVALID_NUB_ADDRESS), + m_addrDATA(INVALID_NUB_ADDRESS) +{ +} + + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- + +DNBDataRef::~DNBDataRef() +{ +} + + +//---------------------------------------------------------------------- +// Get8 +//---------------------------------------------------------------------- +uint8_t +DNBDataRef::Get8(offset_t *offset_ptr) const +{ + uint8_t val = 0; + if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) ) + { + val = *(m_start + *offset_ptr); + *offset_ptr += sizeof(val); + } + return val; +} + + +//---------------------------------------------------------------------- +// Get16 +//---------------------------------------------------------------------- +uint16_t +DNBDataRef::Get16(offset_t *offset_ptr) const +{ + uint16_t val = 0; + if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) ) + { + const uint8_t *p = m_start + *offset_ptr; + val = *(uint16_t*)p; + + if (m_swap) + val = OSSwapInt16(val); + + // Advance the offset + *offset_ptr += sizeof(val); + } + return val; +} + + +//---------------------------------------------------------------------- +// Get32 +//---------------------------------------------------------------------- +uint32_t +DNBDataRef::Get32(offset_t *offset_ptr) const +{ + uint32_t val = 0; + if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) ) + { + const uint8_t *p = m_start + *offset_ptr; + val = *(uint32_t*)p; + if (m_swap) + val = OSSwapInt32(val); + + // Advance the offset + *offset_ptr += sizeof(val); + } + return val; +} + + +//---------------------------------------------------------------------- +// Get64 +//---------------------------------------------------------------------- +uint64_t +DNBDataRef::Get64(offset_t *offset_ptr) const +{ + uint64_t val = 0; + if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) ) + { + const uint8_t *p = m_start + *offset_ptr; + val = *(uint64_t*)p; + if (m_swap) + val = OSSwapInt64(val); + + // Advance the offset + *offset_ptr += sizeof(val); + } + return val; +} + + +//---------------------------------------------------------------------- +// GetMax32 +// +// Used for calls when the size can vary. Fill in extra cases if they +// are ever needed. +//---------------------------------------------------------------------- +uint32_t +DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const +{ + switch (byte_size) + { + case 1: return Get8 (offset_ptr); break; + case 2: return Get16(offset_ptr); break; + case 4: return Get32(offset_ptr); break; + default: + assert(!"GetMax32 unhandled case!"); + break; + } + return 0; +} + + +//---------------------------------------------------------------------- +// GetMax64 +// +// Used for calls when the size can vary. Fill in extra cases if they +// are ever needed. +//---------------------------------------------------------------------- +uint64_t +DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const +{ + switch (size) + { + case 1: return Get8 (offset_ptr); break; + case 2: return Get16(offset_ptr); break; + case 4: return Get32(offset_ptr); break; + case 8: return Get64(offset_ptr); break; + default: + assert(!"GetMax64 unhandled case!"); + break; + } + return 0; +} + +//---------------------------------------------------------------------- +// GetPointer +// +// Extract a pointer value from the buffer. The pointer size must be +// set prior to using this using one of the SetPointerSize functions. +//---------------------------------------------------------------------- +uint64_t +DNBDataRef::GetPointer(offset_t *offset_ptr) const +{ + // Must set pointer size prior to using this call + assert(m_ptrSize != 0); + return GetMax64(offset_ptr, m_ptrSize); +} +//---------------------------------------------------------------------- +// GetCStr +//---------------------------------------------------------------------- +const char * +DNBDataRef::GetCStr(offset_t *offset_ptr, uint32_t fixed_length) const +{ + const char *s = NULL; + if ( m_start < m_end ) + { + s = (char*)m_start + *offset_ptr; + + // Advance the offset + if (fixed_length) + *offset_ptr += fixed_length; + else + *offset_ptr += strlen(s) + 1; + } + return s; +} + + +//---------------------------------------------------------------------- +// GetData +//---------------------------------------------------------------------- +const uint8_t * +DNBDataRef::GetData(offset_t *offset_ptr, uint32_t length) const +{ + const uint8_t *data = NULL; + if ( length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length) ) + { + data = m_start + *offset_ptr; + *offset_ptr += length; + } + return data; +} + + +//---------------------------------------------------------------------- +// Get_ULEB128 +//---------------------------------------------------------------------- +uint64_t +DNBDataRef::Get_ULEB128 (offset_t *offset_ptr) const +{ + uint64_t result = 0; + if ( m_start < m_end ) + { + int shift = 0; + const uint8_t *src = m_start + *offset_ptr; + uint8_t byte; + int bytecount = 0; + + while (src < m_end) + { + bytecount++; + byte = *src++; + result |= (byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + break; + } + + *offset_ptr += bytecount; + } + return result; +} + + +//---------------------------------------------------------------------- +// Get_SLEB128 +//---------------------------------------------------------------------- +int64_t +DNBDataRef::Get_SLEB128 (offset_t *offset_ptr) const +{ + int64_t result = 0; + + if ( m_start < m_end ) + { + int shift = 0; + int size = sizeof (uint32_t) * 8; + const uint8_t *src = m_start + *offset_ptr; + + uint8_t byte = 0; + int bytecount = 0; + + while (src < m_end) + { + bytecount++; + byte = *src++; + result |= (byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + break; + } + + // Sign bit of byte is 2nd high order bit (0x40) + if (shift < size && (byte & 0x40)) + result |= - (1ll << shift); + + *offset_ptr += bytecount; + } + return result; +} + + +//---------------------------------------------------------------------- +// Skip_LEB128 +// +// Skips past ULEB128 and SLEB128 numbers (just updates the offset) +//---------------------------------------------------------------------- +void +DNBDataRef::Skip_LEB128 (offset_t *offset_ptr) const +{ + if ( m_start < m_end ) + { + const uint8_t *start = m_start + *offset_ptr; + const uint8_t *src = start; + + while ((src < m_end) && (*src++ & 0x80)) + /* Do nothing */; + + *offset_ptr += src - start; + } +} + +uint32_t +DNBDataRef::Dump +( + uint32_t startOffset, + uint32_t endOffset, + uint64_t offsetBase, + DNBDataRef::Type type, + uint32_t numPerLine, + const char *format +) +{ + uint32_t offset; + uint32_t count; + char str[1024]; + str[0] = '\0'; + size_t str_offset = 0; + + for (offset = startOffset, count = 0; ValidOffset(offset) && offset < endOffset; ++count) + { + if ((count % numPerLine) == 0) + { + // Print out any previous string + if (str[0] != '\0') + DNBLog("%s", str); + // Reset string offset and fill the current line string with address: + str_offset = 0; + str_offset += snprintf(str, sizeof(str), "0x%8.8llx:", (uint64_t)(offsetBase + (offset - startOffset))); + } + + // Make sure we don't pass the bounds of our current string buffer on each iteration through this loop + if (str_offset >= sizeof(str)) + { + // The last snprintf consumed our string buffer, we will need to dump this out + // and reset the string with no address + DNBLog("%s", str); + str_offset = 0; + str[0] = '\0'; + } + + // We already checked that there is at least some room in the string str above, so it is safe to make + // the snprintf call each time through this loop + switch (type) + { + default: + case TypeUInt8: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %2.2x", Get8(&offset)); break; + case TypeChar: + { + char ch = Get8(&offset); + str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %c", isprint(ch) ? ch : ' '); + } + break; + case TypeUInt16: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %4.4x", Get16(&offset)); break; + case TypeUInt32: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %8.8x", Get32(&offset)); break; + case TypeUInt64: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %16.16llx", Get64(&offset)); break; + case TypePointer: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " 0x%llx", GetPointer(&offset)); break; + case TypeULEB128: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " 0x%llx", Get_ULEB128(&offset)); break; + case TypeSLEB128: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %lld", Get_SLEB128(&offset)); break; + } + } + + if (str[0] != '\0') + DNBLog("%s", str); + + return offset; // Return the offset at which we ended up +} |