Beispiel #1
0
void MCELFStreamer::Flush() {
  for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(),
                                                e = LocalCommons.end();
       i != e; ++i) {
    MCSymbolData *SD = i->SD;
    uint64_t Size = i->Size;
    unsigned ByteAlignment = i->ByteAlignment;
    const MCSymbol &Symbol = SD->getSymbol();
    const MCSection &Section = Symbol.getSection();

    MCSectionData &SectData = getAssembler().getOrCreateSectionData(Section);
    new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &SectData);

    MCFragment *F = new MCFillFragment(0, 0, Size, &SectData);
    SD->setFragment(F);

    // Update the maximum alignment of the section if necessary.
    if (ByteAlignment > SectData.getAlignment())
      SectData.setAlignment(ByteAlignment);
  }

  LocalCommons.clear();
}
Beispiel #2
0
bool MachObjectWriter::
IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
                                       const MCSymbolData &DataA,
                                       const MCFragment &FB,
                                       bool InSet,
                                       bool IsPCRel) const {
  if (InSet)
    return true;

  // The effective address is
  //     addr(atom(A)) + offset(A)
  //   - addr(atom(B)) - offset(B)
  // and the offsets are not relocatable, so the fixup is fully resolved when
  //  addr(atom(A)) - addr(atom(B)) == 0.
  const MCSymbolData *A_Base = 0, *B_Base = 0;

  const MCSymbol &SA = DataA.getSymbol().AliasedSymbol();
  const MCSection &SecA = SA.getSection();
  const MCSection &SecB = FB.getParent()->getSection();

  if (IsPCRel) {
    // The simple (Darwin, except on x86_64) way of dealing with this was to
    // assume that any reference to a temporary symbol *must* be a temporary
    // symbol in the same atom, unless the sections differ. Therefore, any PCrel
    // relocation to a temporary symbol (in the same section) is fully
    // resolved. This also works in conjunction with absolutized .set, which
    // requires the compiler to use .set to absolutize the differences between
    // symbols which the compiler knows to be assembly time constants, so we
    // don't need to worry about considering symbol differences fully resolved.
    //
    // If the file isn't using sub-sections-via-symbols, we can make the
    // same assumptions about any symbol that we normally make about
    // assembler locals.

    if (!Asm.getBackend().hasReliableSymbolDifference()) {
      if (!SA.isInSection() || &SecA != &SecB ||
          (!SA.isTemporary() &&
           FB.getAtom() != Asm.getSymbolData(SA).getFragment()->getAtom() &&
           Asm.getSubsectionsViaSymbols()))
        return false;
      return true;
    }
    // For Darwin x86_64, there is one special case when the reference IsPCRel.
    // If the fragment with the reference does not have a base symbol but meets
    // the simple way of dealing with this, in that it is a temporary symbol in
    // the same atom then it is assumed to be fully resolved.  This is needed so
    // a relocation entry is not created and so the static linker does not
    // mess up the reference later.
    else if(!FB.getAtom() &&
            SA.isTemporary() && SA.isInSection() && &SecA == &SecB){
      return true;
    }
  } else {
    if (!TargetObjectWriter->useAggressiveSymbolFolding())
      return false;
  }

  const MCFragment *FA = Asm.getSymbolData(SA).getFragment();

  // Bail if the symbol has no fragment.
  if (!FA)
    return false;

  A_Base = FA->getAtom();
  if (!A_Base)
    return false;

  B_Base = FB.getAtom();
  if (!B_Base)
    return false;

  // If the atoms are the same, they are guaranteed to have the same address.
  if (A_Base == B_Base)
    return true;

  // Otherwise, we can't prove this is fully resolved.
  return false;
}
/// This function takes a section data object from the assembler
/// and creates the associated COFF symbol staging object.
void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
                                       MCAssembler &Assembler,
                                       const MCAsmLayout &Layout) {
  MCSymbol const &Symbol = SymbolData.getSymbol();
  COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol);
  SymbolMap[&Symbol] = coff_symbol;

  if (SymbolData.getFlags() & COFF::SF_WeakExternal) {
    coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;

    if (Symbol.isVariable()) {
      const MCSymbolRefExpr *SymRef =
        dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());

      if (!SymRef)
        report_fatal_error("Weak externals may only alias symbols");

      coff_symbol->Other = GetOrCreateCOFFSymbol(&SymRef->getSymbol());
    } else {
      std::string WeakName = std::string(".weak.")
                           +  Symbol.getName().str()
                           + ".default";
      COFFSymbol *WeakDefault = createSymbol(WeakName);
      WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
      WeakDefault->Data.StorageClass  = COFF::IMAGE_SYM_CLASS_EXTERNAL;
      WeakDefault->Data.Type          = 0;
      WeakDefault->Data.Value         = 0;
      coff_symbol->Other = WeakDefault;
    }

    // Setup the Weak External auxiliary symbol.
    coff_symbol->Aux.resize(1);
    memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
    coff_symbol->Aux[0].AuxType = ATWeakExternal;
    coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
    coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
      COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;

    coff_symbol->MCData = &SymbolData;
  } else {
    const MCSymbolData &ResSymData =
      Assembler.getSymbolData(Symbol.AliasedSymbol());

    if (Symbol.isVariable()) {
      int64_t Addr;
      if (Symbol.getVariableValue()->EvaluateAsAbsolute(Addr, Layout))
        coff_symbol->Data.Value = Addr;
    }

    coff_symbol->Data.Type         = (ResSymData.getFlags() & 0x0000FFFF) >>  0;
    coff_symbol->Data.StorageClass = (ResSymData.getFlags() & 0x00FF0000) >> 16;

    // If no storage class was specified in the streamer, define it here.
    if (coff_symbol->Data.StorageClass == 0) {
      bool external = ResSymData.isExternal() || (ResSymData.Fragment == NULL);

      coff_symbol->Data.StorageClass =
       external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC;
    }

    if (Symbol.isAbsolute() || Symbol.AliasedSymbol().isVariable())
      coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
    else if (ResSymData.Fragment != NULL)
      coff_symbol->Section =
        SectionMap[&ResSymData.Fragment->getParent()->getSection()];

    coff_symbol->MCData = &ResSymData;
  }
}
bool MachObjectWriter::
IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
                                       const MCSymbolData &DataA,
                                       const MCFragment &FB,
                                       bool InSet,
                                       bool IsPCRel) const {
  if (InSet)
    return true;

  // The effective address is
  //     addr(atom(A)) + offset(A)
  //   - addr(atom(B)) - offset(B)
  // and the offsets are not relocatable, so the fixup is fully resolved when
  //  addr(atom(A)) - addr(atom(B)) == 0.
  const MCSymbolData *A_Base = 0, *B_Base = 0;

  const MCSymbol &SA = DataA.getSymbol().AliasedSymbol();
  const MCSection &SecA = SA.getSection();
  const MCSection &SecB = FB.getParent()->getSection();

  if (IsPCRel) {
    // The simple (Darwin, except on x86_64) way of dealing with this was to
    // assume that any reference to a temporary symbol *must* be a temporary
    // symbol in the same atom, unless the sections differ. Therefore, any PCrel
    // relocation to a temporary symbol (in the same section) is fully
    // resolved. This also works in conjunction with absolutized .set, which
    // requires the compiler to use .set to absolutize the differences between
    // symbols which the compiler knows to be assembly time constants, so we
    // don't need to worry about considering symbol differences fully resolved.

    if (!Asm.getBackend().hasReliableSymbolDifference()) {
      if (!SA.isTemporary() || !SA.isInSection() || &SecA != &SecB)
        return false;
      return true;
    }
  } else {
    if (!TargetObjectWriter->useAggressiveSymbolFolding())
      return false;
  }

  const MCFragment *FA = Asm.getSymbolData(SA).getFragment();

  // Bail if the symbol has no fragment.
  if (!FA)
    return false;

  A_Base = FA->getAtom();
  if (!A_Base)
    return false;

  B_Base = FB.getAtom();
  if (!B_Base)
    return false;

  // If the atoms are the same, they are guaranteed to have the same address.
  if (A_Base == B_Base)
    return true;

  // Otherwise, we can't prove this is fully resolved.
  return false;
}
void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
                                              const MCAssembler &Asm,
                                              const MCAsmLayout &Layout,
                                              const MCFragment *Fragment,
                                              const MCFixup &Fixup,
                                              MCValue Target,
                                              uint64_t &FixedValue) {
  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
  unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());

  // If this is a 32-bit TLVP reloc it's handled a bit differently.
  if (Target.getSymA() &&
      Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
    RecordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
                         FixedValue);
    return;
  }

  // If this is a difference or a defined symbol plus an offset, then we need a
  // scattered relocation entry. Differences always require scattered
  // relocations.
  if (Target.getSymB()) {
    RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
                              Target, Log2Size, FixedValue);
    return;
  }

  // Get the symbol data, if any.
  MCSymbolData *SD = 0;
  if (Target.getSymA())
    SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());

  // If this is an internal relocation with an offset, it also needs a scattered
  // relocation entry.
  uint32_t Offset = Target.getConstant();
  if (IsPCRel)
    Offset += 1 << Log2Size;
  // Try to record the scattered relocation if needed. Fall back to non
  // scattered if necessary (see comments in RecordScatteredRelocation()
  // for details).
  if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD) &&
      RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
                                Target, Log2Size, FixedValue))
    return;

  // See <reloc.h>.
  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
  unsigned Index = 0;
  unsigned IsExtern = 0;
  unsigned Type = 0;

  if (Target.isAbsolute()) { // constant
    // SymbolNum of 0 indicates the absolute section.
    //
    // FIXME: Currently, these are never generated (see code below). I cannot
    // find a case where they are actually emitted.
    Type = macho::RIT_Vanilla;
  } else {
    // Resolve constant variables.
    if (SD->getSymbol().isVariable()) {
      int64_t Res;
      if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
            Res, Layout, Writer->getSectionAddressMap())) {
        FixedValue = Res;
        return;
      }
    }

    // Check whether we need an external or internal relocation.
    if (Writer->doesSymbolRequireExternRelocation(SD)) {
      IsExtern = 1;
      Index = SD->getIndex();
      // For external relocations, make sure to offset the fixup value to
      // compensate for the addend of the symbol address, if it was
      // undefined. This occurs with weak definitions, for example.
      if (!SD->Symbol->isUndefined())
        FixedValue -= Layout.getSymbolOffset(SD);
    } else {
      // The index is the section ordinal (1-based).
      const MCSectionData &SymSD = Asm.getSectionData(
        SD->getSymbol().getSection());
      Index = SymSD.getOrdinal() + 1;
      FixedValue += Writer->getSectionAddress(&SymSD);
    }
    if (IsPCRel)
      FixedValue -= Writer->getSectionAddress(Fragment->getParent());

    Type = macho::RIT_Vanilla;
  }

  // struct relocation_info (8 bytes)
  macho::RelocationEntry MRE;
  MRE.Word0 = FixupOffset;
  MRE.Word1 = ((Index     <<  0) |
               (IsPCRel   << 24) |
               (Log2Size  << 25) |
               (IsExtern  << 27) |
               (Type      << 28));
  Writer->addRelocation(Fragment->getParent(), MRE);
}