forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			153 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- DWARFLinkerCompileUnit.cpp -----------------------------------------===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
 | 
						|
#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
 | 
						|
/// Check if the DIE at \p Idx is in the scope of a function.
 | 
						|
static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
 | 
						|
  while (Idx) {
 | 
						|
    if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
 | 
						|
      return true;
 | 
						|
    Idx = U.getInfo(Idx).ParentIdx;
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
uint16_t CompileUnit::getLanguage() {
 | 
						|
  if (!Language) {
 | 
						|
    DWARFDie CU = getOrigUnit().getUnitDIE();
 | 
						|
    Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
 | 
						|
  }
 | 
						|
  return Language;
 | 
						|
}
 | 
						|
 | 
						|
StringRef CompileUnit::getSysRoot() {
 | 
						|
  if (SysRoot.empty()) {
 | 
						|
    DWARFDie CU = getOrigUnit().getUnitDIE();
 | 
						|
    SysRoot = dwarf::toStringRef(CU.find(dwarf::DW_AT_LLVM_sysroot)).str();
 | 
						|
  }
 | 
						|
  return SysRoot;
 | 
						|
}
 | 
						|
 
 | 
						|
void CompileUnit::markEverythingAsKept() {
 | 
						|
  unsigned Idx = 0;
 | 
						|
 | 
						|
  setHasInterestingContent();
 | 
						|
 | 
						|
  for (auto &I : Info) {
 | 
						|
    // Mark everything that wasn't explicit marked for pruning.
 | 
						|
    I.Keep = !I.Prune;
 | 
						|
    auto DIE = OrigUnit.getDIEAtIndex(Idx++);
 | 
						|
 | 
						|
    // Try to guess which DIEs must go to the accelerator tables. We do that
 | 
						|
    // just for variables, because functions will be handled depending on
 | 
						|
    // whether they carry a DW_AT_low_pc attribute or not.
 | 
						|
    if (DIE.getTag() != dwarf::DW_TAG_variable &&
 | 
						|
        DIE.getTag() != dwarf::DW_TAG_constant)
 | 
						|
      continue;
 | 
						|
 | 
						|
    Optional<DWARFFormValue> Value;
 | 
						|
    if (!(Value = DIE.find(dwarf::DW_AT_location))) {
 | 
						|
      if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
 | 
						|
          !inFunctionScope(*this, I.ParentIdx))
 | 
						|
        I.InDebugMap = true;
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    if (auto Block = Value->getAsBlock()) {
 | 
						|
      if (Block->size() > OrigUnit.getAddressByteSize() &&
 | 
						|
          (*Block)[0] == dwarf::DW_OP_addr)
 | 
						|
        I.InDebugMap = true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
uint64_t CompileUnit::computeNextUnitOffset() {
 | 
						|
  NextUnitOffset = StartOffset;
 | 
						|
  if (NewUnit) {
 | 
						|
    NextUnitOffset += 11 /* Header size */;
 | 
						|
    NextUnitOffset += NewUnit->getUnitDie().getSize();
 | 
						|
  }
 | 
						|
  return NextUnitOffset;
 | 
						|
}
 | 
						|
 | 
						|
/// Keep track of a forward cross-cu reference from this unit
 | 
						|
/// to \p Die that lives in \p RefUnit.
 | 
						|
void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
 | 
						|
                                       DeclContext *Ctxt, PatchLocation Attr) {
 | 
						|
  ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
 | 
						|
}
 | 
						|
 | 
						|
void CompileUnit::fixupForwardReferences() {
 | 
						|
  for (const auto &Ref : ForwardDIEReferences) {
 | 
						|
    DIE *RefDie;
 | 
						|
    const CompileUnit *RefUnit;
 | 
						|
    PatchLocation Attr;
 | 
						|
    DeclContext *Ctxt;
 | 
						|
    std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
 | 
						|
    if (Ctxt && Ctxt->getCanonicalDIEOffset())
 | 
						|
      Attr.set(Ctxt->getCanonicalDIEOffset());
 | 
						|
    else
 | 
						|
      Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
 | 
						|
  Labels.insert({LabelLowPc, PcOffset});
 | 
						|
}
 | 
						|
 | 
						|
void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
 | 
						|
                                   int64_t PcOffset) {
 | 
						|
  //  Don't add empty ranges to the interval map.  They are a problem because
 | 
						|
  //  the interval map expects half open intervals. This is safe because they
 | 
						|
  //  are empty anyway.
 | 
						|
  if (FuncHighPc != FuncLowPc)
 | 
						|
    Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
 | 
						|
  this->LowPc = std::min(LowPc, FuncLowPc + PcOffset);
 | 
						|
  this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
 | 
						|
}
 | 
						|
 | 
						|
void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
 | 
						|
  if (Die.getTag() != dwarf::DW_TAG_compile_unit)
 | 
						|
    RangeAttributes.push_back(Attr);
 | 
						|
  else
 | 
						|
    UnitRangeAttribute = Attr;
 | 
						|
}
 | 
						|
 | 
						|
void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
 | 
						|
  LocationAttributes.emplace_back(Attr, PcOffset);
 | 
						|
}
 | 
						|
 | 
						|
void CompileUnit::addNamespaceAccelerator(const DIE *Die,
 | 
						|
                                          DwarfStringPoolEntryRef Name) {
 | 
						|
  Namespaces.emplace_back(Name, Die);
 | 
						|
}
 | 
						|
 | 
						|
void CompileUnit::addObjCAccelerator(const DIE *Die,
 | 
						|
                                     DwarfStringPoolEntryRef Name,
 | 
						|
                                     bool SkipPubSection) {
 | 
						|
  ObjC.emplace_back(Name, Die, SkipPubSection);
 | 
						|
}
 | 
						|
 | 
						|
void CompileUnit::addNameAccelerator(const DIE *Die,
 | 
						|
                                     DwarfStringPoolEntryRef Name,
 | 
						|
                                     bool SkipPubSection) {
 | 
						|
  Pubnames.emplace_back(Name, Die, SkipPubSection);
 | 
						|
}
 | 
						|
 | 
						|
void CompileUnit::addTypeAccelerator(const DIE *Die,
 | 
						|
                                     DwarfStringPoolEntryRef Name,
 | 
						|
                                     bool ObjcClassImplementation,
 | 
						|
                                     uint32_t QualifiedNameHash) {
 | 
						|
  Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace llvm
 |