// 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); }
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); }
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()); }
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); }
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); }
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); } }
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()); }
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); }
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); }
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)); }
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; }
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)); }
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); }
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()); }
// 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))); }
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); }
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); }
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()); }
// 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); }
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; } } }
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()); }
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()); }