130fdc8d8SChris Lattner //===-- DNBDataRef.cpp ------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner // 1030fdc8d8SChris Lattner // Created by Greg Clayton on 1/11/06. 1130fdc8d8SChris Lattner // 1230fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 1330fdc8d8SChris Lattner 1430fdc8d8SChris Lattner #include "DNBDataRef.h" 1530fdc8d8SChris Lattner #include "DNBLog.h" 1630fdc8d8SChris Lattner #include <assert.h> 1730fdc8d8SChris Lattner #include <ctype.h> 1830fdc8d8SChris Lattner #include <libkern/OSByteOrder.h> 1930fdc8d8SChris Lattner 2030fdc8d8SChris Lattner //---------------------------------------------------------------------- 2130fdc8d8SChris Lattner // Constructor 2230fdc8d8SChris Lattner //---------------------------------------------------------------------- 2330fdc8d8SChris Lattner 24b9c1b51eSKate Stone DNBDataRef::DNBDataRef() 25b9c1b51eSKate Stone : m_start(NULL), m_end(NULL), m_swap(false), m_ptrSize(0), 26b9c1b51eSKate Stone m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS), 27b9c1b51eSKate Stone m_addrDATA(INVALID_NUB_ADDRESS) {} 2830fdc8d8SChris Lattner 2930fdc8d8SChris Lattner //---------------------------------------------------------------------- 3030fdc8d8SChris Lattner // Constructor 3130fdc8d8SChris Lattner //---------------------------------------------------------------------- 3230fdc8d8SChris Lattner 33b9c1b51eSKate Stone DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap) 34b9c1b51eSKate Stone : m_start(start), m_end(start + size), m_swap(swap), m_ptrSize(0), 35b9c1b51eSKate Stone m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS), 36b9c1b51eSKate Stone m_addrDATA(INVALID_NUB_ADDRESS) {} 3730fdc8d8SChris Lattner 3830fdc8d8SChris Lattner //---------------------------------------------------------------------- 3930fdc8d8SChris Lattner // Destructor 4030fdc8d8SChris Lattner //---------------------------------------------------------------------- 4130fdc8d8SChris Lattner 42b9c1b51eSKate Stone DNBDataRef::~DNBDataRef() {} 4330fdc8d8SChris Lattner 4430fdc8d8SChris Lattner //---------------------------------------------------------------------- 4530fdc8d8SChris Lattner // Get8 4630fdc8d8SChris Lattner //---------------------------------------------------------------------- 47b9c1b51eSKate Stone uint8_t DNBDataRef::Get8(offset_t *offset_ptr) const { 4830fdc8d8SChris Lattner uint8_t val = 0; 49b9c1b51eSKate Stone if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { 5030fdc8d8SChris Lattner val = *(m_start + *offset_ptr); 5130fdc8d8SChris Lattner *offset_ptr += sizeof(val); 5230fdc8d8SChris Lattner } 5330fdc8d8SChris Lattner return val; 5430fdc8d8SChris Lattner } 5530fdc8d8SChris Lattner 5630fdc8d8SChris Lattner //---------------------------------------------------------------------- 5730fdc8d8SChris Lattner // Get16 5830fdc8d8SChris Lattner //---------------------------------------------------------------------- 59b9c1b51eSKate Stone uint16_t DNBDataRef::Get16(offset_t *offset_ptr) const { 6030fdc8d8SChris Lattner uint16_t val = 0; 61b9c1b51eSKate Stone if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { 6230fdc8d8SChris Lattner const uint8_t *p = m_start + *offset_ptr; 6330fdc8d8SChris Lattner val = *(uint16_t *)p; 6430fdc8d8SChris Lattner 6530fdc8d8SChris Lattner if (m_swap) 6630fdc8d8SChris Lattner val = OSSwapInt16(val); 6730fdc8d8SChris Lattner 6830fdc8d8SChris Lattner // Advance the offset 6930fdc8d8SChris Lattner *offset_ptr += sizeof(val); 7030fdc8d8SChris Lattner } 7130fdc8d8SChris Lattner return val; 7230fdc8d8SChris Lattner } 7330fdc8d8SChris Lattner 7430fdc8d8SChris Lattner //---------------------------------------------------------------------- 7530fdc8d8SChris Lattner // Get32 7630fdc8d8SChris Lattner //---------------------------------------------------------------------- 77b9c1b51eSKate Stone uint32_t DNBDataRef::Get32(offset_t *offset_ptr) const { 7830fdc8d8SChris Lattner uint32_t val = 0; 79b9c1b51eSKate Stone if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { 8030fdc8d8SChris Lattner const uint8_t *p = m_start + *offset_ptr; 8130fdc8d8SChris Lattner val = *(uint32_t *)p; 8230fdc8d8SChris Lattner if (m_swap) 8330fdc8d8SChris Lattner val = OSSwapInt32(val); 8430fdc8d8SChris Lattner 8530fdc8d8SChris Lattner // Advance the offset 8630fdc8d8SChris Lattner *offset_ptr += sizeof(val); 8730fdc8d8SChris Lattner } 8830fdc8d8SChris Lattner return val; 8930fdc8d8SChris Lattner } 9030fdc8d8SChris Lattner 9130fdc8d8SChris Lattner //---------------------------------------------------------------------- 9230fdc8d8SChris Lattner // Get64 9330fdc8d8SChris Lattner //---------------------------------------------------------------------- 94b9c1b51eSKate Stone uint64_t DNBDataRef::Get64(offset_t *offset_ptr) const { 9530fdc8d8SChris Lattner uint64_t val = 0; 96b9c1b51eSKate Stone if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { 9730fdc8d8SChris Lattner const uint8_t *p = m_start + *offset_ptr; 9830fdc8d8SChris Lattner val = *(uint64_t *)p; 9930fdc8d8SChris Lattner if (m_swap) 10030fdc8d8SChris Lattner val = OSSwapInt64(val); 10130fdc8d8SChris Lattner 10230fdc8d8SChris Lattner // Advance the offset 10330fdc8d8SChris Lattner *offset_ptr += sizeof(val); 10430fdc8d8SChris Lattner } 10530fdc8d8SChris Lattner return val; 10630fdc8d8SChris Lattner } 10730fdc8d8SChris Lattner 10830fdc8d8SChris Lattner //---------------------------------------------------------------------- 10930fdc8d8SChris Lattner // GetMax32 11030fdc8d8SChris Lattner // 11130fdc8d8SChris Lattner // Used for calls when the size can vary. Fill in extra cases if they 11230fdc8d8SChris Lattner // are ever needed. 11330fdc8d8SChris Lattner //---------------------------------------------------------------------- 114b9c1b51eSKate Stone uint32_t DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const { 115b9c1b51eSKate Stone switch (byte_size) { 116b9c1b51eSKate Stone case 1: 117b9c1b51eSKate Stone return Get8(offset_ptr); 118*a77ec68eSDavid Blaikie break; 119b9c1b51eSKate Stone case 2: 120b9c1b51eSKate Stone return Get16(offset_ptr); 121*a77ec68eSDavid Blaikie break; 122b9c1b51eSKate Stone case 4: 123b9c1b51eSKate Stone return Get32(offset_ptr); 124*a77ec68eSDavid Blaikie break; 12530fdc8d8SChris Lattner default: 126*a77ec68eSDavid Blaikie assert(!"GetMax32 unhandled case!"); 127*a77ec68eSDavid Blaikie break; 12830fdc8d8SChris Lattner } 129*a77ec68eSDavid Blaikie return 0; 13030fdc8d8SChris Lattner } 13130fdc8d8SChris Lattner 13230fdc8d8SChris Lattner //---------------------------------------------------------------------- 13330fdc8d8SChris Lattner // GetMax64 13430fdc8d8SChris Lattner // 13530fdc8d8SChris Lattner // Used for calls when the size can vary. Fill in extra cases if they 13630fdc8d8SChris Lattner // are ever needed. 13730fdc8d8SChris Lattner //---------------------------------------------------------------------- 138b9c1b51eSKate Stone uint64_t DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const { 139b9c1b51eSKate Stone switch (size) { 140b9c1b51eSKate Stone case 1: 141b9c1b51eSKate Stone return Get8(offset_ptr); 142*a77ec68eSDavid Blaikie break; 143b9c1b51eSKate Stone case 2: 144b9c1b51eSKate Stone return Get16(offset_ptr); 145*a77ec68eSDavid Blaikie break; 146b9c1b51eSKate Stone case 4: 147b9c1b51eSKate Stone return Get32(offset_ptr); 148*a77ec68eSDavid Blaikie break; 149b9c1b51eSKate Stone case 8: 150b9c1b51eSKate Stone return Get64(offset_ptr); 151*a77ec68eSDavid Blaikie break; 15230fdc8d8SChris Lattner default: 153*a77ec68eSDavid Blaikie assert(!"GetMax64 unhandled case!"); 154*a77ec68eSDavid Blaikie break; 15530fdc8d8SChris Lattner } 156*a77ec68eSDavid Blaikie return 0; 15730fdc8d8SChris Lattner } 15830fdc8d8SChris Lattner 15930fdc8d8SChris Lattner //---------------------------------------------------------------------- 16030fdc8d8SChris Lattner // GetPointer 16130fdc8d8SChris Lattner // 16230fdc8d8SChris Lattner // Extract a pointer value from the buffer. The pointer size must be 16330fdc8d8SChris Lattner // set prior to using this using one of the SetPointerSize functions. 16430fdc8d8SChris Lattner //---------------------------------------------------------------------- 165b9c1b51eSKate Stone uint64_t DNBDataRef::GetPointer(offset_t *offset_ptr) const { 16630fdc8d8SChris Lattner // Must set pointer size prior to using this call 16730fdc8d8SChris Lattner assert(m_ptrSize != 0); 16830fdc8d8SChris Lattner return GetMax64(offset_ptr, m_ptrSize); 16930fdc8d8SChris Lattner } 17030fdc8d8SChris Lattner //---------------------------------------------------------------------- 17130fdc8d8SChris Lattner // GetCStr 17230fdc8d8SChris Lattner //---------------------------------------------------------------------- 173b9c1b51eSKate Stone const char *DNBDataRef::GetCStr(offset_t *offset_ptr, 174b9c1b51eSKate Stone uint32_t fixed_length) const { 17530fdc8d8SChris Lattner const char *s = NULL; 176b9c1b51eSKate Stone if (m_start < m_end) { 17730fdc8d8SChris Lattner s = (char *)m_start + *offset_ptr; 17830fdc8d8SChris Lattner 17930fdc8d8SChris Lattner // Advance the offset 18030fdc8d8SChris Lattner if (fixed_length) 18130fdc8d8SChris Lattner *offset_ptr += fixed_length; 18230fdc8d8SChris Lattner else 18330fdc8d8SChris Lattner *offset_ptr += strlen(s) + 1; 18430fdc8d8SChris Lattner } 18530fdc8d8SChris Lattner return s; 18630fdc8d8SChris Lattner } 18730fdc8d8SChris Lattner 18830fdc8d8SChris Lattner //---------------------------------------------------------------------- 18930fdc8d8SChris Lattner // GetData 19030fdc8d8SChris Lattner //---------------------------------------------------------------------- 191b9c1b51eSKate Stone const uint8_t *DNBDataRef::GetData(offset_t *offset_ptr, 192b9c1b51eSKate Stone uint32_t length) const { 19330fdc8d8SChris Lattner const uint8_t *data = NULL; 194b9c1b51eSKate Stone if (length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length)) { 19530fdc8d8SChris Lattner data = m_start + *offset_ptr; 19630fdc8d8SChris Lattner *offset_ptr += length; 19730fdc8d8SChris Lattner } 19830fdc8d8SChris Lattner return data; 19930fdc8d8SChris Lattner } 20030fdc8d8SChris Lattner 20130fdc8d8SChris Lattner //---------------------------------------------------------------------- 20230fdc8d8SChris Lattner // Get_ULEB128 20330fdc8d8SChris Lattner //---------------------------------------------------------------------- 204b9c1b51eSKate Stone uint64_t DNBDataRef::Get_ULEB128(offset_t *offset_ptr) const { 20530fdc8d8SChris Lattner uint64_t result = 0; 206b9c1b51eSKate Stone if (m_start < m_end) { 20730fdc8d8SChris Lattner int shift = 0; 20830fdc8d8SChris Lattner const uint8_t *src = m_start + *offset_ptr; 20930fdc8d8SChris Lattner uint8_t byte; 21030fdc8d8SChris Lattner int bytecount = 0; 21130fdc8d8SChris Lattner 212b9c1b51eSKate Stone while (src < m_end) { 21330fdc8d8SChris Lattner bytecount++; 21430fdc8d8SChris Lattner byte = *src++; 215d781d2c9SGreg Clayton result |= (uint64_t)(byte & 0x7f) << shift; 21630fdc8d8SChris Lattner shift += 7; 21730fdc8d8SChris Lattner if ((byte & 0x80) == 0) 21830fdc8d8SChris Lattner break; 21930fdc8d8SChris Lattner } 22030fdc8d8SChris Lattner 22130fdc8d8SChris Lattner *offset_ptr += bytecount; 22230fdc8d8SChris Lattner } 22330fdc8d8SChris Lattner return result; 22430fdc8d8SChris Lattner } 22530fdc8d8SChris Lattner 22630fdc8d8SChris Lattner //---------------------------------------------------------------------- 22730fdc8d8SChris Lattner // Get_SLEB128 22830fdc8d8SChris Lattner //---------------------------------------------------------------------- 229b9c1b51eSKate Stone int64_t DNBDataRef::Get_SLEB128(offset_t *offset_ptr) const { 23030fdc8d8SChris Lattner int64_t result = 0; 23130fdc8d8SChris Lattner 232b9c1b51eSKate Stone if (m_start < m_end) { 23330fdc8d8SChris Lattner int shift = 0; 23430fdc8d8SChris Lattner int size = sizeof(uint32_t) * 8; 23530fdc8d8SChris Lattner const uint8_t *src = m_start + *offset_ptr; 23630fdc8d8SChris Lattner 237d14651afSJohnny Chen uint8_t byte = 0; 23830fdc8d8SChris Lattner int bytecount = 0; 23930fdc8d8SChris Lattner 240b9c1b51eSKate Stone while (src < m_end) { 24130fdc8d8SChris Lattner bytecount++; 24230fdc8d8SChris Lattner byte = *src++; 243d781d2c9SGreg Clayton result |= (int64_t)(byte & 0x7f) << shift; 24430fdc8d8SChris Lattner shift += 7; 24530fdc8d8SChris Lattner if ((byte & 0x80) == 0) 24630fdc8d8SChris Lattner break; 24730fdc8d8SChris Lattner } 24830fdc8d8SChris Lattner 24930fdc8d8SChris Lattner // Sign bit of byte is 2nd high order bit (0x40) 25030fdc8d8SChris Lattner if (shift < size && (byte & 0x40)) 25130fdc8d8SChris Lattner result |= -(1ll << shift); 25230fdc8d8SChris Lattner 25330fdc8d8SChris Lattner *offset_ptr += bytecount; 25430fdc8d8SChris Lattner } 25530fdc8d8SChris Lattner return result; 25630fdc8d8SChris Lattner } 25730fdc8d8SChris Lattner 25830fdc8d8SChris Lattner //---------------------------------------------------------------------- 25930fdc8d8SChris Lattner // Skip_LEB128 26030fdc8d8SChris Lattner // 26130fdc8d8SChris Lattner // Skips past ULEB128 and SLEB128 numbers (just updates the offset) 26230fdc8d8SChris Lattner //---------------------------------------------------------------------- 263b9c1b51eSKate Stone void DNBDataRef::Skip_LEB128(offset_t *offset_ptr) const { 264b9c1b51eSKate Stone if (m_start < m_end) { 26530fdc8d8SChris Lattner const uint8_t *start = m_start + *offset_ptr; 26630fdc8d8SChris Lattner const uint8_t *src = start; 26730fdc8d8SChris Lattner 26830fdc8d8SChris Lattner while ((src < m_end) && (*src++ & 0x80)) 26930fdc8d8SChris Lattner /* Do nothing */; 27030fdc8d8SChris Lattner 27130fdc8d8SChris Lattner *offset_ptr += src - start; 27230fdc8d8SChris Lattner } 27330fdc8d8SChris Lattner } 27430fdc8d8SChris Lattner 275b9c1b51eSKate Stone uint32_t DNBDataRef::Dump(uint32_t startOffset, uint32_t endOffset, 276b9c1b51eSKate Stone uint64_t offsetBase, DNBDataRef::Type type, 277b9c1b51eSKate Stone uint32_t numPerLine, const char *format) { 27830fdc8d8SChris Lattner uint32_t offset; 27930fdc8d8SChris Lattner uint32_t count; 28030fdc8d8SChris Lattner char str[1024]; 28130fdc8d8SChris Lattner str[0] = '\0'; 282a026de05SBruce Mitchener size_t str_offset = 0; 28330fdc8d8SChris Lattner 284b9c1b51eSKate Stone for (offset = startOffset, count = 0; 285b9c1b51eSKate Stone ValidOffset(offset) && offset < endOffset; ++count) { 286b9c1b51eSKate Stone if ((count % numPerLine) == 0) { 28730fdc8d8SChris Lattner // Print out any previous string 28830fdc8d8SChris Lattner if (str[0] != '\0') 28930fdc8d8SChris Lattner DNBLog("%s", str); 29030fdc8d8SChris Lattner // Reset string offset and fill the current line string with address: 29130fdc8d8SChris Lattner str_offset = 0; 292b9c1b51eSKate Stone str_offset += snprintf(str, sizeof(str), "0x%8.8llx:", 293b9c1b51eSKate Stone (uint64_t)(offsetBase + (offset - startOffset))); 29430fdc8d8SChris Lattner } 29530fdc8d8SChris Lattner 296b9c1b51eSKate Stone // Make sure we don't pass the bounds of our current string buffer on each 297b9c1b51eSKate Stone // iteration through this loop 298b9c1b51eSKate Stone if (str_offset >= sizeof(str)) { 299b9c1b51eSKate Stone // The last snprintf consumed our string buffer, we will need to dump this 300b9c1b51eSKate Stone // out 30130fdc8d8SChris Lattner // and reset the string with no address 30230fdc8d8SChris Lattner DNBLog("%s", str); 30330fdc8d8SChris Lattner str_offset = 0; 30430fdc8d8SChris Lattner str[0] = '\0'; 30530fdc8d8SChris Lattner } 30630fdc8d8SChris Lattner 307b9c1b51eSKate Stone // We already checked that there is at least some room in the string str 308b9c1b51eSKate Stone // above, so it is safe to make 30930fdc8d8SChris Lattner // the snprintf call each time through this loop 310b9c1b51eSKate Stone switch (type) { 311b9c1b51eSKate Stone case TypeUInt8: 312b9c1b51eSKate Stone str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, 313b9c1b51eSKate Stone format ? format : " %2.2x", Get8(&offset)); 31430fdc8d8SChris Lattner break; 315b9c1b51eSKate Stone case TypeChar: { 316b9c1b51eSKate Stone char ch = Get8(&offset); 317b9c1b51eSKate Stone str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, 318b9c1b51eSKate Stone format ? format : " %c", isprint(ch) ? ch : ' '); 319b9c1b51eSKate Stone } break; 320b9c1b51eSKate Stone case TypeUInt16: 321b9c1b51eSKate Stone str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, 322b9c1b51eSKate Stone format ? format : " %4.4x", Get16(&offset)); 323b9c1b51eSKate Stone break; 324b9c1b51eSKate Stone case TypeUInt32: 325b9c1b51eSKate Stone str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, 326b9c1b51eSKate Stone format ? format : " %8.8x", Get32(&offset)); 327b9c1b51eSKate Stone break; 328b9c1b51eSKate Stone case TypeUInt64: 329b9c1b51eSKate Stone str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, 330b9c1b51eSKate Stone format ? format : " %16.16llx", Get64(&offset)); 331b9c1b51eSKate Stone break; 332b9c1b51eSKate Stone case TypePointer: 333b9c1b51eSKate Stone str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, 334b9c1b51eSKate Stone format ? format : " 0x%llx", GetPointer(&offset)); 335b9c1b51eSKate Stone break; 336b9c1b51eSKate Stone case TypeULEB128: 337b9c1b51eSKate Stone str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, 338b9c1b51eSKate Stone format ? format : " 0x%llx", Get_ULEB128(&offset)); 339b9c1b51eSKate Stone break; 340b9c1b51eSKate Stone case TypeSLEB128: 341b9c1b51eSKate Stone str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, 342b9c1b51eSKate Stone format ? format : " %lld", Get_SLEB128(&offset)); 343b9c1b51eSKate Stone break; 34430fdc8d8SChris Lattner } 34530fdc8d8SChris Lattner } 34630fdc8d8SChris Lattner 34730fdc8d8SChris Lattner if (str[0] != '\0') 34830fdc8d8SChris Lattner DNBLog("%s", str); 34930fdc8d8SChris Lattner 35030fdc8d8SChris Lattner return offset; // Return the offset at which we ended up 35130fdc8d8SChris Lattner } 352