예제 #1
0
// Associate DTPRel64 fixup with data and resize data area
void MCObjectStreamer::EmitDTPRel64Value(const MCExpr *Value) {
  MCDataFragment *DF = getOrCreateDataFragment();
  flushPendingLabels(DF, DF->getContents().size());

  DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
                                            Value, FK_DTPRel_8));
  DF->getContents().resize(DF->getContents().size() + 8, 0);
}
예제 #2
0
void WinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol)
{
  MCDataFragment *DF = getOrCreateDataFragment();

  DF->addFixup(MCFixup::Create(DF->getContents().size(),
                               MCSymbolRefExpr::Create (Symbol, getContext ()),
                               FK_SecRel_4));
  DF->getContents().resize(DF->getContents().size() + 4, 0);
}
예제 #3
0
void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
  MCAssembler &Assembler = getAssembler();
  SmallVector<MCFixup, 4> Fixups;
  SmallString<256> Code;
  raw_svector_ostream VecOS(Code);
  Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
  VecOS.flush();

  for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
    fixSymbolsInTLSFixups(Fixups[i].getValue());

  // There are several possibilities here:
  //
  // If bundling is disabled, append the encoded instruction to the current data
  // fragment (or create a new such fragment if the current fragment is not a
  // data fragment).
  //
  // If bundling is enabled:
  // - If we're not in a bundle-locked group, emit the instruction into a data
  //   fragment of its own.
  // - If we're in a bundle-locked group, append the instruction to the current
  //   data fragment because we want all the instructions in a group to get into
  //   the same fragment. Be careful not to do that for the first instruction in
  //   the group, though.
  MCDataFragment *DF;

  if (Assembler.isBundlingEnabled()) {
    MCSectionData *SD = getCurrentSectionData();
    if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst())
      DF = getOrCreateDataFragment();
    else {
      DF = new MCDataFragment(SD);
      if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) {
        // If this is a new fragment created for a bundle-locked group, and the
        // group was marked as "align_to_end", set a flag in the fragment.
        DF->setAlignToBundleEnd(true);
      }
    }

    // We're now emitting an instruction in a bundle group, so this flag has
    // to be turned off.
    SD->setBundleGroupBeforeFirstInst(false);
  } else {
    DF = getOrCreateDataFragment();
  }

  // Add the fixups and data.
  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
    Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
    DF->getFixups().push_back(Fixups[i]);
  }
  DF->setHasInstructions(true);
  DF->getContents().append(Code.begin(), Code.end());
}
예제 #4
0
void MCObjectStreamer::EmitBytes(StringRef Data) {
  MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
  MCDataFragment *DF = getOrCreateDataFragment();
  flushPendingLabels(DF, DF->getContents().size());
  DF->getContents().append(Data.begin(), Data.end());

  // EmitBytes might not cover all possible ways we emit data (or could be used
  // to emit executable code in some cases), but is the best method we have
  // right now for checking this.
  MCSection *Sec = getCurrentSectionOnly();
  Sec->setHasData(true);
}
예제 #5
0
void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol,
                                         uint64_t Offset) {
  MCDataFragment *DF = getOrCreateDataFragment();
  // Create Symbol A for the relocation relative reference.
  const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext());
  // Add the constant offset, if given.
  if (Offset)
    MCE = MCBinaryExpr::createAdd(
        MCE, MCConstantExpr::create(Offset, getContext()), getContext());
  // Build the secrel32 relocation.
  MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4);
  // Record the relocation.
  DF->getFixups().push_back(Fixup);
  // Emit 4 bytes (zeros) to the object file.
  DF->getContents().resize(DF->getContents().size() + 4, 0);
}
예제 #6
0
void SVMMemoryLayout::ApplyLateFixups(const MCAssembler &Asm,
    const MCAsmLayout &Layout)
{
    for (LateFixupList_t::iterator i = LateFixupList.begin();
        i != LateFixupList.end(); ++i) {
        SVMLateFixup &F = *i;
        MCDataFragment *DF = dyn_cast<MCDataFragment>(F.Fragment);
        assert(DF);
        MCSectionData *SD = DF->getParent();

        /*
         * Normally we use specially formatted "code addresses" for
         * labels in the text segment. These aren't real VAs, they are
         * packed words that include a 24-bit address and a stack adjustment.
         *
         * These addresses need to be formed for pointers that are stored
         * either in the text or the data segments, since they need to take
         * effect for function pointers.
         *
         * In debug sections, however, they're quite unhelpful- debuggers
         * expect real VAs. So we'll explicitly disable this feature when
         * performing a fixup that is located in a debug section.
         */
        bool useCodeAddresses = getSectionKind(SD) != SPS_DEBUG;

        SVMAsmBackend::ApplyStaticFixup(F.Kind,
            &DF->getContents().data()[F.Offset],
            getSymbol(Asm, Layout, F.Target, useCodeAddresses).Value);
    }
}
예제 #7
0
void MCMachOStreamer::EmitInstToData(const MCInst &Inst,
                                     const MCSubtargetInfo &STI) {
  MCDataFragment *DF = getOrCreateDataFragment();

  SmallVector<MCFixup, 4> Fixups;
  SmallString<256> Code;
  raw_svector_ostream VecOS(Code);
  getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);

  // Add the fixups and data.
  for (MCFixup &Fixup : Fixups) {
    Fixup.setOffset(Fixup.getOffset() + DF->getContents().size());
    DF->getFixups().push_back(Fixup);
  }
  DF->getContents().append(Code.begin(), Code.end());
}
예제 #8
0
void MCMachOStreamer::EmitInstToData(const MCInst &Inst) {
  MCDataFragment *DF = getOrCreateDataFragment();

  SmallVector<MCFixup, 4> Fixups;
  SmallString<256> Code;
  raw_svector_ostream VecOS(Code);
  getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
  VecOS.flush();

  // Add the fixups and data.
  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
    Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
    DF->addFixup(Fixups[i]);
  }
  DF->getContents().append(Code.begin(), Code.end());
}
void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
                                     unsigned AddrSpace) {
  assert(AddrSpace == 0 && "Address space must be 0!");
  MCDataFragment *DF = getOrCreateDataFragment();

  // Avoid fixups when possible.
  int64_t AbsValue;
  if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue, getAssembler())) {
    EmitIntValue(AbsValue, Size, AddrSpace);
    return;
  }
  DF->addFixup(MCFixup::Create(DF->getContents().size(),
                               Value,
                               MCFixup::getKindForSize(Size, false)));
  DF->getContents().resize(DF->getContents().size() + Size, 0);
}
예제 #10
0
void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size) {
  MCDataFragment *DF = getOrCreateDataFragment();

  MCLineEntry::Make(this, getCurrentSection().first);

  // Avoid fixups when possible.
  int64_t AbsValue;
  if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue, getAssembler())) {
    EmitIntValue(AbsValue, Size);
    return;
  }
  DF->getFixups().push_back(
      MCFixup::Create(DF->getContents().size(), Value,
                      MCFixup::getKindForSize(Size, false)));
  DF->getContents().resize(DF->getContents().size() + Size, 0);
}
예제 #11
0
void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
                                int64_t Expr, SMLoc Loc) {
  int64_t IntNumValues;
  // Do additional checking now if we can resolve the value.
  if (NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) {
    if (IntNumValues < 0) {
      getContext().getSourceManager()->PrintMessage(
          Loc, SourceMgr::DK_Warning,
          "'.fill' directive with negative repeat count has no effect");
      return;
    }
    // Emit now if we can for better errors.
    int64_t NonZeroSize = Size > 4 ? 4 : Size;
    Expr &= ~0ULL >> (64 - NonZeroSize * 8);
    for (uint64_t i = 0, e = IntNumValues; i != e; ++i) {
      EmitIntValue(Expr, NonZeroSize);
      if (NonZeroSize < Size)
        EmitIntValue(0, Size - NonZeroSize);
    }
    return;
  }

  // Otherwise emit as fragment.
  MCDataFragment *DF = getOrCreateDataFragment();
  flushPendingLabels(DF, DF->getContents().size());

  assert(getCurrentSectionOnly() && "need a section");
  insert(new MCFillFragment(Expr, Size, NumValues, Loc));
}
예제 #12
0
bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
                                          const MCExpr *Expr, SMLoc Loc,
                                          const MCSubtargetInfo &STI) {
  int64_t OffsetValue;
  if (!Offset.evaluateAsAbsolute(OffsetValue))
    llvm_unreachable("Offset is not absolute");

  if (OffsetValue < 0)
    llvm_unreachable("Offset is negative");

  MCDataFragment *DF = getOrCreateDataFragment(&STI);
  flushPendingLabels(DF, DF->getContents().size());

  Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name);
  if (!MaybeKind.hasValue())
    return true;

  MCFixupKind Kind = *MaybeKind;

  if (Expr == nullptr)
    Expr =
        MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
  DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc));
  return false;
}
예제 #13
0
void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
                                SMLoc Loc) {
  MCDataFragment *DF = getOrCreateDataFragment();
  flushPendingLabels(DF, DF->getContents().size());

  assert(getCurrentSectionOnly() && "need a section");
  insert(new MCFillFragment(FillValue, 1, NumBytes, Loc));
}
예제 #14
0
void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
                                     SMLoc Loc) {
    MCStreamer::EmitValueImpl(Value, Size, Loc);
    MCDataFragment *DF = getOrCreateDataFragment();
    flushPendingLabels(DF, DF->getContents().size());

    MCCVLineEntry::Make(this);
    MCDwarfLineEntry::Make(this, getCurrentSection().first);

    // Avoid fixups when possible.
    int64_t AbsValue;
    if (Value->evaluateAsAbsolute(AbsValue, getAssembler())) {
        EmitIntValue(AbsValue, Size);
        return;
    }
    DF->getFixups().push_back(
        MCFixup::create(DF->getContents().size(), Value,
                        MCFixup::getKindForSize(Size, false), Loc));
    DF->getContents().resize(DF->getContents().size() + Size, 0);
}
예제 #15
0
void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) {
  MCStreamer::EmitLabel(Symbol);

  MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);

  // FIXME: This is wasteful, we don't necessarily need to create a data
  // fragment. Instead, we should mark the symbol as pointing into the data
  // fragment if it exists, otherwise we should just queue the label and set its
  // fragment pointer when we emit the next fragment.
  MCDataFragment *F = getOrCreateDataFragment();
  assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
  SD.setFragment(F);
  SD.setOffset(F->getContents().size());
}
예제 #16
0
// Add the R_ARM_NONE fixup at the same position
void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) {
    const MCSymbol *PersonalitySym = getContext().GetOrCreateSymbol(Name);

    const MCSymbolRefExpr *PersonalityRef =
        MCSymbolRefExpr::Create(PersonalitySym,
                                MCSymbolRefExpr::VK_ARM_NONE,
                                getContext());

    AddValueSymbols(PersonalityRef);
    MCDataFragment *DF = getOrCreateDataFragment();
    DF->getFixups().push_back(
        MCFixup::Create(DF->getContents().size(), PersonalityRef,
                        MCFixup::getKindForSize(4, false)));
}
예제 #17
0
void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
                                     SMLoc Loc) {
  MCStreamer::EmitValueImpl(Value, Size, Loc);
  MCDataFragment *DF = getOrCreateDataFragment();
  flushPendingLabels(DF, DF->getContents().size());

  MCDwarfLineEntry::Make(this, getCurrentSectionOnly());

  // Avoid fixups when possible.
  int64_t AbsValue;
  if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {
    if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {
      getContext().reportError(
          Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");
      return;
    }
    EmitIntValue(AbsValue, Size);
    return;
  }
  DF->getFixups().push_back(
      MCFixup::create(DF->getContents().size(), Value,
                      MCFixup::getKindForSize(Size, false), Loc));
  DF->getContents().resize(DF->getContents().size() + Size, 0);
}
예제 #18
0
void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
                                SMLoc Loc) {
    MCDataFragment *DF = getOrCreateDataFragment();
    flushPendingLabels(DF, DF->getContents().size());

    int64_t IntNumBytes;
    if (!NumBytes.evaluateAsAbsolute(IntNumBytes, getAssembler())) {
        getContext().reportError(Loc, "expected absolute expression");
        return;
    }

    if (IntNumBytes <= 0) {
        getContext().reportError(Loc, "invalid number of bytes");
        return;
    }

    emitFill(IntNumBytes, FillValue);
}
예제 #19
0
void MCPureStreamer::EmitLabel(MCSymbol *Symbol) {
    assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
    assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
    assert(getCurrentSection() && "Cannot emit before setting section!");

    Symbol->setSection(*getCurrentSection());

    MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);

    // We have to create a new fragment if this is an atom defining symbol,
    // fragments cannot span atoms.
    if (getAssembler().isSymbolLinkerVisible(SD.getSymbol()))
        new MCDataFragment(getCurrentSectionData());

    // FIXME: This is wasteful, we don't necessarily need to create a data
    // fragment. Instead, we should mark the symbol as pointing into the data
    // fragment if it exists, otherwise we should just queue the label and set its
    // fragment pointer when we emit the next fragment.
    MCDataFragment *F = getOrCreateDataFragment();
    assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
    SD.setFragment(F);
    SD.setOffset(F->getContents().size());
}
예제 #20
0
// Associate GPRel32 fixup with data and resize data area
void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) {
  MCDataFragment *DF = getOrCreateDataFragment();

  DF->addFixup(MCFixup::Create(DF->getContents().size(), Value, FK_GPRel_4));
  DF->getContents().resize(DF->getContents().size() + 8, 0);
}
예제 #21
0
void MCELFStreamer::EmitInstToData(const MCInst &Inst,
                                   const MCSubtargetInfo &STI) {
  MCAssembler &Assembler = getAssembler();
  SmallVector<MCFixup, 4> Fixups;
  SmallString<256> Code;
  raw_svector_ostream VecOS(Code);
  Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
  VecOS.flush();

  for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
    fixSymbolsInTLSFixups(Fixups[i].getValue());

  // There are several possibilities here:
  //
  // If bundling is disabled, append the encoded instruction to the current data
  // fragment (or create a new such fragment if the current fragment is not a
  // data fragment).
  //
  // If bundling is enabled:
  // - If we're not in a bundle-locked group, emit the instruction into a
  //   fragment of its own. If there are no fixups registered for the
  //   instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a
  //   MCDataFragment.
  // - If we're in a bundle-locked group, append the instruction to the current
  //   data fragment because we want all the instructions in a group to get into
  //   the same fragment. Be careful not to do that for the first instruction in
  //   the group, though.
  MCDataFragment *DF;

  if (Assembler.isBundlingEnabled()) {
    MCSection &Sec = *getCurrentSectionOnly();
    if (Assembler.getRelaxAll() && isBundleLocked())
      // If the -mc-relax-all flag is used and we are bundle-locked, we re-use
      // the current bundle group.
      DF = BundleGroups.back();
    else if (Assembler.getRelaxAll() && !isBundleLocked())
      // When not in a bundle-locked group and the -mc-relax-all flag is used,
      // we create a new temporary fragment which will be later merged into
      // the current fragment.
      DF = new MCDataFragment();
    else if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst())
      // If we are bundle-locked, we re-use the current fragment.
      // The bundle-locking directive ensures this is a new data fragment.
      DF = cast<MCDataFragment>(getCurrentFragment());
    else if (!isBundleLocked() && Fixups.size() == 0) {
      // Optimize memory usage by emitting the instruction to a
      // MCCompactEncodedInstFragment when not in a bundle-locked group and
      // there are no fixups registered.
      MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment();
      insert(CEIF);
      CEIF->getContents().append(Code.begin(), Code.end());
      return;
    } else {
      DF = new MCDataFragment();
      insert(DF);
    }
    if (Sec.getBundleLockState() == MCSection::BundleLockedAlignToEnd) {
      // If this fragment is for a group marked "align_to_end", set a flag
      // in the fragment. This can happen after the fragment has already been
      // created if there are nested bundle_align groups and an inner one
      // is the one marked align_to_end.
      DF->setAlignToBundleEnd(true);
    }

    // We're now emitting an instruction in a bundle group, so this flag has
    // to be turned off.
    Sec.setBundleGroupBeforeFirstInst(false);
  } else {
    DF = getOrCreateDataFragment();
  }

  // Add the fixups and data.
  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
    Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
    DF->getFixups().push_back(Fixups[i]);
  }
  DF->setHasInstructions(true);
  DF->getContents().append(Code.begin(), Code.end());

  if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) {
    if (!isBundleLocked()) {
      mergeFragment(getOrCreateDataFragment(), DF);
      delete DF;
    }
  }
}
예제 #22
0
void MCObjectStreamer::EmitBytes(StringRef Data) {
  MCLineEntry::Make(this, getCurrentSection().first);
  MCDataFragment *DF = getOrCreateDataFragment();
  flushPendingLabels(DF, DF->getContents().size());
  DF->getContents().append(Data.begin(), Data.end());
}
예제 #23
0
void SVMELFProgramWriter::rwCompress(MCAssembler &Asm, const MCAsmLayout &Layout, SVMMemoryLayout &ML)
{
    /*
     * Look for all segments with initialized data for RAM, flatten them, and
     * compress the resulting data. Create a new segment with the compressed
     * RWDATA. This segment will always be included in the binary. The originals
     * are considered debug-only sections, since they are no longer needed
     * at runtime.
     */

    // Flattened binary contents of RAM
    std::vector<uint8_t> plaintext;

    // Iterate over SPS_RW sections
    for (MCAssembler::const_iterator IS = Asm.begin(), ES = Asm.end(); IS != ES; ++IS) {
        const MCSectionData *SD = &*IS;
        if (ML.getSectionKind(SD) != SPS_RW_PLAIN)
            continue;

        int offset = ML.getSectionMemAddress(SD) - SVMTargetMachine::getRAMBase();
        int limit = SVMTargetMachine::getRAMSize();

        // Iterate over fragments, pasting them into 'plaintext'
        for (MCSectionData::const_iterator IF = SD->begin(), EF = SD->end(); IF != EF; ++IF) {
            const MCFragment *F = &*IF;
            if (F->getKind() == MCFragment::FT_Data) {
                const MCDataFragment *DF = cast<MCDataFragment>(F);
                int fragmentOffset = Layout.getFragmentOffset(F);
                for (unsigned i = 0; i < DF->getContents().size(); i++) {
                    int totalOffset = fragmentOffset + offset + i;
                    if (totalOffset < limit) {
                        while (totalOffset >= int(plaintext.size()))
                            plaintext.push_back(0);
                        plaintext[totalOffset] = DF->getContents()[i];
                    }
                }
            }
        }
    }

    // FastLZ requires a minimum of 16 bytes to compress. Pad our section data.
    while (plaintext.size() < 16)
        plaintext.push_back(0);

    // Compress using FastLZ level 1
    std::vector<uint8_t> compressed(plaintext.size() * 2);
    compressed.resize(fastlz_compress_level(1, &plaintext[0], plaintext.size(), &compressed[0]));

    // Create the new section
    const MCSectionELF *LZSection =
        Asm.getContext().getELFSection(".rwdata.lz", ELF::SHT_NOTE,
                                       0, SectionKind::getDataNoRel());
    MCSectionData &LZSectionSD = Asm.getOrCreateSectionData(*LZSection);
    LZSectionSD.setAlignment(1);

    // Force it to be interpreted as SPS_RW, and set the decompressed size
    ML.setSectionKind(&LZSectionSD, SPS_RW_Z);
    ML.setSectionMemSize(&LZSectionSD, plaintext.size());

    // Add compressed data
    MCDataFragment *F = new MCDataFragment(&LZSectionSD);
    F->getContents().append(compressed.begin(), compressed.end());
}