/// been initialized.
void LayoutFragment(MCFragment *Fragment);
- /// \brief Performs initial layout for a single section, assuming that the
- /// previous section (including its fragments) has already been layed out
- /// correctly.
- void LayoutSection(MCSectionData *SD);
-
/// @name Section Access (in layout order)
/// @{
/// \brief Get the offset of the given fragment inside its containing section.
uint64_t getFragmentOffset(const MCFragment *F) const;
- /// @}
- /// @name Section Layout Data
- /// @{
-
- /// \brief Get the computed address of the given section.
- uint64_t getSectionAddress(const MCSectionData *SD) const;
-
/// @}
/// @name Utility Functions
/// @{
- /// \brief Get the address of the given fragment, as computed in the current
- /// layout.
- uint64_t getFragmentAddress(const MCFragment *F) const;
-
/// \brief Get the address space size of the given section, as it effects
/// layout. This may differ from the size reported by \see getSectionSize() by
/// not including section tail padding.
/// file. This may include additional padding, or be 0 for virtual sections.
uint64_t getSectionFileSize(const MCSectionData *SD) const;
- /// \brief Get the logical data size of the given section.
- uint64_t getSectionSize(const MCSectionData *SD) const;
-
- /// \brief Get the address of the given symbol, as computed in the current
- /// layout.
- uint64_t getSymbolAddress(const MCSymbolData *SD) const;
-
/// \brief Get the offset of the given symbol, as computed in the current
/// layout.
uint64_t getSymbolOffset(const MCSymbolData *SD) const;
/// target dependent.
bool EmitNops : 1;
- /// OnlyAlignAddress - Flag to indicate that this align is only used to adjust
- /// the address space size of a section and that it should not be included as
- /// part of the section size. This flag can only be used on the last fragment
- /// in a section.
- bool OnlyAlignAddress : 1;
-
public:
MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize,
unsigned _MaxBytesToEmit, MCSectionData *SD = 0)
: MCFragment(FT_Align, SD), Alignment(_Alignment),
Value(_Value),ValueSize(_ValueSize),
- MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false),
- OnlyAlignAddress(false) {}
+ MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {}
/// @name Accessors
/// @{
bool hasEmitNops() const { return EmitNops; }
void setEmitNops(bool Value) { EmitNops = Value; }
- bool hasOnlyAlignAddress() const { return OnlyAlignAddress; }
- void setOnlyAlignAddress(bool Value) { OnlyAlignAddress = Value; }
-
/// @}
static bool classof(const MCFragment *F) {
//
// FIXME: This could all be kept private to the assembler implementation.
- /// Address - The computed address of this section. This is ~0 until
- /// initialized.
- uint64_t Address;
-
/// HasInstructions - Whether this section has had instructions emitted into
/// it.
unsigned HasInstructions : 1;
unsigned RelaxAll : 1;
unsigned SubsectionsViaSymbols : 1;
- unsigned PadSectionToAlignment : 1;
private:
/// Evaluate a fixup to a relocatable expression and the value which should be
/// Compute the effective fragment size assuming it is layed out at the given
/// \arg SectionAddress and \arg FragmentOffset.
uint64_t ComputeFragmentSize(const MCFragment &F,
- uint64_t SectionAddress,
uint64_t FragmentOffset) const;
/// LayoutOnce - Perform one layout iteration and return true if any offsets
// option is to make this abstract, and have targets provide concrete
// implementations as we do with AsmParser.
MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend,
- MCCodeEmitter &_Emitter, bool _PadSectionToAlignment,
- raw_ostream &OS);
+ MCCodeEmitter &_Emitter, raw_ostream &OS);
~MCAssembler();
MCContext &getContext() const { return Context; }
#ifndef LLVM_MC_MCEXPR_H
#define LLVM_MC_MCEXPR_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
class MCAsmLayout;
class MCAssembler;
class MCContext;
+class MCSectionData;
class MCSymbol;
class MCValue;
class raw_ostream;
class StringRef;
+typedef DenseMap<const MCSectionData*, uint64_t> SectionAddrMap;
/// MCExpr - Base class for the full range of assembler expressions which are
/// needed for parsing.
void operator=(const MCExpr&); // DO NOT IMPLEMENT
bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
- const MCAsmLayout *Layout) const;
+ const MCAsmLayout *Layout,
+ const SectionAddrMap *Addrs) const;
protected:
explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {}
bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout,
+ const SectionAddrMap *Addrs,
bool InSet) const;
public:
/// @name Accessors
bool EvaluateAsAbsolute(int64_t &Res) const;
bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const;
bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
+ bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout,
+ const SectionAddrMap &Addrs) const;
/// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable
/// value, i.e. an expression of the fixed form (a - b + constant).
protected:
MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB,
- raw_ostream &_OS, MCCodeEmitter *_Emitter,
- bool _PadSectionToAlignment);
+ raw_ostream &_OS, MCCodeEmitter *_Emitter);
~MCObjectStreamer();
MCSectionData *getCurrentSectionData() const {
///
/// This routine is called by the assembler after layout and relaxation is
/// complete.
- virtual void ExecutePostLayoutBinding(MCAssembler &Asm) = 0;
+ virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout) = 0;
/// Record a relocation entry.
///
virtual void CreateGroupSections(MCAssembler &Asm, MCAsmLayout &Layout,
GroupMapTy &GroupMap, RevGroupMapTy &RevGroupMap);
- virtual void ExecutePostLayoutBinding(MCAssembler &Asm);
+ virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout);
virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
uint64_t Address, uint64_t Offset,
return 0;
}
-void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
+void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
// The presence of symbol versions causes undefined symbols and
// versions declared with @@@ to be renamed.
return Layout.getSectionFileSize(&SD);
}
-static uint64_t GetSectionSize(const MCAsmLayout &Layout,
- const MCSectionData &SD) {
+static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout,
+ const MCSectionData &SD) {
if (IsELFMetaDataSection(SD))
return DataSectionSize(SD);
- return Layout.getSectionSize(&SD);
+ return Layout.getSectionAddressSize(&SD);
}
static void WriteDataSectionData(ELFObjectWriter *W, const MCSectionData &SD) {
else
GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, GroupMap[&Section]);
- uint64_t Size = GetSectionSize(Layout, SD);
+ uint64_t Size = GetSectionAddressSize(Layout, SD);
WriteSection(Asm, SectionIndexMap, GroupSymbolIndex,
SectionOffsetMap[&Section], Size,
STATISTIC(ObjectBytes, "Number of emitted object file bytes");
STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps");
STATISTIC(RelaxedInstructions, "Number of relaxed instructions");
-STATISTIC(SectionLayouts, "Number of section layouts");
}
}
}
}
-uint64_t MCAsmLayout::getFragmentAddress(const MCFragment *F) const {
- assert(F->getParent() && "Missing section()!");
- return getSectionAddress(F->getParent()) + getFragmentOffset(F);
-}
-
uint64_t MCAsmLayout::getFragmentEffectiveSize(const MCFragment *F) const {
EnsureValid(F);
assert(F->EffectiveSize != ~UINT64_C(0) && "Address not set!");
return getFragmentOffset(SD->getFragment()) + SD->getOffset();
}
-uint64_t MCAsmLayout::getSymbolAddress(const MCSymbolData *SD) const {
- assert(SD->getFragment() && "Invalid getAddress() on undefined symbol!");
- return getFragmentAddress(SD->getFragment()) + SD->getOffset();
-}
-
-uint64_t MCAsmLayout::getSectionAddress(const MCSectionData *SD) const {
- EnsureValid(SD->begin());
- assert(SD->Address != ~UINT64_C(0) && "Address not set!");
- return SD->Address;
-}
-
uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const {
// The size is the last fragment's end offset.
const MCFragment &F = SD->getFragmentList().back();
return getSectionAddressSize(SD);
}
-uint64_t MCAsmLayout::getSectionSize(const MCSectionData *SD) const {
- // The logical size is the address space size minus any tail padding.
- uint64_t Size = getSectionAddressSize(SD);
- const MCAlignFragment *AF =
- dyn_cast<MCAlignFragment>(&(SD->getFragmentList().back()));
- if (AF && AF->hasOnlyAlignAddress())
- Size -= getFragmentEffectiveSize(AF);
-
- return Size;
-}
-
/* *** */
MCFragment::MCFragment() : Kind(FragmentType(~0)) {
: Section(&_Section),
Ordinal(~UINT32_C(0)),
Alignment(1),
- Address(~UINT64_C(0)),
HasInstructions(false)
{
if (A)
/* *** */
MCAssembler::MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend,
- MCCodeEmitter &_Emitter, bool _PadSectionToAlignment,
- raw_ostream &_OS)
+ MCCodeEmitter &_Emitter, raw_ostream &_OS)
: Context(_Context), Backend(_Backend), Emitter(_Emitter),
- OS(_OS), RelaxAll(false), SubsectionsViaSymbols(false),
- PadSectionToAlignment(_PadSectionToAlignment)
+ OS(_OS), RelaxAll(false), SubsectionsViaSymbols(false)
{
}
if (const MCSymbolRefExpr *A = Target.getSymA()) {
const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
if (Sym.isDefined())
- Value += Layout.getSymbolAddress(&getSymbolData(Sym));
+ Value += Layout.getSymbolOffset(&getSymbolData(Sym));
else
IsResolved = false;
}
if (const MCSymbolRefExpr *B = Target.getSymB()) {
const MCSymbol &Sym = B->getSymbol().AliasedSymbol();
if (Sym.isDefined())
- Value -= Layout.getSymbolAddress(&getSymbolData(Sym));
+ Value -= Layout.getSymbolOffset(&getSymbolData(Sym));
else
IsResolved = false;
}
IsResolved = Writer.IsFixupFullyResolved(*this, Target, IsPCRel, DF);
if (IsPCRel)
- Value -= Layout.getFragmentAddress(DF) + Fixup.getOffset();
+ Value -= Layout.getFragmentOffset(DF) + Fixup.getOffset();
return IsResolved;
}
uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
- uint64_t SectionAddress,
uint64_t FragmentOffset) const {
switch (F.getKind()) {
case MCFragment::FT_Data:
case MCFragment::FT_Align: {
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
- assert((!AF.hasOnlyAlignAddress() || !AF.getNextNode()) &&
- "Invalid OnlyAlignAddress bit, not the last fragment!");
-
- uint64_t Size = OffsetToAlignment(SectionAddress + FragmentOffset,
- AF.getAlignment());
+ uint64_t Size = OffsetToAlignment(FragmentOffset, AF.getAlignment());
// Honor MaxBytesToEmit.
if (Size > AF.getMaxBytesToEmit())
// Initialize the first section and set the valid fragment layout point. All
// actual layout computations are done lazily.
LastValidFragment = 0;
- if (!getSectionOrder().empty())
- getSectionOrder().front()->Address = 0;
}
void MCAsmLayout::LayoutFragment(MCFragment *F) {
++stats::FragmentLayouts;
- // Compute the fragment start address.
- uint64_t StartAddress = F->getParent()->Address;
- uint64_t Address = StartAddress;
+ // Compute fragment offset and size.
+ uint64_t Offset = 0;
if (Prev)
- Address += Prev->Offset + Prev->EffectiveSize;
+ Offset += Prev->Offset + Prev->EffectiveSize;
- // Compute fragment offset and size.
- F->Offset = Address - StartAddress;
- F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, StartAddress,
- F->Offset);
+ F->Offset = Offset;
+ F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, F->Offset);
LastValidFragment = F;
-
- // If this is the last fragment in a section, update the next section address.
- if (!F->getNextNode()) {
- unsigned NextIndex = F->getParent()->getLayoutOrder() + 1;
- if (NextIndex != getSectionOrder().size())
- LayoutSection(getSectionOrder()[NextIndex]);
- }
-}
-
-void MCAsmLayout::LayoutSection(MCSectionData *SD) {
- unsigned SectionOrderIndex = SD->getLayoutOrder();
-
- ++stats::SectionLayouts;
-
- // Compute the section start address.
- uint64_t StartAddress = 0;
- if (SectionOrderIndex) {
- MCSectionData *Prev = getSectionOrder()[SectionOrderIndex - 1];
- StartAddress = getSectionAddress(Prev) + getSectionAddressSize(Prev);
- }
-
- // Honor the section alignment requirements.
- StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment());
-
- // Set the section address.
- SD->Address = StartAddress;
}
/// WriteFragmentData - Write the \arg F data to the output file.
ie = SD->end(); it != ie; ++it)
WriteFragmentData(*this, Layout, *it, OW);
- assert(OW->getStream().tell() - Start == Layout.getSectionFileSize(SD));
+ assert(OW->getStream().tell() - Start == Layout.getSectionAddressSize(SD));
}
// Create the layout object.
MCAsmLayout Layout(*this);
- // Insert additional align fragments for concrete sections to explicitly pad
- // the previous section to match their alignment requirements. This is for
- // 'gas' compatibility, it shouldn't strictly be necessary.
- if (PadSectionToAlignment) {
- for (unsigned i = 1, e = Layout.getSectionOrder().size(); i < e; ++i) {
- MCSectionData *SD = Layout.getSectionOrder()[i];
-
- // Ignore sections without alignment requirements.
- unsigned Align = SD->getAlignment();
- if (Align <= 1)
- continue;
-
- // Ignore virtual sections, they don't cause file size modifications.
- if (SD->getSection().isVirtualSection())
- continue;
-
- // Otherwise, create a new align fragment at the end of the previous
- // section.
- MCAlignFragment *AF = new MCAlignFragment(Align, 0, 1, Align,
- Layout.getSectionOrder()[i - 1]);
- AF->setOnlyAlignAddress(true);
- }
- }
+
// Create dummy fragments and assign section ordinals.
unsigned SectionIndex = 0;
// Allow the object writer a chance to perform post-layout binding (for
// example, to set the index fields in the symbol data).
- Writer->ExecutePostLayoutBinding(*this);
+ Writer->ExecutePostLayoutBinding(*this, Layout);
// Evaluate and apply the fixups, generating relocation entries as necessary.
for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) {
const MCAlignFragment *AF = cast<MCAlignFragment>(this);
if (AF->hasEmitNops())
OS << " (emit nops)";
- if (AF->hasOnlyAlignAddress())
- OS << " (only align section)";
OS << "\n ";
OS << " Alignment:" << AF->getAlignment()
<< " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize()
raw_ostream &OS = llvm::errs();
OS << "<MCSectionData";
- OS << " Alignment:" << getAlignment() << " Address:" << Address
- << " Fragments:[\n ";
+ OS << " Alignment:" << getAlignment() << " Fragments:[\n ";
for (iterator it = begin(), ie = end(); it != ie; ++it) {
if (it != begin()) OS << ",\n ";
it->dump();
public:
MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter)
- : MCObjectStreamer(Context, TAB, OS, Emitter, false) {}
+ : MCObjectStreamer(Context, TAB, OS, Emitter) {}
~MCELFStreamer() {}
/* *** */
bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const {
- return EvaluateAsAbsolute(Res, 0, 0);
+ return EvaluateAsAbsolute(Res, 0, 0, 0);
}
bool MCExpr::EvaluateAsAbsolute(int64_t &Res,
const MCAsmLayout &Layout) const {
- return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout);
+ return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, 0);
+}
+
+bool MCExpr::EvaluateAsAbsolute(int64_t &Res,
+ const MCAsmLayout &Layout,
+ const SectionAddrMap &Addrs) const {
+ return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs);
}
bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
- return EvaluateAsAbsolute(Res, &Asm, 0);
+ return EvaluateAsAbsolute(Res, &Asm, 0, 0);
}
bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
- const MCAsmLayout *Layout) const {
+ const MCAsmLayout *Layout,
+ const SectionAddrMap *Addrs) const {
MCValue Value;
// Fast path constants.
return true;
}
- if (!EvaluateAsRelocatableImpl(Value, Asm, Layout, false) ||
+ if (!EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, Addrs) ||
!Value.isAbsolute()) {
// EvaluateAsAbsolute is defined to return the "current value" of
// the expression if we are given a Layout object, even in cases
if (Layout) {
Res = Value.getConstant();
if (Value.getSymA()) {
- Res += Layout->getSymbolAddress(
+ Res += Layout->getSymbolOffset(
&Layout->getAssembler().getSymbolData(Value.getSymA()->getSymbol()));
}
if (Value.getSymB()) {
- Res -= Layout->getSymbolAddress(
+ Res -= Layout->getSymbolOffset(
&Layout->getAssembler().getSymbolData(Value.getSymB()->getSymbol()));
}
}
return true;
}
-static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout,
- const MCAssembler *Asm,
+static bool EvaluateSymbolicAdd(const MCAssembler *Asm,
+ const MCAsmLayout *Layout,
+ const SectionAddrMap *Addrs,
bool InSet,
const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst,
}
if (Layout) {
- Res = MCValue::get(+ Layout->getSymbolAddress(&AD)
- - Layout->getSymbolAddress(&BD)
- + LHS.getConstant()
- + RHS_Cst);
+ const MCSectionData &SecA = *AD.getFragment()->getParent();
+ const MCSectionData &SecB = *BD.getFragment()->getParent();
+ int64_t Val = + Layout->getSymbolOffset(&AD)
+ - Layout->getSymbolOffset(&BD)
+ + LHS.getConstant()
+ + RHS_Cst;
+ if (&SecA != &SecB) {
+ if (!Addrs)
+ return false;
+ Val += Addrs->lookup(&SecA);
+ Val -= Addrs->lookup(&SecB);
+ }
+ Res = MCValue::get(Val);
return true;
}
}
const MCAsmLayout *Layout) const {
if (Layout)
return EvaluateAsRelocatableImpl(Res, &Layout->getAssembler(), Layout,
- false);
+ 0, false);
else
- return EvaluateAsRelocatableImpl(Res, 0, 0, false);
+ return EvaluateAsRelocatableImpl(Res, 0, 0, 0, false);
}
bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
const MCAssembler *Asm,
const MCAsmLayout *Layout,
+ const SectionAddrMap *Addrs,
bool InSet) const {
++stats::MCExprEvaluate;
if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm,
Layout,
+ Addrs,
true);
// If we failed to simplify this to a constant, let the target
// handle it.
MCValue Value;
if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout,
- InSet))
+ Addrs, InSet))
return false;
switch (AUE->getOpcode()) {
MCValue LHSValue, RHSValue;
if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout,
- InSet) ||
+ Addrs, InSet) ||
!ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout,
- InSet))
+ Addrs, InSet))
return false;
// We only support a few operations on non-constant expressions, handle
return false;
case MCBinaryExpr::Sub:
// Negate RHS and add.
- return EvaluateSymbolicAdd(Layout, Asm, InSet, LHSValue,
+ return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
RHSValue.getSymB(), RHSValue.getSymA(),
-RHSValue.getConstant(),
Res);
case MCBinaryExpr::Add:
- return EvaluateSymbolicAdd(Layout, Asm, InSet, LHSValue,
+ return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
RHSValue.getSymA(), RHSValue.getSymB(),
RHSValue.getConstant(),
Res);
public:
MCMachOStreamer(MCContext &Context, TargetAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter)
- : MCObjectStreamer(Context, TAB, OS, Emitter, true) {}
+ : MCObjectStreamer(Context, TAB, OS, Emitter) {}
/// @name MCStreamer Interface
/// @{
using namespace llvm;
MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB,
- raw_ostream &_OS, MCCodeEmitter *_Emitter,
- bool _PadSectionToAlignment)
+ raw_ostream &_OS, MCCodeEmitter *_Emitter)
: MCStreamer(Context), Assembler(new MCAssembler(Context, TAB,
*_Emitter,
- _PadSectionToAlignment,
_OS)),
CurSectionData(0)
{
public:
MCPureStreamer(MCContext &Context, TargetAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter)
- : MCObjectStreamer(Context, TAB, OS, Emitter,
- /*PadSectionToAlignment=*/true) {}
+ : MCObjectStreamer(Context, TAB, OS, Emitter) {}
/// @name MCStreamer Interface
/// @{
/// @}
+ SectionAddrMap SectionAddress;
+ uint64_t getSectionAddress(const MCSectionData* SD) const {
+ return SectionAddress.lookup(SD);
+ }
+ uint64_t getSymbolAddress(const MCSymbolData* SD,
+ const MCAsmLayout &Layout) const {
+ return getSectionAddress(SD->getFragment()->getParent()) +
+ Layout.getSymbolOffset(SD);
+ }
+ uint64_t getFragmentAddress(const MCFragment *Fragment,
+ const MCAsmLayout &Layout) const {
+ return getSectionAddress(Fragment->getParent()) +
+ Layout.getFragmentOffset(Fragment);
+ }
+
+ uint64_t getPaddingSize(const MCSectionData *SD,
+ const MCAsmLayout &Layout) const {
+ uint64_t EndAddr = getSectionAddress(SD) + Layout.getSectionAddressSize(SD);
+ unsigned Next = SD->getLayoutOrder() + 1;
+ if (Next >= Layout.getSectionOrder().size())
+ return 0;
+
+ const MCSectionData &NextSD = *Layout.getSectionOrder()[Next];
+ if (NextSD.getSection().isVirtualSection())
+ return 0;
+ return OffsetToAlignment(EndAddr, NextSD.getAlignment());
+ }
+
unsigned Is64Bit : 1;
uint32_t CPUType;
void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCSectionData &SD, uint64_t FileOffset,
uint64_t RelocationsStart, unsigned NumRelocations) {
- uint64_t SectionSize = Layout.getSectionSize(&SD);
+ uint64_t SectionSize = Layout.getSectionAddressSize(&SD);
// The offset is unused for virtual sections.
if (SD.getSection().isVirtualSection()) {
WriteBytes(Section.getSectionName(), 16);
WriteBytes(Section.getSegmentName(), 16);
if (Is64Bit) {
- Write64(Layout.getSectionAddress(&SD)); // address
+ Write64(getSectionAddress(&SD)); // address
Write64(SectionSize); // size
} else {
- Write32(Layout.getSectionAddress(&SD)); // address
+ Write32(getSectionAddress(&SD)); // address
Write32(SectionSize); // size
}
Write32(FileOffset);
if (Symbol.isAbsolute()) {
Address = cast<MCConstantExpr>(Symbol.getVariableValue())->getValue();
} else {
- Address = Layout.getSymbolAddress(&Data);
+ Address = getSymbolAddress(&Data, Layout);
}
} else if (Data.isCommon()) {
// Common symbols are encoded with the size in the address
uint32_t FixupOffset =
Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
uint32_t FixupAddress =
- Layout.getFragmentAddress(Fragment) + Fixup.getOffset();
+ getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
int64_t Value = 0;
unsigned Index = 0;
unsigned IsExtern = 0;
// The index is the section ordinal (1-based).
Index = SD.getFragment()->getParent()->getOrdinal() + 1;
IsExtern = 0;
- Value += Layout.getSymbolAddress(&SD);
+ Value += getSymbolAddress(&SD, Layout);
if (IsPCRel)
Value -= FixupAddress + (1 << Log2Size);
+ } else if (Symbol->isVariable()) {
+ const MCExpr *Value = Symbol->getVariableValue();
+ int64_t Res;
+ bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, SectionAddress);
+ if (isAbs) {
+ FixedValue = Res;
+ return;
+ } else {
+ report_fatal_error("unsupported relocation of variable '" +
+ Symbol->getName() + "'");
+ }
} else {
report_fatal_error("unsupported relocation of undefined symbol '" +
Symbol->getName() + "'");
report_fatal_error("symbol '" + A->getName() +
"' can not be undefined in a subtraction expression");
- uint32_t Value = Layout.getSymbolAddress(A_SD);
+ uint32_t Value = getSymbolAddress(A_SD, Layout);
+ uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent());
+ FixedValue += SecAddr;
uint32_t Value2 = 0;
if (const MCSymbolRefExpr *B = Target.getSymB()) {
// for pedantic compatibility with 'as'.
Type = A_SD->isExternal() ? macho::RIT_Difference :
macho::RIT_LocalDifference;
- Value2 = Layout.getSymbolAddress(B_SD);
+ Value2 = getSymbolAddress(B_SD, Layout);
+ FixedValue -= getSectionAddress(B_SD->getFragment()->getParent());
}
// Relocations are written out in reverse order, so the PAIR comes first.
if (Target.getSymB()) {
// If this is a subtraction then we're pcrel.
uint32_t FixupAddress =
- Layout.getFragmentAddress(Fragment) + Fixup.getOffset();
+ getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol());
IsPCRel = 1;
- FixedValue = (FixupAddress - Layout.getSymbolAddress(SD_B) +
+ FixedValue = (FixupAddress - getSymbolAddress(SD_B, Layout) +
Target.getConstant());
FixedValue += 1ULL << Log2Size;
} else {
// 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.getSymbolAddress(SD);
+ FixedValue -= getSymbolAddress(SD, Layout);
} else {
// The index is the section ordinal (1-based).
Index = SD->getFragment()->getParent()->getOrdinal() + 1;
+ FixedValue += getSectionAddress(SD->getFragment()->getParent());
+ if (IsPCRel)
+ FixedValue -= getSectionAddress(Fragment->getParent());
}
Type = macho::RIT_Vanilla;
StringTable += '\x00';
}
- void ExecutePostLayoutBinding(MCAssembler &Asm) {
+ void computeSectionAddresses(const MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ uint64_t StartAddress = 0;
+ const SmallVectorImpl<MCSectionData*> &Order = Layout.getSectionOrder();
+ for (int i = 0, n = Order.size(); i != n ; ++i) {
+ const MCSectionData *SD = Order[i];
+ StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment());
+ SectionAddress[SD] = StartAddress;
+ StartAddress += Layout.getSectionAddressSize(SD);
+ // Explicitly pad the section to match the alignment requirements of the
+ // following one. This is for 'gas' compatibility, it shouldn't
+ /// strictly be necessary.
+ StartAddress += getPaddingSize(SD, Layout);
+ }
+ }
+
+ void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) {
+ computeSectionAddresses(Asm, Layout);
+
// Create symbol data for any indirect symbols.
BindIndirectSymbols(Asm);
for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it) {
const MCSectionData &SD = *it;
- uint64_t Address = Layout.getSectionAddress(&SD);
- uint64_t Size = Layout.getSectionSize(&SD);
+ uint64_t Address = getSectionAddress(&SD);
+ uint64_t Size = Layout.getSectionAddressSize(&SD);
uint64_t FileSize = Layout.getSectionFileSize(&SD);
+ FileSize += getPaddingSize(&SD, Layout);
VMSize = std::max(VMSize, Address + Size);
ie = Asm.end(); it != ie; ++it) {
std::vector<macho::RelocationEntry> &Relocs = Relocations[it];
unsigned NumRelocs = Relocs.size();
- uint64_t SectionStart = SectionDataStart + Layout.getSectionAddress(it);
+ uint64_t SectionStart = SectionDataStart + getSectionAddress(it);
WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs);
RelocTableEnd += NumRelocs * macho::RelocationInfoSize;
}
// Write the actual section data.
for (MCAssembler::const_iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it)
+ ie = Asm.end(); it != ie; ++it) {
Asm.WriteSectionData(it, Layout, this);
+ uint64_t Pad = getPaddingSize(it, Layout);
+ for (unsigned int i = 0; i < Pad; ++i)
+ Write8(0);
+ }
+
// Write the extra padding.
WriteZeros(SectionDataPadding);
// MCObjectWriter interface implementation.
- void ExecutePostLayoutBinding(MCAssembler &Asm);
+ void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout);
void RecordRelocation(const MCAssembler &Asm,
const MCAsmLayout &Layout,
////////////////////////////////////////////////////////////////////////////////
// MCObjectWriter interface implementations
-void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
+void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
// "Define" each section & symbol. This creates section & symbol
// entries in the staging area.
for (sections::iterator i = Sections.begin(),
e = Sections.end(); i != e; i++) {
- if (Layout.getSectionSize((*i)->MCData) > 0) {
+ if (Layout.getSectionAddressSize((*i)->MCData) > 0) {
MakeSectionReal(**i, ++Header.NumberOfSections);
} else {
(*i)->Number = -1;
TargetAsmBackend &TAB,
MCCodeEmitter &CE,
raw_ostream &OS)
- : MCObjectStreamer(Context, TAB, OS, &CE, false)
+ : MCObjectStreamer(Context, TAB, OS, &CE)
, CurSymbol(NULL) {
}