コード例 #1
0
ファイル: Symbols.cpp プロジェクト: genewitch/lld
static typename ELFT::uint getSymVA(const SymbolBody &Body,
                                    typename ELFT::uint &Addend) {
  typedef typename ELFT::uint uintX_t;

  switch (Body.kind()) {
  case SymbolBody::DefinedSyntheticKind: {
    auto &D = cast<DefinedSynthetic<ELFT>>(Body);
    const OutputSectionBase<ELFT> *Sec = D.Section;
    if (!Sec)
      return D.Value;
    if (D.Value == DefinedSynthetic<ELFT>::SectionEnd)
      return Sec->getVA() + Sec->getSize();
    return Sec->getVA() + D.Value;
  }
  case SymbolBody::DefinedRegularKind: {
    auto &D = cast<DefinedRegular<ELFT>>(Body);
    InputSectionBase<ELFT> *SC = D.Section;

    // According to the ELF spec reference to a local symbol from outside
    // the group are not allowed. Unfortunately .eh_frame breaks that rule
    // and must be treated specially. For now we just replace the symbol with
    // 0.
    if (SC == &InputSection<ELFT>::Discarded)
      return 0;

    // This is an absolute symbol.
    if (!SC)
      return D.Value;

    uintX_t Offset = D.Value;
    if (D.isSection()) {
      Offset += Addend;
      Addend = 0;
    }
    uintX_t VA = SC->OutSec->getVA() + SC->getOffset(Offset);
    if (D.isTls())
      return VA - Out<ELFT>::TlsPhdr->p_vaddr;
    return VA;
  }
  case SymbolBody::DefinedCommonKind:
    return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(Body).OffsetInBss;
  case SymbolBody::SharedKind: {
    auto &SS = cast<SharedSymbol<ELFT>>(Body);
    if (!SS.NeedsCopyOrPltAddr)
      return 0;
    if (SS.isFunc())
      return Body.getPltVA<ELFT>();
    return Out<ELFT>::Bss->getVA() + SS.OffsetInBss;
  }
  case SymbolBody::UndefinedKind:
    return 0;
  case SymbolBody::LazyArchiveKind:
  case SymbolBody::LazyObjectKind:
    assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer");
    return 0;
  case SymbolBody::DefinedBitcodeKind:
    llvm_unreachable("should have been replaced");
  }
  llvm_unreachable("invalid symbol kind");
}
コード例 #2
0
void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
  InputSectionBase *Sec = getRelocatedSection();

  for (const RelTy &Rel : Rels) {
    RelType Type = Rel.getType(Config->IsMips64EL);
    Symbol &Sym = getFile<ELFT>()->getRelocTargetSym(Rel);

    auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf);
    Buf += sizeof(RelTy);

    if (Config->IsRela)
      P->r_addend = getAddend<ELFT>(Rel);

    // Output section VA is zero for -r, so r_offset is an offset within the
    // section, but for --emit-relocs it is an virtual address.
    P->r_offset = Sec->getOutputSection()->Addr + Sec->getOffset(Rel.r_offset);
    P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Sym), Type,
                        Config->IsMips64EL);

    if (Sym.Type == STT_SECTION) {
      // We combine multiple section symbols into only one per
      // section. This means we have to update the addend. That is
      // trivial for Elf_Rela, but for Elf_Rel we have to write to the
      // section data. We do that by adding to the Relocation vector.

      // .eh_frame is horribly special and can reference discarded sections. To
      // avoid having to parse and recreate .eh_frame, we just replace any
      // relocation in it pointing to discarded sections with R_*_NONE, which
      // hopefully creates a frame that is ignored at runtime.
      auto *D = dyn_cast<Defined>(&Sym);
      if (!D) {
        error("STT_SECTION symbol should be defined");
        continue;
      }
      SectionBase *Section = D->Section;
      if (Section == &InputSection::Discarded) {
        P->setSymbolAndType(0, 0, false);
        continue;
      }

      if (Config->IsRela) {
        P->r_addend =
            Sym.getVA(getAddend<ELFT>(Rel)) - Section->getOutputSection()->Addr;
      } else if (Config->Relocatable) {
        const uint8_t *BufLoc = Sec->Data.begin() + Rel.r_offset;
        Sec->Relocations.push_back({R_ABS, Type, Rel.r_offset,
                                    Target->getImplicitAddend(BufLoc, Type),
                                    &Sym});
      }
    }

  }
}
コード例 #3
0
ファイル: InputSection.cpp プロジェクト: llvm-beanz/lld
void InputSection<ELFT>::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
  InputSectionBase<ELFT> *RelocatedSection = getRelocatedSection();

  for (const RelTy &Rel : Rels) {
    uint32_t Type = Rel.getType(Config->Mips64EL);
    SymbolBody &Body = this->File->getRelocTargetSym(Rel);

    RelTy *P = reinterpret_cast<RelTy *>(Buf);
    Buf += sizeof(RelTy);

    P->r_offset = RelocatedSection->getOffset(Rel.r_offset);
    P->setSymbolAndType(Body.DynsymIndex, Type, Config->Mips64EL);
  }
}
コード例 #4
0
ファイル: Writer.cpp プロジェクト: 8l/lld
void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &S,
                              const Elf_Shdr &RelSec) {
  ELFFile<ELFT> &EObj = S.getFile()->getObj();
  if (RelSec.sh_type == SHT_RELA)
    scanRelocs(S, EObj.relas(&RelSec));
  else
    scanRelocs(S, EObj.rels(&RelSec));
}
コード例 #5
0
template <class ELFT> void OutputSection::finalize() {
  if (Type == SHT_NOBITS)
    for (BaseCommand *Base : SectionCommands)
      if (isa<ByteCommand>(Base))
        Type = SHT_PROGBITS;

  std::vector<InputSection *> V = getInputSections(this);
  InputSection *First = V.empty() ? nullptr : V[0];

  if (Flags & SHF_LINK_ORDER) {
    // We must preserve the link order dependency of sections with the
    // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We
    // need to translate the InputSection sh_link to the OutputSection sh_link,
    // all InputSections in the OutputSection have the same dependency.
    if (auto *D = First->getLinkOrderDep())
      Link = D->getParent()->SectionIndex;
  }

  if (Type == SHT_GROUP) {
    finalizeShtGroup<ELFT>(this, First);
    return;
  }

  if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))
    return;

  if (isa<SyntheticSection>(First))
    return;

  Link = In.SymTab->getParent()->SectionIndex;
  // sh_info for SHT_REL[A] sections should contain the section header index of
  // the section to which the relocation applies.
  InputSectionBase *S = First->getRelocatedSection();
  Info = S->getOutputSection()->SectionIndex;
  Flags |= SHF_INFO_LINK;
}
コード例 #6
0
ファイル: Writer.cpp プロジェクト: 8l/lld
void Writer<ELFT>::scanRelocs(
    InputSectionBase<ELFT> &C,
    iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) {
  typedef Elf_Rel_Impl<ELFT, isRela> RelType;
  const ObjectFile<ELFT> &File = *C.getFile();
  for (const RelType &RI : Rels) {
    uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
    SymbolBody *Body = File.getSymbolBody(SymIndex);
    uint32_t Type = RI.getType(Config->Mips64EL);

    if (Target->isTlsLocalDynamicReloc(Type)) {
      if (Target->isTlsOptimized(Type, nullptr))
        continue;
      if (Out<ELFT>::LocalModuleTlsIndexOffset == uint32_t(-1)) {
        Out<ELFT>::LocalModuleTlsIndexOffset =
            Out<ELFT>::Got->addLocalModuleTlsIndex();
        Out<ELFT>::RelaDyn->addReloc({&C, &RI});
      }
      continue;
    }

    // Set "used" bit for --as-needed.
    if (Body && Body->isUndefined() && !Body->isWeak())
      if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl()))
        S->File->IsUsed = true;

    if (Body)
      Body = Body->repl();

    if (Body && Body->isTLS() && Target->isTlsGlobalDynamicReloc(Type)) {
      if (Target->isTlsOptimized(Type, Body))
        continue;
      if (Body->isInGot())
        continue;
      Out<ELFT>::Got->addDynTlsEntry(Body);
      Out<ELFT>::RelaDyn->addReloc({&C, &RI});
      Out<ELFT>::RelaDyn->addReloc({nullptr, nullptr});
      Body->setUsedInDynamicReloc();
      continue;
    }

    if (Body && Body->isTLS() && !Target->isTlsDynReloc(Type))
      continue;

    bool NeedsGot = false;
    bool NeedsPlt = false;
    if (Body) {
      if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) {
        if (E->needsCopy())
          continue;
        if (Target->relocNeedsCopy(Type, *Body))
          E->OffsetInBSS = 0;
      }
      NeedsPlt = Target->relocNeedsPlt(Type, *Body);
      if (NeedsPlt) {
        if (Body->isInPlt())
          continue;
        Out<ELFT>::Plt->addEntry(Body);
      }
      NeedsGot = Target->relocNeedsGot(Type, *Body);
      if (NeedsGot) {
        if (NeedsPlt && Target->supportsLazyRelocations()) {
          Out<ELFT>::GotPlt->addEntry(Body);
        } else {
          if (Body->isInGot())
            continue;
          Out<ELFT>::Got->addEntry(Body);
        }
      }
    }

    if (Config->EMachine == EM_MIPS && NeedsGot) {
      // MIPS ABI has special rules to process GOT entries
      // and doesn't require relocation entries for them.
      // See "Global Offset Table" in Chapter 5 in the following document
      // for detailed description:
      // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
      Body->setUsedInDynamicReloc();
      continue;
    }
    bool CBP = canBePreempted(Body, NeedsGot);
    if (!CBP && (!Config->Shared || Target->isRelRelative(Type)))
      continue;
    if (CBP)
      Body->setUsedInDynamicReloc();
    if (NeedsPlt && Target->supportsLazyRelocations())
      Out<ELFT>::RelaPlt->addReloc({&C, &RI});
    else
      Out<ELFT>::RelaDyn->addReloc({&C, &RI});
  }
}
コード例 #7
0
ファイル: Symbols.cpp プロジェクト: arichardson/lld
std::string lld::verboseToString(Symbol *B, uint64_t SymOffset) {
  std::string Msg;

  if (B->isLocal())
    Msg += "local ";
  if (B->isWeak())
      Msg += "weak ";
  if (B->isShared())
    Msg += "shared ";
  // else if (B->isDefined())
  //  Msg += "defined ";
  if (B->Type == STT_COMMON)
    Msg += "common ";
  else if (B->Type == STT_TLS)
    Msg += "TLS ";
  if (B->isSection())
    Msg += "section ";
  else if (B->isTls())
    Msg += "tls ";
  else if (B->isFunc())
    Msg += "function ";
  else if (B->isGnuIFunc())
    Msg += "gnu ifunc ";
  else if (B->isObject())
    Msg += "object ";
  else if (B->isFile())
    Msg += "file ";
  else if (B->isUndefined())
    Msg += "<undefined> ";
  else
    Msg += "<unknown kind> ";

  if (B->isInGot())
    Msg += "(in GOT) ";
  if (B->isInPlt())
    Msg += "(in PLT) ";

  Defined* DR = dyn_cast<Defined>(B);
  InputSectionBase* IS = nullptr;
  if (DR && DR->Section) {
    SymOffset = DR->isSection() ? SymOffset : DR->Section->getOffset(DR->Value);
    IS = dyn_cast<InputSectionBase>(DR->Section);
  }
  std::string Name = toString(*B);
  if (Name.empty()) {
    if (DR && DR->Section) {
      if (IS) {
        Name = IS->getLocation<ELFT>(SymOffset);
      } else {
        Name = (DR->Section->Name + "+0x" + utohexstr(SymOffset)).str();
      }
    } else if (OutputSection* OS = B->getOutputSection()) {
      Name = (OS->Name + "+(unknown offset)").str();
    }
  }
  if (Name.empty()) {
    Name = "<unknown symbol>";
  }
  Msg += Name;
  if (!B->isUndefined()) {
    std::string Src = IS ? IS->getSrcMsg(*B, SymOffset) : toString(B->File);
    if (IS)
      Src += " (" + IS->getObjMsg(SymOffset) + ")";
    Msg += "\n>>> defined in " + Src;
  }
  return Msg;
}
コード例 #8
0
ファイル: Symbols.cpp プロジェクト: mulichao/freebsd
static typename ELFT::uint getSymVA(const SymbolBody &Body,
                                    typename ELFT::uint &Addend) {
  typedef typename ELFT::uint uintX_t;

  switch (Body.kind()) {
  case SymbolBody::DefinedSyntheticKind: {
    auto &D = cast<DefinedSynthetic>(Body);
    const OutputSectionBase *Sec = D.Section;
    if (!Sec)
      return D.Value;
    if (D.Value == uintX_t(-1))
      return Sec->Addr + Sec->Size;
    return Sec->Addr + D.Value;
  }
  case SymbolBody::DefinedRegularKind: {
    auto &D = cast<DefinedRegular<ELFT>>(Body);
    InputSectionBase<ELFT> *IS = D.Section;

    // According to the ELF spec reference to a local symbol from outside
    // the group are not allowed. Unfortunately .eh_frame breaks that rule
    // and must be treated specially. For now we just replace the symbol with
    // 0.
    if (IS == &InputSection<ELFT>::Discarded)
      return 0;

    // This is an absolute symbol.
    if (!IS)
      return D.Value;

    uintX_t Offset = D.Value;
    if (D.isSection()) {
      Offset += Addend;
      Addend = 0;
    }
    uintX_t VA = (IS->OutSec ? IS->OutSec->Addr : 0) + IS->getOffset(Offset);
    if (D.isTls() && !Config->Relocatable) {
      if (!Out<ELFT>::TlsPhdr)
        fatal(toString(D.File) +
              " has a STT_TLS symbol but doesn't have a PT_TLS section");
      return VA - Out<ELFT>::TlsPhdr->p_vaddr;
    }
    return VA;
  }
  case SymbolBody::DefinedCommonKind:
    if (!Config->DefineCommon)
      return 0;
    return In<ELFT>::Common->OutSec->Addr + In<ELFT>::Common->OutSecOff +
           cast<DefinedCommon>(Body).Offset;
  case SymbolBody::SharedKind: {
    auto &SS = cast<SharedSymbol<ELFT>>(Body);
    if (!SS.NeedsCopyOrPltAddr)
      return 0;
    if (SS.isFunc())
      return Body.getPltVA<ELFT>();
    return SS.getBssSectionForCopy()->Addr + SS.CopyOffset;
  }
  case SymbolBody::UndefinedKind:
    return 0;
  case SymbolBody::LazyArchiveKind:
  case SymbolBody::LazyObjectKind:
    assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer");
    return 0;
  }
  llvm_unreachable("invalid symbol kind");
}