brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.7 KiB · 13ffd25 Raw
321 lines · cpp
1//===-- DNBDataRef.cpp ------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  Created by Greg Clayton on 1/11/06.10//11//===----------------------------------------------------------------------===//12 13#include "DNBDataRef.h"14#include "DNBLog.h"15#include <cassert>16#include <cctype>17#include <libkern/OSByteOrder.h>18 19// Constructor20 21DNBDataRef::DNBDataRef()22    : m_start(NULL), m_end(NULL), m_swap(false), m_ptrSize(0),23      m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS),24      m_addrDATA(INVALID_NUB_ADDRESS) {}25 26// Constructor27 28DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap)29    : m_start(start), m_end(start + size), m_swap(swap), m_ptrSize(0),30      m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS),31      m_addrDATA(INVALID_NUB_ADDRESS) {}32 33// Destructor34 35DNBDataRef::~DNBDataRef() = default;36 37// Get838uint8_t DNBDataRef::Get8(offset_t *offset_ptr) const {39  uint8_t val = 0;40  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {41    val = *(m_start + *offset_ptr);42    *offset_ptr += sizeof(val);43  }44  return val;45}46 47// Get1648uint16_t DNBDataRef::Get16(offset_t *offset_ptr) const {49  uint16_t val = 0;50  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {51    const uint8_t *p = m_start + *offset_ptr;52    memcpy(&val, p, sizeof(uint16_t));53 54    if (m_swap)55      val = OSSwapInt16(val);56 57    // Advance the offset58    *offset_ptr += sizeof(val);59  }60  return val;61}62 63// Get3264uint32_t DNBDataRef::Get32(offset_t *offset_ptr) const {65  uint32_t val = 0;66  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {67    const uint8_t *p = m_start + *offset_ptr;68    memcpy(&val, p, sizeof(uint32_t));69    if (m_swap)70      val = OSSwapInt32(val);71 72    // Advance the offset73    *offset_ptr += sizeof(val);74  }75  return val;76}77 78// Get6479uint64_t DNBDataRef::Get64(offset_t *offset_ptr) const {80  uint64_t val = 0;81  if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {82    const uint8_t *p = m_start + *offset_ptr;83    memcpy(&val, p, sizeof(uint64_t));84    if (m_swap)85      val = OSSwapInt64(val);86 87    // Advance the offset88    *offset_ptr += sizeof(val);89  }90  return val;91}92 93// GetMax3294//95// Used for calls when the size can vary. Fill in extra cases if they96// are ever needed.97uint32_t DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const {98  switch (byte_size) {99  case 1:100    return Get8(offset_ptr);101    break;102  case 2:103    return Get16(offset_ptr);104    break;105  case 4:106    return Get32(offset_ptr);107    break;108  default:109    assert(false && "GetMax32 unhandled case!");110    break;111  }112  return 0;113}114 115// GetMax64116//117// Used for calls when the size can vary. Fill in extra cases if they118// are ever needed.119uint64_t DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const {120  switch (size) {121  case 1:122    return Get8(offset_ptr);123    break;124  case 2:125    return Get16(offset_ptr);126    break;127  case 4:128    return Get32(offset_ptr);129    break;130  case 8:131    return Get64(offset_ptr);132    break;133  default:134    assert(false && "GetMax64 unhandled case!");135    break;136  }137  return 0;138}139 140// GetPointer141//142// Extract a pointer value from the buffer. The pointer size must be143// set prior to using this using one of the SetPointerSize functions.144uint64_t DNBDataRef::GetPointer(offset_t *offset_ptr) const {145  // Must set pointer size prior to using this call146  assert(m_ptrSize != 0);147  return GetMax64(offset_ptr, m_ptrSize);148}149// GetCStr150const char *DNBDataRef::GetCStr(offset_t *offset_ptr,151                                uint32_t fixed_length) const {152  const char *s = NULL;153  if (m_start < m_end) {154    s = (const char *)m_start + *offset_ptr;155 156    // Advance the offset157    if (fixed_length)158      *offset_ptr += fixed_length;159    else160      *offset_ptr += strlen(s) + 1;161  }162  return s;163}164 165// GetData166const uint8_t *DNBDataRef::GetData(offset_t *offset_ptr,167                                   uint32_t length) const {168  const uint8_t *data = NULL;169  if (length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length)) {170    data = m_start + *offset_ptr;171    *offset_ptr += length;172  }173  return data;174}175 176// Get_ULEB128177uint64_t DNBDataRef::Get_ULEB128(offset_t *offset_ptr) const {178  uint64_t result = 0;179  if (m_start < m_end) {180    int shift = 0;181    const uint8_t *src = m_start + *offset_ptr;182    uint8_t byte;183    int bytecount = 0;184 185    while (src < m_end) {186      bytecount++;187      byte = *src++;188      result |= (uint64_t)(byte & 0x7f) << shift;189      shift += 7;190      if ((byte & 0x80) == 0)191        break;192    }193 194    *offset_ptr += bytecount;195  }196  return result;197}198 199// Get_SLEB128200int64_t DNBDataRef::Get_SLEB128(offset_t *offset_ptr) const {201  int64_t result = 0;202 203  if (m_start < m_end) {204    int shift = 0;205    int size = sizeof(uint32_t) * 8;206    const uint8_t *src = m_start + *offset_ptr;207 208    uint8_t byte = 0;209    int bytecount = 0;210 211    while (src < m_end) {212      bytecount++;213      byte = *src++;214      result |= (int64_t)(byte & 0x7f) << shift;215      shift += 7;216      if ((byte & 0x80) == 0)217        break;218    }219 220    // Sign bit of byte is 2nd high order bit (0x40)221    if (shift < size && (byte & 0x40))222      result |= -(1ll << shift);223 224    *offset_ptr += bytecount;225  }226  return result;227}228 229// Skip_LEB128230//231// Skips past ULEB128 and SLEB128 numbers (just updates the offset)232void DNBDataRef::Skip_LEB128(offset_t *offset_ptr) const {233  if (m_start < m_end) {234    const uint8_t *start = m_start + *offset_ptr;235    const uint8_t *src = start;236 237    while ((src < m_end) && (*src++ & 0x80))238      /* Do nothing */;239 240    *offset_ptr += src - start;241  }242}243 244uint32_t DNBDataRef::Dump(uint32_t startOffset, uint32_t endOffset,245                          uint64_t offsetBase, DNBDataRef::Type type,246                          uint32_t numPerLine, const char *format) {247  uint32_t offset;248  uint32_t count;249  char str[1024];250  str[0] = '\0';251  size_t str_offset = 0;252 253  for (offset = startOffset, count = 0;254       ValidOffset(offset) && offset < endOffset; ++count) {255    if ((count % numPerLine) == 0) {256      // Print out any previous string257      if (str[0] != '\0')258        DNBLog("%s", str);259      // Reset string offset and fill the current line string with address:260      str_offset = 0;261      str_offset += snprintf(str, sizeof(str), "0x%8.8llx:",262                             (uint64_t)(offsetBase + (offset - startOffset)));263    }264 265    // Make sure we don't pass the bounds of our current string buffer on each266    // iteration through this loop267    if (str_offset >= sizeof(str)) {268      // The last snprintf consumed our string buffer, we will need to dump this269      // out270      // and reset the string with no address271      DNBLog("%s", str);272      str_offset = 0;273      str[0] = '\0';274    }275 276    // We already checked that there is at least some room in the string str277    // above, so it is safe to make278    // the snprintf call each time through this loop279    switch (type) {280    case TypeUInt8:281      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,282                             format ? format : " %2.2x", Get8(&offset));283      break;284    case TypeChar: {285      char ch = Get8(&offset);286      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,287                             format ? format : " %c", isprint(ch) ? ch : ' ');288    } break;289    case TypeUInt16:290      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,291                             format ? format : " %4.4x", Get16(&offset));292      break;293    case TypeUInt32:294      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,295                             format ? format : " %8.8x", Get32(&offset));296      break;297    case TypeUInt64:298      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,299                             format ? format : " %16.16llx", Get64(&offset));300      break;301    case TypePointer:302      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,303                             format ? format : " 0x%llx", GetPointer(&offset));304      break;305    case TypeULEB128:306      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,307                             format ? format : " 0x%llx", Get_ULEB128(&offset));308      break;309    case TypeSLEB128:310      str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,311                             format ? format : " %lld", Get_SLEB128(&offset));312      break;313    }314  }315 316  if (str[0] != '\0')317    DNBLog("%s", str);318 319  return offset; // Return the offset at which we ended up320}321