brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · 8dc5f51 Raw
228 lines · cpp
1//===-- GNUstepObjCRuntime.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 "GNUstepObjCRuntime.h"10 11#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"12 13#include "lldb/Core/Module.h"14#include "lldb/Core/PluginManager.h"15#include "lldb/Expression/UtilityFunction.h"16#include "lldb/Target/ExecutionContext.h"17#include "lldb/Target/Process.h"18#include "lldb/Target/Target.h"19#include "lldb/Utility/ArchSpec.h"20#include "lldb/Utility/ConstString.h"21#include "lldb/ValueObject/ValueObject.h"22 23using namespace lldb;24using namespace lldb_private;25 26LLDB_PLUGIN_DEFINE(GNUstepObjCRuntime)27 28char GNUstepObjCRuntime::ID = 0;29 30void GNUstepObjCRuntime::Initialize() {31  PluginManager::RegisterPlugin(32      GetPluginNameStatic(), "GNUstep Objective-C Language Runtime - libobjc2",33      CreateInstance);34}35 36void GNUstepObjCRuntime::Terminate() {37  PluginManager::UnregisterPlugin(CreateInstance);38}39 40static bool CanModuleBeGNUstepObjCLibrary(const ModuleSP &module_sp,41                                          const llvm::Triple &TT) {42  if (!module_sp)43    return false;44  const FileSpec &module_file_spec = module_sp->GetFileSpec();45  if (!module_file_spec)46    return false;47  llvm::StringRef filename = module_file_spec.GetFilename().GetStringRef();48  if (TT.isOSBinFormatELF())49    return filename.starts_with("libobjc.so");50  if (TT.isOSWindows())51    return filename == "objc.dll";52  return false;53}54 55static bool ScanForGNUstepObjCLibraryCandidate(const ModuleList &modules,56                                               const llvm::Triple &TT) {57  std::lock_guard<std::recursive_mutex> guard(modules.GetMutex());58  size_t num_modules = modules.GetSize();59  for (size_t i = 0; i < num_modules; i++) {60    auto mod = modules.GetModuleAtIndex(i);61    if (CanModuleBeGNUstepObjCLibrary(mod, TT))62      return true;63  }64  return false;65}66 67LanguageRuntime *GNUstepObjCRuntime::CreateInstance(Process *process,68                                                    LanguageType language) {69  if (language != eLanguageTypeObjC)70    return nullptr;71  if (!process)72    return nullptr;73 74  Target &target = process->GetTarget();75  const llvm::Triple &TT = target.GetArchitecture().GetTriple();76  if (TT.getVendor() == llvm::Triple::VendorType::Apple)77    return nullptr;78 79  const ModuleList &images = target.GetImages();80  if (!ScanForGNUstepObjCLibraryCandidate(images, TT))81    return nullptr;82 83  if (TT.isOSBinFormatELF()) {84    SymbolContextList eh_pers;85    RegularExpression regex("__gnustep_objc[x]*_personality_v[0-9]+");86    images.FindSymbolsMatchingRegExAndType(regex, eSymbolTypeCode, eh_pers);87    if (eh_pers.GetSize() == 0)88      return nullptr;89  } else if (TT.isOSWindows()) {90    SymbolContextList objc_mandatory;91    images.FindSymbolsWithNameAndType(ConstString("__objc_load"),92                                      eSymbolTypeCode, objc_mandatory);93    if (objc_mandatory.GetSize() == 0)94      return nullptr;95  }96 97  return new GNUstepObjCRuntime(process);98}99 100GNUstepObjCRuntime::~GNUstepObjCRuntime() = default;101 102GNUstepObjCRuntime::GNUstepObjCRuntime(Process *process)103    : ObjCLanguageRuntime(process), m_objc_module_sp(nullptr) {104  ReadObjCLibraryIfNeeded(process->GetTarget().GetImages());105}106 107llvm::Error GNUstepObjCRuntime::GetObjectDescription(Stream &str,108                                                     ValueObject &valobj) {109  return llvm::createStringError(110      "LLDB's GNUStep runtime does not support object description");111}112 113llvm::Error114GNUstepObjCRuntime::GetObjectDescription(Stream &strm, Value &value,115                                         ExecutionContextScope *exe_scope) {116  return llvm::createStringError(117      "LLDB's GNUStep runtime does not support object description");118}119 120bool GNUstepObjCRuntime::CouldHaveDynamicValue(ValueObject &in_value) {121  static constexpr bool check_cxx = false;122  static constexpr bool check_objc = true;123  return in_value.GetCompilerType().IsPossibleDynamicType(nullptr, check_cxx,124                                                          check_objc);125}126 127bool GNUstepObjCRuntime::GetDynamicTypeAndAddress(128    ValueObject &in_value, DynamicValueType use_dynamic,129    TypeAndOrName &class_type_or_name, Address &address,130    Value::ValueType &value_type, llvm::ArrayRef<uint8_t> &local_buffer) {131  return false;132}133 134TypeAndOrName135GNUstepObjCRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,136                                     ValueObject &static_value) {137  CompilerType static_type(static_value.GetCompilerType());138  Flags static_type_flags(static_type.GetTypeInfo());139 140  TypeAndOrName ret(type_and_or_name);141  if (type_and_or_name.HasType()) {142    // The type will always be the type of the dynamic object.  If our parent's143    // type was a pointer, then our type should be a pointer to the type of the144    // dynamic object.  If a reference, then the original type should be145    // okay...146    CompilerType orig_type = type_and_or_name.GetCompilerType();147    CompilerType corrected_type = orig_type;148    if (static_type_flags.AllSet(eTypeIsPointer))149      corrected_type = orig_type.GetPointerType();150    ret.SetCompilerType(corrected_type);151  } else {152    // If we are here we need to adjust our dynamic type name to include the153    // correct & or * symbol154    std::string corrected_name(type_and_or_name.GetName().GetCString());155    if (static_type_flags.AllSet(eTypeIsPointer))156      corrected_name.append(" *");157    // the parent type should be a correctly pointer'ed or referenc'ed type158    ret.SetCompilerType(static_type);159    ret.SetName(corrected_name.c_str());160  }161  return ret;162}163 164BreakpointResolverSP165GNUstepObjCRuntime::CreateExceptionResolver(const BreakpointSP &bkpt,166                                            bool catch_bp, bool throw_bp) {167  BreakpointResolverSP resolver_sp;168 169  if (throw_bp)170    resolver_sp = std::make_shared<BreakpointResolverName>(171        bkpt, "objc_exception_throw", eFunctionNameTypeBase,172        eLanguageTypeUnknown, Breakpoint::Exact, 0,173        /*offset_is_insn_count = */ false, eLazyBoolNo);174 175  return resolver_sp;176}177 178llvm::Expected<std::unique_ptr<UtilityFunction>>179GNUstepObjCRuntime::CreateObjectChecker(std::string name,180                                        ExecutionContext &exe_ctx) {181  // TODO: This function is supposed to check whether an ObjC selector is182  // present for an object. Might be implemented similar as in the Apple V2183  // runtime.184  const char *function_template = R"(185    extern "C" void186    %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {}187  )";188 189  char empty_function_code[2048];190  int len = ::snprintf(empty_function_code, sizeof(empty_function_code),191                       function_template, name.c_str());192 193  assert(len < (int)sizeof(empty_function_code));194  UNUSED_IF_ASSERT_DISABLED(len);195 196  return GetTargetRef().CreateUtilityFunction(empty_function_code, name,197                                              eLanguageTypeC, exe_ctx);198}199 200ThreadPlanSP201GNUstepObjCRuntime::GetStepThroughTrampolinePlan(Thread &thread,202                                                 bool stop_others) {203  // TODO: Implement this properly to avoid stepping into things like PLT stubs204  return nullptr;205}206 207void GNUstepObjCRuntime::UpdateISAToDescriptorMapIfNeeded() {208  // TODO: Support lazily named and dynamically loaded Objective-C classes209}210 211bool GNUstepObjCRuntime::IsModuleObjCLibrary(const ModuleSP &module_sp) {212  const llvm::Triple &TT = GetTargetRef().GetArchitecture().GetTriple();213  return CanModuleBeGNUstepObjCLibrary(module_sp, TT);214}215 216bool GNUstepObjCRuntime::ReadObjCLibrary(const ModuleSP &module_sp) {217  assert(m_objc_module_sp == nullptr && "Check HasReadObjCLibrary() first");218  m_objc_module_sp = module_sp;219 220  // Right now we don't use this, but we might want to check for debugger221  // runtime support symbols like 'gdb_object_getClass' in the future.222  return true;223}224 225void GNUstepObjCRuntime::ModulesDidLoad(const ModuleList &module_list) {226  ReadObjCLibraryIfNeeded(module_list);227}228