brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.7 KiB · 9bcd2b8 Raw
470 lines · cpp
1//=== OutputSections.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 "OutputSections.h"10#include "DWARFLinkerCompileUnit.h"11#include "DWARFLinkerTypeUnit.h"12 13using namespace llvm;14using namespace dwarf_linker;15using namespace dwarf_linker::parallel;16 17DebugDieRefPatch::DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,18                                   CompileUnit *RefCU, uint32_t RefIdx)19    : SectionPatch({PatchOffset}),20      RefCU(RefCU, (SrcCU != nullptr) &&21                       (SrcCU->getUniqueID() == RefCU->getUniqueID())),22      RefDieIdxOrClonedOffset(RefIdx) {}23 24DebugULEB128DieRefPatch::DebugULEB128DieRefPatch(uint64_t PatchOffset,25                                                 CompileUnit *SrcCU,26                                                 CompileUnit *RefCU,27                                                 uint32_t RefIdx)28    : SectionPatch({PatchOffset}),29      RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),30      RefDieIdxOrClonedOffset(RefIdx) {}31 32DebugDieTypeRefPatch::DebugDieTypeRefPatch(uint64_t PatchOffset,33                                           TypeEntry *RefTypeName)34    : SectionPatch({PatchOffset}), RefTypeName(RefTypeName) {}35 36DebugType2TypeDieRefPatch::DebugType2TypeDieRefPatch(uint64_t PatchOffset,37                                                     DIE *Die,38                                                     TypeEntry *TypeName,39                                                     TypeEntry *RefTypeName)40    : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),41      RefTypeName(RefTypeName) {}42 43DebugTypeStrPatch::DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die,44                                     TypeEntry *TypeName, StringEntry *String)45    : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),46      String(String) {}47 48DebugTypeLineStrPatch::DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die,49                                             TypeEntry *TypeName,50                                             StringEntry *String)51    : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),52      String(String) {}53 54DebugTypeDeclFilePatch::DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName,55                                               StringEntry *Directory,56                                               StringEntry *FilePath)57    : Die(Die), TypeName(TypeName), Directory(Directory), FilePath(FilePath) {}58 59void SectionDescriptor::clearAllSectionData() {60  StartOffset = 0;61  clearSectionContent();62  ListDebugStrPatch.erase();63  ListDebugLineStrPatch.erase();64  ListDebugRangePatch.erase();65  ListDebugLocPatch.erase();66  ListDebugDieRefPatch.erase();67  ListDebugULEB128DieRefPatch.erase();68  ListDebugOffsetPatch.erase();69  ListDebugType2TypeDieRefPatch.erase();70  ListDebugTypeDeclFilePatch.erase();71  ListDebugTypeLineStrPatch.erase();72  ListDebugTypeStrPatch.erase();73}74 75void SectionDescriptor::clearSectionContent() { Contents = OutSectionDataTy(); }76 77void SectionDescriptor::setSizesForSectionCreatedByAsmPrinter() {78  if (Contents.empty())79    return;80 81  MemoryBufferRef Mem(Contents, "obj");82  Expected<std::unique_ptr<object::ObjectFile>> Obj =83      object::ObjectFile::createObjectFile(Mem);84  if (!Obj) {85    consumeError(Obj.takeError());86    Contents.clear();87    return;88  }89 90  for (const object::SectionRef &Sect : (*Obj).get()->sections()) {91    Expected<StringRef> SectNameOrErr = Sect.getName();92    if (!SectNameOrErr) {93      consumeError(SectNameOrErr.takeError());94      continue;95    }96    if (std::optional<DebugSectionKind> SectKind =97            parseDebugTableName(*SectNameOrErr)) {98      if (*SectKind == SectionKind) {99        Expected<StringRef> Data = Sect.getContents();100        if (!Data) {101          consumeError(SectNameOrErr.takeError());102          Contents.clear();103          return;104        }105 106        SectionOffsetInsideAsmPrinterOutputStart =107            Data->data() - Contents.data();108        SectionOffsetInsideAsmPrinterOutputEnd =109            SectionOffsetInsideAsmPrinterOutputStart + Data->size();110      }111    }112  }113}114 115void SectionDescriptor::emitString(dwarf::Form StringForm,116                                   const char *StringVal) {117  assert(StringVal != nullptr);118 119  switch (StringForm) {120  case dwarf::DW_FORM_string: {121    emitInplaceString(StringVal);122  } break;123  case dwarf::DW_FORM_strp: {124    notePatch(DebugStrPatch{125        {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});126    emitStringPlaceholder();127  } break;128  case dwarf::DW_FORM_line_strp: {129    notePatch(DebugLineStrPatch{130        {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});131    emitStringPlaceholder();132  } break;133  default:134    llvm_unreachable("Unsupported string form");135    break;136  };137}138 139void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) {140  switch (Size) {141  case 1: {142    OS.write(static_cast<uint8_t>(Val));143  } break;144  case 2: {145    uint16_t ShortVal = static_cast<uint16_t>(Val);146    if (Endianess != llvm::endianness::native)147      sys::swapByteOrder(ShortVal);148    OS.write(reinterpret_cast<const char *>(&ShortVal), Size);149  } break;150  case 4: {151    uint32_t ShortVal = static_cast<uint32_t>(Val);152    if (Endianess != llvm::endianness::native)153      sys::swapByteOrder(ShortVal);154    OS.write(reinterpret_cast<const char *>(&ShortVal), Size);155  } break;156  case 8: {157    if (Endianess != llvm::endianness::native)158      sys::swapByteOrder(Val);159    OS.write(reinterpret_cast<const char *>(&Val), Size);160  } break;161  default:162    llvm_unreachable("Unsupported integer type size");163  }164}165 166void SectionDescriptor::emitBinaryData(llvm::StringRef Data) {167  OS.write(Data.data(), Data.size());168}169 170void SectionDescriptor::apply(uint64_t PatchOffset, dwarf::Form AttrForm,171                              uint64_t Val) {172  switch (AttrForm) {173  case dwarf::DW_FORM_strp:174  case dwarf::DW_FORM_line_strp: {175    applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());176  } break;177 178  case dwarf::DW_FORM_ref_addr: {179    applyIntVal(PatchOffset, Val, Format.getRefAddrByteSize());180  } break;181  case dwarf::DW_FORM_ref1: {182    applyIntVal(PatchOffset, Val, 1);183  } break;184  case dwarf::DW_FORM_ref2: {185    applyIntVal(PatchOffset, Val, 2);186  } break;187  case dwarf::DW_FORM_ref4: {188    applyIntVal(PatchOffset, Val, 4);189  } break;190  case dwarf::DW_FORM_ref8: {191    applyIntVal(PatchOffset, Val, 8);192  } break;193 194  case dwarf::DW_FORM_data1: {195    applyIntVal(PatchOffset, Val, 1);196  } break;197  case dwarf::DW_FORM_data2: {198    applyIntVal(PatchOffset, Val, 2);199  } break;200  case dwarf::DW_FORM_data4: {201    applyIntVal(PatchOffset, Val, 4);202  } break;203  case dwarf::DW_FORM_data8: {204    applyIntVal(PatchOffset, Val, 8);205  } break;206  case dwarf::DW_FORM_udata: {207    applyULEB128(PatchOffset, Val);208  } break;209  case dwarf::DW_FORM_sdata: {210    applySLEB128(PatchOffset, Val);211  } break;212  case dwarf::DW_FORM_sec_offset: {213    applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());214  } break;215  case dwarf::DW_FORM_flag: {216    applyIntVal(PatchOffset, Val, 1);217  } break;218 219  default:220    llvm_unreachable("Unsupported attribute form");221    break;222  }223}224 225uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset, unsigned Size) {226  assert(PatchOffset < getContents().size());227  switch (Size) {228  case 1: {229    return *reinterpret_cast<const uint8_t *>(230        (getContents().data() + PatchOffset));231  }232  case 2: {233    return support::endian::read16(getContents().data() + PatchOffset,234                                   Endianess);235  }236  case 4: {237    return support::endian::read32(getContents().data() + PatchOffset,238                                   Endianess);239  }240  case 8: {241    return support::endian::read64(getContents().data() + PatchOffset,242                                   Endianess);243  }244  }245  llvm_unreachable("Unsupported integer type size");246  return 0;247}248 249void SectionDescriptor::applyIntVal(uint64_t PatchOffset, uint64_t Val,250                                    unsigned Size) {251  assert(PatchOffset < getContents().size());252 253  switch (Size) {254  case 1: {255    support::endian::write(256        const_cast<char *>(getContents().data() + PatchOffset),257        static_cast<uint8_t>(Val), Endianess);258  } break;259  case 2: {260    support::endian::write(261        const_cast<char *>(getContents().data() + PatchOffset),262        static_cast<uint16_t>(Val), Endianess);263  } break;264  case 4: {265    support::endian::write(266        const_cast<char *>(getContents().data() + PatchOffset),267        static_cast<uint32_t>(Val), Endianess);268  } break;269  case 8: {270    support::endian::write(271        const_cast<char *>(getContents().data() + PatchOffset),272        static_cast<uint64_t>(Val), Endianess);273  } break;274  default:275    llvm_unreachable("Unsupported integer type size");276  }277}278 279void SectionDescriptor::applyULEB128(uint64_t PatchOffset, uint64_t Val) {280  assert(PatchOffset < getContents().size());281 282  uint8_t ULEB[16];283  uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;284  uint8_t RealSize = encodeULEB128(Val, ULEB, DestSize);285 286  memcpy(const_cast<char *>(getContents().data() + PatchOffset), ULEB,287         RealSize);288}289 290/// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.291void SectionDescriptor::applySLEB128(uint64_t PatchOffset, uint64_t Val) {292  assert(PatchOffset < getContents().size());293 294  uint8_t SLEB[16];295  uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;296  uint8_t RealSize = encodeSLEB128(Val, SLEB, DestSize);297 298  memcpy(const_cast<char *>(getContents().data() + PatchOffset), SLEB,299         RealSize);300}301 302void OutputSections::applyPatches(303    SectionDescriptor &Section,304    StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,305    StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,306    TypeUnit *TypeUnitPtr) {307  Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {308    DwarfStringPoolEntryWithExtString *Entry =309        DebugStrStrings.getExistingEntry(Patch.String);310    assert(Entry != nullptr);311 312    Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);313  });314  Section.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {315    assert(TypeUnitPtr != nullptr);316    TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();317    assert(TypeEntry &&318           formatv("No data for type {0}", Patch.TypeName->getKey())319               .str()320               .c_str());321 322    if (&TypeEntry->getFinalDie() != Patch.Die)323      return;324 325    DwarfStringPoolEntryWithExtString *Entry =326        DebugStrStrings.getExistingEntry(Patch.String);327    assert(Entry != nullptr);328 329    Patch.PatchOffset +=330        Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());331 332    Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);333  });334 335  Section.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {336    DwarfStringPoolEntryWithExtString *Entry =337        DebugLineStrStrings.getExistingEntry(Patch.String);338    assert(Entry != nullptr);339 340    Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);341  });342  Section.ListDebugTypeLineStrPatch.forEach([&](DebugTypeLineStrPatch &Patch) {343    assert(TypeUnitPtr != nullptr);344    TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();345    assert(TypeEntry &&346           formatv("No data for type {0}", Patch.TypeName->getKey())347               .str()348               .c_str());349 350    if (&TypeEntry->getFinalDie() != Patch.Die)351      return;352 353    DwarfStringPoolEntryWithExtString *Entry =354        DebugLineStrStrings.getExistingEntry(Patch.String);355    assert(Entry != nullptr);356 357    Patch.PatchOffset +=358        Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());359 360    Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);361  });362 363  std::optional<SectionDescriptor *> RangeSection;364  if (Format.Version >= 5)365    RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRngLists);366  else367    RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRange);368 369  if (RangeSection) {370    Section.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {371      uint64_t FinalValue =372          Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());373      FinalValue += (*RangeSection)->StartOffset;374 375      Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);376    });377  }378 379  std::optional<SectionDescriptor *> LocationSection;380  if (Format.Version >= 5)381    LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLocLists);382  else383    LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLoc);384 385  if (LocationSection) {386    Section.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {387      uint64_t FinalValue =388          Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());389      FinalValue += (*LocationSection)->StartOffset;390 391      Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);392    });393  }394 395  Section.ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {396    uint64_t FinalOffset = Patch.RefDieIdxOrClonedOffset;397    dwarf::Form FinalForm = dwarf::DW_FORM_ref4;398 399    // Check whether it is local or inter-CU reference.400    if (!Patch.RefCU.getInt()) {401      SectionDescriptor &ReferencedSectionDescriptor =402          Patch.RefCU.getPointer()->getSectionDescriptor(403              DebugSectionKind::DebugInfo);404 405      FinalForm = dwarf::DW_FORM_ref_addr;406      FinalOffset += ReferencedSectionDescriptor.StartOffset;407    }408 409    Section.apply(Patch.PatchOffset, FinalForm, FinalOffset);410  });411 412  Section.ListDebugULEB128DieRefPatch.forEach(413      [&](DebugULEB128DieRefPatch &Patch) {414        assert(Patch.RefCU.getInt());415        Section.apply(Patch.PatchOffset, dwarf::DW_FORM_udata,416                      Patch.RefDieIdxOrClonedOffset);417      });418 419  Section.ListDebugDieTypeRefPatch.forEach([&](DebugDieTypeRefPatch &Patch) {420    assert(TypeUnitPtr != nullptr);421    assert(Patch.RefTypeName != nullptr);422 423    TypeEntryBody *TypeEntry = Patch.RefTypeName->getValue().load();424    assert(TypeEntry &&425           formatv("No data for type {0}", Patch.RefTypeName->getKey())426               .str()427               .c_str());428 429    Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref_addr,430                  TypeEntry->getFinalDie().getOffset());431  });432 433  Section.ListDebugType2TypeDieRefPatch.forEach(434      [&](DebugType2TypeDieRefPatch &Patch) {435        assert(TypeUnitPtr != nullptr);436        TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();437        assert(TypeEntry &&438               formatv("No data for type {0}", Patch.TypeName->getKey())439                   .str()440                   .c_str());441 442        if (&TypeEntry->getFinalDie() != Patch.Die)443          return;444 445        Patch.PatchOffset += Patch.Die->getOffset() +446                             getULEB128Size(Patch.Die->getAbbrevNumber());447 448        assert(Patch.RefTypeName != nullptr);449        TypeEntryBody *RefTypeEntry = Patch.RefTypeName->getValue().load();450        assert(TypeEntry &&451               formatv("No data for type {0}", Patch.RefTypeName->getKey())452                   .str()453                   .c_str());454 455        Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref4,456                      RefTypeEntry->getFinalDie().getOffset());457      });458 459  Section.ListDebugOffsetPatch.forEach([&](DebugOffsetPatch &Patch) {460    uint64_t FinalValue = Patch.SectionPtr.getPointer()->StartOffset;461 462    // Check whether we need to read value from the original location.463    if (Patch.SectionPtr.getInt())464      FinalValue +=465          Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());466 467    Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);468  });469}470