summaryrefslogtreecommitdiff
path: root/tools/debugserver/source/DNBDataRef.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/debugserver/source/DNBDataRef.cpp')
-rw-r--r--tools/debugserver/source/DNBDataRef.cpp386
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
+}