brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.3 KiB · 9af2223 Raw
294 lines · cpp
1//=== AcceleratorRecordsSaver.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 "AcceleratorRecordsSaver.h"10#include "llvm/DWARFLinker/Utils.h"11#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"12#include "llvm/Support/DJB.h"13 14using namespace llvm;15using namespace dwarf_linker;16using namespace dwarf_linker::parallel;17 18static uint32_t hashFullyQualifiedName(CompileUnit &InputCU, DWARFDie &InputDIE,19                                       int ChildRecurseDepth = 0) {20  const char *Name = nullptr;21  CompileUnit *CU = &InputCU;22  std::optional<DWARFFormValue> RefVal;23 24  if (Error Err = finiteLoop([&]() -> Expected<bool> {25        if (const char *CurrentName = InputDIE.getName(DINameKind::ShortName))26          Name = CurrentName;27 28        if (!(RefVal = InputDIE.find(dwarf::DW_AT_specification)) &&29            !(RefVal = InputDIE.find(dwarf::DW_AT_abstract_origin)))30          return false;31 32        if (!RefVal->isFormClass(DWARFFormValue::FC_Reference))33          return false;34 35        std::optional<UnitEntryPairTy> RefDie = CU->resolveDIEReference(36            *RefVal, ResolveInterCUReferencesMode::Resolve);37        if (!RefDie)38          return false;39 40        if (!RefDie->DieEntry)41          return false;42 43        CU = RefDie->CU;44        InputDIE = RefDie->CU->getDIE(RefDie->DieEntry);45        return true;46      })) {47    consumeError(std::move(Err));48  }49 50  if (!Name && InputDIE.getTag() == dwarf::DW_TAG_namespace)51    Name = "(anonymous namespace)";52 53  DWARFDie ParentDie = InputDIE.getParent();54  if (!ParentDie.isValid() || ParentDie.getTag() == dwarf::DW_TAG_compile_unit)55    return djbHash(Name ? Name : "", djbHash(ChildRecurseDepth ? "" : "::"));56 57  return djbHash(58      (Name ? Name : ""),59      djbHash((Name ? "::" : ""),60              hashFullyQualifiedName(*CU, ParentDie, ++ChildRecurseDepth)));61}62 63void AcceleratorRecordsSaver::save(const DWARFDebugInfoEntry *InputDieEntry,64                                   DIE *OutDIE, AttributesInfo &AttrInfo,65                                   TypeEntry *TypeEntry) {66  if (GlobalData.getOptions().AccelTables.empty())67    return;68 69  DWARFDie InputDIE = InUnit.getDIE(InputDieEntry);70 71  // Look for short name recursively if short name is not known yet.72  if (AttrInfo.Name == nullptr)73    if (const char *ShortName = InputDIE.getShortName())74      AttrInfo.Name = GlobalData.getStringPool().insert(ShortName).first;75 76  switch (InputDieEntry->getTag()) {77  case dwarf::DW_TAG_array_type:78  case dwarf::DW_TAG_class_type:79  case dwarf::DW_TAG_enumeration_type:80  case dwarf::DW_TAG_pointer_type:81  case dwarf::DW_TAG_reference_type:82  case dwarf::DW_TAG_string_type:83  case dwarf::DW_TAG_structure_type:84  case dwarf::DW_TAG_subroutine_type:85  case dwarf::DW_TAG_typedef:86  case dwarf::DW_TAG_union_type:87  case dwarf::DW_TAG_ptr_to_member_type:88  case dwarf::DW_TAG_set_type:89  case dwarf::DW_TAG_subrange_type:90  case dwarf::DW_TAG_base_type:91  case dwarf::DW_TAG_const_type:92  case dwarf::DW_TAG_constant:93  case dwarf::DW_TAG_file_type:94  case dwarf::DW_TAG_namelist:95  case dwarf::DW_TAG_packed_type:96  case dwarf::DW_TAG_volatile_type:97  case dwarf::DW_TAG_restrict_type:98  case dwarf::DW_TAG_atomic_type:99  case dwarf::DW_TAG_interface_type:100  case dwarf::DW_TAG_unspecified_type:101  case dwarf::DW_TAG_shared_type:102  case dwarf::DW_TAG_immutable_type:103  case dwarf::DW_TAG_rvalue_reference_type: {104    if (!AttrInfo.IsDeclaration && AttrInfo.Name != nullptr &&105        !AttrInfo.Name->getKey().empty()) {106      uint32_t Hash = hashFullyQualifiedName(InUnit, InputDIE);107 108      uint64_t RuntimeLang =109          dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class))110              .value_or(0);111 112      bool ObjCClassIsImplementation =113          (RuntimeLang == dwarf::DW_LANG_ObjC ||114           RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&115          dwarf::toUnsigned(116              InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type))117              .value_or(0);118 119      saveTypeRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(), Hash,120                     ObjCClassIsImplementation, TypeEntry);121    }122  } break;123  case dwarf::DW_TAG_namespace: {124    if (AttrInfo.Name == nullptr)125      AttrInfo.Name =126          GlobalData.getStringPool().insert("(anonymous namespace)").first;127 128    saveNamespaceRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(),129                        TypeEntry);130  } break;131  case dwarf::DW_TAG_imported_declaration: {132    if (AttrInfo.Name != nullptr)133      saveNamespaceRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(),134                          TypeEntry);135  } break;136  case dwarf::DW_TAG_compile_unit:137  case dwarf::DW_TAG_lexical_block: {138    // Nothing to do.139  } break;140  default:141    if (TypeEntry)142      // Do not store this kind of accelerator entries for type entries.143      return;144 145    if (AttrInfo.HasLiveAddress || AttrInfo.HasRanges) {146      if (AttrInfo.Name)147        saveNameRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(),148                       InputDieEntry->getTag() ==149                           dwarf::DW_TAG_inlined_subroutine);150 151      // Look for mangled name recursively if mangled name is not known yet.152      if (!AttrInfo.MangledName)153        if (const char *LinkageName = InputDIE.getLinkageName())154          AttrInfo.MangledName =155              GlobalData.getStringPool().insert(LinkageName).first;156 157      if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)158        saveNameRecord(AttrInfo.MangledName, OutDIE, InputDieEntry->getTag(),159                       InputDieEntry->getTag() ==160                           dwarf::DW_TAG_inlined_subroutine);161 162      // Strip template parameters from the short name.163      if (AttrInfo.Name && AttrInfo.MangledName != AttrInfo.Name &&164          (InputDieEntry->getTag() != dwarf::DW_TAG_inlined_subroutine)) {165        if (std::optional<StringRef> Name =166                StripTemplateParameters(AttrInfo.Name->getKey())) {167          StringEntry *NameWithoutTemplateParams =168              GlobalData.getStringPool().insert(*Name).first;169 170          saveNameRecord(NameWithoutTemplateParams, OutDIE,171                         InputDieEntry->getTag(), true);172        }173      }174 175      if (AttrInfo.Name)176        saveObjC(InputDieEntry, OutDIE, AttrInfo);177    }178    break;179  }180}181 182void AcceleratorRecordsSaver::saveObjC(const DWARFDebugInfoEntry *InputDieEntry,183                                       DIE *OutDIE, AttributesInfo &AttrInfo) {184  std::optional<ObjCSelectorNames> Names =185      getObjCNamesIfSelector(AttrInfo.Name->getKey());186  if (!Names)187    return;188 189  StringEntry *Selector =190      GlobalData.getStringPool().insert(Names->Selector).first;191  saveNameRecord(Selector, OutDIE, InputDieEntry->getTag(), true);192  StringEntry *ClassName =193      GlobalData.getStringPool().insert(Names->ClassName).first;194  saveObjCNameRecord(ClassName, OutDIE, InputDieEntry->getTag());195  if (Names->ClassNameNoCategory) {196    StringEntry *ClassNameNoCategory =197        GlobalData.getStringPool().insert(*Names->ClassNameNoCategory).first;198    saveObjCNameRecord(ClassNameNoCategory, OutDIE, InputDieEntry->getTag());199  }200  if (Names->MethodNameNoCategory) {201    StringEntry *MethodNameNoCategory =202        GlobalData.getStringPool().insert(*Names->MethodNameNoCategory).first;203    saveNameRecord(MethodNameNoCategory, OutDIE, InputDieEntry->getTag(), true);204  }205}206 207void AcceleratorRecordsSaver::saveNameRecord(StringEntry *Name, DIE *OutDIE,208                                             dwarf::Tag Tag,209                                             bool AvoidForPubSections) {210  DwarfUnit::AccelInfo Info;211 212  Info.Type = DwarfUnit::AccelType::Name;213  Info.String = Name;214  Info.OutOffset = OutDIE->getOffset();215  Info.Tag = Tag;216  Info.AvoidForPubSections = AvoidForPubSections;217 218  OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);219}220void AcceleratorRecordsSaver::saveNamespaceRecord(StringEntry *Name,221                                                  DIE *OutDIE, dwarf::Tag Tag,222                                                  TypeEntry *TypeEntry) {223  if (OutUnit.isCompileUnit()) {224    assert(TypeEntry == nullptr);225    DwarfUnit::AccelInfo Info;226 227    Info.Type = DwarfUnit::AccelType::Namespace;228    Info.String = Name;229    Info.OutOffset = OutDIE->getOffset();230    Info.Tag = Tag;231 232    OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);233    return;234  }235 236  assert(TypeEntry != nullptr);237  TypeUnit::TypeUnitAccelInfo Info;238  Info.Type = DwarfUnit::AccelType::Namespace;239  Info.String = Name;240  Info.OutOffset = 0xbaddef;241  Info.Tag = Tag;242  Info.OutDIE = OutDIE;243  Info.TypeEntryBodyPtr = TypeEntry->getValue().load();244 245  OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);246}247 248void AcceleratorRecordsSaver::saveObjCNameRecord(StringEntry *Name, DIE *OutDIE,249                                                 dwarf::Tag Tag) {250  DwarfUnit::AccelInfo Info;251 252  Info.Type = DwarfUnit::AccelType::ObjC;253  Info.String = Name;254  Info.OutOffset = OutDIE->getOffset();255  Info.Tag = Tag;256  Info.AvoidForPubSections = true;257 258  OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);259}260 261void AcceleratorRecordsSaver::saveTypeRecord(StringEntry *Name, DIE *OutDIE,262                                             dwarf::Tag Tag,263                                             uint32_t QualifiedNameHash,264                                             bool ObjcClassImplementation,265                                             TypeEntry *TypeEntry) {266  if (OutUnit.isCompileUnit()) {267    assert(TypeEntry == nullptr);268    DwarfUnit::AccelInfo Info;269 270    Info.Type = DwarfUnit::AccelType::Type;271    Info.String = Name;272    Info.OutOffset = OutDIE->getOffset();273    Info.Tag = Tag;274    Info.QualifiedNameHash = QualifiedNameHash;275    Info.ObjcClassImplementation = ObjcClassImplementation;276 277    OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);278    return;279  }280 281  assert(TypeEntry != nullptr);282  TypeUnit::TypeUnitAccelInfo Info;283 284  Info.Type = DwarfUnit::AccelType::Type;285  Info.String = Name;286  Info.OutOffset = 0xbaddef;287  Info.Tag = Tag;288  Info.QualifiedNameHash = QualifiedNameHash;289  Info.ObjcClassImplementation = ObjcClassImplementation;290  Info.OutDIE = OutDIE;291  Info.TypeEntryBodyPtr = TypeEntry->getValue().load();292  OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);293}294