brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.6 KiB · eba905b Raw
287 lines · cpp
1//===-- CF.cpp ------------------------------------------------------------===//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#include "CF.h"10 11#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"12#include "lldb/DataFormatters/FormattersHelpers.h"13#include "lldb/Target/Language.h"14#include "lldb/Target/StackFrame.h"15#include "lldb/Target/Target.h"16#include "lldb/Utility/DataBufferHeap.h"17#include "lldb/Utility/Endian.h"18#include "lldb/Utility/Status.h"19#include "lldb/Utility/Stream.h"20#include "lldb/ValueObject/ValueObject.h"21#include "lldb/ValueObject/ValueObjectConstResult.h"22 23#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"24 25using namespace lldb;26using namespace lldb_private;27using namespace lldb_private::formatters;28 29bool lldb_private::formatters::CFAbsoluteTimeSummaryProvider(30    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {31  time_t epoch = GetOSXEpoch();32  epoch = epoch + (time_t)valobj.GetValueAsSigned(0);33  tm *tm_date = localtime(&epoch);34  if (!tm_date)35    return false;36  std::string buffer(1024, 0);37  if (strftime(&buffer[0], 1023, "%Z", tm_date) == 0)38    return false;39  stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year + 1900,40                tm_date->tm_mon + 1, tm_date->tm_mday, tm_date->tm_hour,41                tm_date->tm_min, tm_date->tm_sec, buffer.c_str());42  return true;43}44 45bool lldb_private::formatters::CFBagSummaryProvider(46    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {47  static constexpr llvm::StringLiteral g_TypeHint("CFBag");48 49  ProcessSP process_sp = valobj.GetProcessSP();50  if (!process_sp)51    return false;52 53  ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);54 55  if (!runtime)56    return false;57 58  ObjCLanguageRuntime::ClassDescriptorSP descriptor(59      runtime->GetClassDescriptor(valobj));60 61  if (!descriptor.get() || !descriptor->IsValid())62    return false;63 64  uint32_t ptr_size = process_sp->GetAddressByteSize();65 66  lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);67 68  if (!valobj_addr)69    return false;70 71  uint32_t count = 0;72 73  bool is_type_ok = false; // check to see if this is a CFBag we know about74  if (descriptor->IsCFType()) {75    ConstString type_name(valobj.GetTypeName());76 77    static ConstString g_CFBag("__CFBag");78    static ConstString g_conststruct__CFBag("const struct __CFBag");79 80    if (type_name == g_CFBag || type_name == g_conststruct__CFBag) {81      if (valobj.IsPointerType())82        is_type_ok = true;83    }84  }85 86  if (is_type_ok) {87    lldb::addr_t offset = 2 * ptr_size + 4 + valobj_addr;88    Status error;89    count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);90    if (error.Fail())91      return false;92  } else93    return false;94 95  llvm::StringRef prefix, suffix;96  if (Language *language = Language::FindPlugin(options.GetLanguage()))97    std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);98 99  stream << prefix;100  stream.Printf("\"%u value%s\"", count, (count == 1 ? "" : "s"));101  stream << suffix;102  return true;103}104 105bool lldb_private::formatters::CFBitVectorSummaryProvider(106    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {107  ProcessSP process_sp = valobj.GetProcessSP();108  if (!process_sp)109    return false;110 111  ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);112 113  if (!runtime)114    return false;115 116  ObjCLanguageRuntime::ClassDescriptorSP descriptor(117      runtime->GetClassDescriptor(valobj));118 119  if (!descriptor.get() || !descriptor->IsValid())120    return false;121 122  uint32_t ptr_size = process_sp->GetAddressByteSize();123 124  lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);125 126  if (!valobj_addr)127    return false;128 129  uint32_t count = 0;130 131  bool is_type_ok = false; // check to see if this is a CFBag we know about132  if (descriptor->IsCFType()) {133    ConstString type_name(valobj.GetTypeName());134    if (type_name == "__CFMutableBitVector" || type_name == "__CFBitVector" ||135        type_name == "CFMutableBitVectorRef" || type_name == "CFBitVectorRef") {136      if (valobj.IsPointerType())137        is_type_ok = true;138    }139  }140 141  if (!is_type_ok)142    return false;143 144  Status error;145  count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size,146                                                    ptr_size, 0, error);147  if (error.Fail())148    return false;149  uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0);150  addr_t data_ptr = process_sp->ReadPointerFromMemory(151      valobj_addr + 2 * ptr_size + 2 * ptr_size, error);152  if (error.Fail())153    return false;154  // make sure we do not try to read huge amounts of data155  if (num_bytes > 1024)156    num_bytes = 1024;157  WritableDataBufferSP buffer_sp(new DataBufferHeap(num_bytes, 0));158  num_bytes =159      process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error);160  if (error.Fail() || num_bytes == 0)161    return false;162  uint8_t *bytes = buffer_sp->GetBytes();163  for (uint64_t byte_idx = 0; byte_idx < num_bytes - 1; byte_idx++) {164    uint8_t byte = bytes[byte_idx];165    bool bit0 = (byte & 1) == 1;166    bool bit1 = (byte & 2) == 2;167    bool bit2 = (byte & 4) == 4;168    bool bit3 = (byte & 8) == 8;169    bool bit4 = (byte & 16) == 16;170    bool bit5 = (byte & 32) == 32;171    bool bit6 = (byte & 64) == 64;172    bool bit7 = (byte & 128) == 128;173    stream.Printf("%c%c%c%c %c%c%c%c ", (bit7 ? '1' : '0'), (bit6 ? '1' : '0'),174                  (bit5 ? '1' : '0'), (bit4 ? '1' : '0'), (bit3 ? '1' : '0'),175                  (bit2 ? '1' : '0'), (bit1 ? '1' : '0'), (bit0 ? '1' : '0'));176    count -= 8;177  }178  {179    // print the last byte ensuring we do not print spurious bits180    uint8_t byte = bytes[num_bytes - 1];181    bool bit0 = (byte & 1) == 1;182    bool bit1 = (byte & 2) == 2;183    bool bit2 = (byte & 4) == 4;184    bool bit3 = (byte & 8) == 8;185    bool bit4 = (byte & 16) == 16;186    bool bit5 = (byte & 32) == 32;187    bool bit6 = (byte & 64) == 64;188    bool bit7 = (byte & 128) == 128;189    if (count) {190      stream.Printf("%c", bit7 ? '1' : '0');191      count -= 1;192    }193    if (count) {194      stream.Printf("%c", bit6 ? '1' : '0');195      count -= 1;196    }197    if (count) {198      stream.Printf("%c", bit5 ? '1' : '0');199      count -= 1;200    }201    if (count) {202      stream.Printf("%c", bit4 ? '1' : '0');203      count -= 1;204    }205    if (count) {206      stream.Printf("%c", bit3 ? '1' : '0');207      count -= 1;208    }209    if (count) {210      stream.Printf("%c", bit2 ? '1' : '0');211      count -= 1;212    }213    if (count) {214      stream.Printf("%c", bit1 ? '1' : '0');215      count -= 1;216    }217    if (count)218      stream.Printf("%c", bit0 ? '1' : '0');219  }220  return true;221}222 223bool lldb_private::formatters::CFBinaryHeapSummaryProvider(224    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {225  static constexpr llvm::StringLiteral g_TypeHint("CFBinaryHeap");226 227  ProcessSP process_sp = valobj.GetProcessSP();228  if (!process_sp)229    return false;230 231  ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);232 233  if (!runtime)234    return false;235 236  ObjCLanguageRuntime::ClassDescriptorSP descriptor(237      runtime->GetClassDescriptor(valobj));238 239  if (!descriptor.get() || !descriptor->IsValid())240    return false;241 242  uint32_t ptr_size = process_sp->GetAddressByteSize();243 244  lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);245 246  if (!valobj_addr)247    return false;248 249  uint32_t count = 0;250 251  bool is_type_ok =252      false; // check to see if this is a CFBinaryHeap we know about253  if (descriptor->IsCFType()) {254    ConstString type_name(valobj.GetTypeName());255 256    static ConstString g_CFBinaryHeap("__CFBinaryHeap");257    static ConstString g_conststruct__CFBinaryHeap(258        "const struct __CFBinaryHeap");259    static ConstString g_CFBinaryHeapRef("CFBinaryHeapRef");260 261    if (type_name == g_CFBinaryHeap ||262        type_name == g_conststruct__CFBinaryHeap ||263        type_name == g_CFBinaryHeapRef) {264      if (valobj.IsPointerType())265        is_type_ok = true;266    }267  }268 269  if (is_type_ok) {270    lldb::addr_t offset = 2 * ptr_size + valobj_addr;271    Status error;272    count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);273    if (error.Fail())274      return false;275  } else276    return false;277 278  llvm::StringRef prefix, suffix;279  if (Language *language = Language::FindPlugin(options.GetLanguage()))280    std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);281 282  stream << prefix;283  stream.Printf("\"%u item%s\"", count, (count == 1 ? "" : "s"));284  stream << suffix;285  return true;286}287