Summary: BOLT works as a series of patches rebased onto upstream LLVM at revision `f137ed238db`. Some of these patches introduce unnecessary whitespace changes or includes. Remove these to minimize the diff with upstream LLVM. Reviewed By: maksfb Differential Revision: D15064122 fbshipit-source-id: 46fcef4d2e2
2541 lines
99 KiB
Diff
2541 lines
99 KiB
Diff
diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h
|
|
index 124c2a8c86d..03af230f2e7 100644
|
|
--- a/include/llvm/ADT/BitVector.h
|
|
+++ b/include/llvm/ADT/BitVector.h
|
|
@@ -591,6 +591,11 @@ public:
|
|
return *this;
|
|
}
|
|
|
|
+ friend BitVector operator|(BitVector LHS, const BitVector &RHS) {
|
|
+ LHS |= RHS;
|
|
+ return LHS;
|
|
+ }
|
|
+
|
|
BitVector &operator^=(const BitVector &RHS) {
|
|
if (size() < RHS.size())
|
|
resize(RHS.size());
|
|
diff --git a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
|
|
index 84b23398b8c..9ed1792f0c9 100644
|
|
--- a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
|
|
+++ b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
|
|
@@ -28,12 +28,15 @@ class raw_ostream;
|
|
class DWARFAbbreviationDeclaration {
|
|
public:
|
|
struct AttributeSpec {
|
|
- AttributeSpec(dwarf::Attribute A, dwarf::Form F, int64_t Value)
|
|
- : Attr(A), Form(F), Value(Value) {
|
|
+ AttributeSpec(dwarf::Attribute A, dwarf::Form F, int64_t Value,
|
|
+ uint32_t AttrOffset = -1U, uint32_t FormOffset = -1U)
|
|
+ : Attr(A), Form(F), AttrOffset(AttrOffset), FormOffset(FormOffset),
|
|
+ Value(Value) {
|
|
assert(isImplicitConst());
|
|
}
|
|
- AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<uint8_t> ByteSize)
|
|
- : Attr(A), Form(F) {
|
|
+ AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<uint8_t> ByteSize,
|
|
+ uint32_t AttrOffset = -1U, uint32_t FormOffset = -1U)
|
|
+ : Attr(A), Form(F), AttrOffset(AttrOffset), FormOffset(FormOffset) {
|
|
assert(!isImplicitConst());
|
|
this->ByteSize.HasByteSize = ByteSize.hasValue();
|
|
if (this->ByteSize.HasByteSize)
|
|
@@ -42,6 +45,8 @@ public:
|
|
|
|
dwarf::Attribute Attr;
|
|
dwarf::Form Form;
|
|
+ uint32_t AttrOffset;
|
|
+ uint32_t FormOffset;
|
|
|
|
private:
|
|
/// The following field is used for ByteSize for non-implicit_const
|
|
@@ -112,6 +117,8 @@ public:
|
|
return AttributeSpecs[idx].Attr;
|
|
}
|
|
|
|
+ const AttributeSpec *findAttribute(dwarf::Attribute Attr) const;
|
|
+
|
|
/// Get the index of the specified attribute.
|
|
///
|
|
/// Searches the this abbreviation declaration for the index of the specified
|
|
@@ -133,7 +140,8 @@ public:
|
|
/// \returns Optional DWARF form value if the attribute was extracted.
|
|
Optional<DWARFFormValue> getAttributeValue(const uint32_t DIEOffset,
|
|
const dwarf::Attribute Attr,
|
|
- const DWARFUnit &U) const;
|
|
+ const DWARFUnit &U,
|
|
+ uint32_t *OffsetPtr = 0) const;
|
|
|
|
bool extract(DataExtractor Data, uint32_t* OffsetPtr);
|
|
void dump(raw_ostream &OS) const;
|
|
diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h
|
|
index e842cf231e7..83b0dbe0676 100644
|
|
--- a/include/llvm/DebugInfo/DWARF/DWARFContext.h
|
|
+++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h
|
|
@@ -225,6 +225,9 @@ public:
|
|
/// Get a pointer to the parsed DebugLoc object.
|
|
const DWARFDebugLoc *getDebugLoc();
|
|
|
|
+ /// Extract one location list corresponding in \p Offset
|
|
+ Optional<DWARFDebugLoc::LocationList> getOneDebugLocList(uint32_t *Offset);
|
|
+
|
|
/// Get a pointer to the parsed dwo abbreviations object.
|
|
const DWARFDebugAbbrev *getDebugAbbrevDWO();
|
|
|
|
@@ -280,6 +283,10 @@ public:
|
|
/// given address where applicable.
|
|
DIEsForAddress getDIEsForAddress(uint64_t Address);
|
|
|
|
+ /// Get offset to an attribute value within a compile unit
|
|
+ /// or 0 if the attribute was not found.
|
|
+ uint32_t getAttrFieldOffsetForUnit(DWARFUnit *U, dwarf::Attribute Attr) const;
|
|
+
|
|
DILineInfo getLineInfoForAddress(uint64_t Address,
|
|
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
|
|
DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
|
|
@@ -302,7 +309,7 @@ public:
|
|
static std::unique_ptr<DWARFContext>
|
|
create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
|
|
function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler,
|
|
- std::string DWPName = "");
|
|
+ std::string DWPName = "", bool UsesRelocs = true);
|
|
|
|
static std::unique_ptr<DWARFContext>
|
|
create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
|
|
@@ -313,7 +320,6 @@ public:
|
|
/// have initialized the relevant target descriptions.
|
|
Error loadRegisterInfo(const object::ObjectFile &Obj);
|
|
|
|
-private:
|
|
/// Return the compile unit that includes an offset (relative to .debug_info).
|
|
DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
|
|
|
|
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
|
|
index ff1c7fb3838..2622a4e7eef 100644
|
|
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
|
|
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
|
|
@@ -16,6 +16,7 @@
|
|
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
|
|
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
|
|
#include "llvm/Support/Error.h"
|
|
+#include <functional>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
@@ -279,9 +280,20 @@ public:
|
|
void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
|
|
Optional<uint64_t> Offset) const;
|
|
|
|
+ using RefHandlerType =
|
|
+ std::function<void(uint64_t, uint64_t, uint64_t)>;
|
|
+
|
|
/// Parse the section from raw data. \p Data is assumed to contain the whole
|
|
/// frame section contents to be parsed.
|
|
- void parse(DWARFDataExtractor Data);
|
|
+ /// If non-null RefHandler is passed, call it for every encountered external
|
|
+ /// reference in frame data. The expected signature is:
|
|
+ ///
|
|
+ /// void RefHandler(uint64_t Value, uint64_t Offset, uint64_t Type);
|
|
+ ///
|
|
+ /// where Value is a value of the reference, Offset - is an offset into the
|
|
+ /// frame data at which the reference occured, and Type is a DWARF encoding
|
|
+ /// type of the reference.
|
|
+ void parse(DWARFDataExtractor Data, RefHandlerType RefHandler= nullptr);
|
|
|
|
/// Return whether the section has any entries.
|
|
bool empty() const { return Entries.empty(); }
|
|
@@ -293,6 +305,12 @@ public:
|
|
return iterator_range<iterator>(Entries.begin(), Entries.end());
|
|
}
|
|
|
|
+ using FDEFunction = std::function<void(const dwarf::FDE *)>;
|
|
+
|
|
+ /// Call function F for every FDE in the frame.
|
|
+ void for_each_FDE(FDEFunction F) const;
|
|
+
|
|
+
|
|
uint64_t getEHFrameAddress() const { return EHFrameAddress; }
|
|
};
|
|
|
|
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
|
|
index a6d319a9045..39674a9d499 100644
|
|
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
|
|
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
|
|
@@ -68,6 +68,9 @@ public:
|
|
/// Return the location list at the given offset or nullptr.
|
|
LocationList const *getLocationListAtOffset(uint64_t Offset) const;
|
|
|
|
+ /// Returns the parsed location lists.
|
|
+ const LocationLists &getLocationLists() const { return Locations; }
|
|
+
|
|
Optional<LocationList> parseOneLocationList(DWARFDataExtractor Data,
|
|
uint32_t *Offset);
|
|
};
|
|
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h
|
|
index 39a3dd32c0f..84279875611 100644
|
|
--- a/include/llvm/DebugInfo/DWARF/DWARFDie.h
|
|
+++ b/include/llvm/DebugInfo/DWARF/DWARFDie.h
|
|
@@ -130,7 +130,8 @@ public:
|
|
/// \param Attr the attribute to extract.
|
|
/// \returns an optional DWARFFormValue that will have the form value if the
|
|
/// attribute was successfully extracted.
|
|
- Optional<DWARFFormValue> find(dwarf::Attribute Attr) const;
|
|
+ Optional<DWARFFormValue> find(dwarf::Attribute Attr,
|
|
+ uint32_t *OffsetPtr = 0) const;
|
|
|
|
/// Extract the first value of any attribute in Attrs from this DIE.
|
|
///
|
|
diff --git a/include/llvm/DebugInfo/DWARF/DWARFObject.h b/include/llvm/DebugInfo/DWARF/DWARFObject.h
|
|
index 795eddd1c5d..43243e70474 100644
|
|
--- a/include/llvm/DebugInfo/DWARF/DWARFObject.h
|
|
+++ b/include/llvm/DebugInfo/DWARF/DWARFObject.h
|
|
@@ -41,6 +41,7 @@ public:
|
|
virtual StringRef getARangeSection() const { return ""; }
|
|
virtual StringRef getDebugFrameSection() const { return ""; }
|
|
virtual StringRef getEHFrameSection() const { return ""; }
|
|
+ virtual uint64_t getEHFrameAddress() const { return 0; }
|
|
virtual const DWARFSection &getLineSection() const { return Dummy; }
|
|
virtual StringRef getLineStringSection() const { return ""; }
|
|
virtual StringRef getStringSection() const { return ""; }
|
|
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h
|
|
index 7932688290e..51bf4719f6c 100644
|
|
--- a/include/llvm/ExecutionEngine/ExecutionEngine.h
|
|
+++ b/include/llvm/ExecutionEngine/ExecutionEngine.h
|
|
@@ -251,6 +251,16 @@ public:
|
|
"EE!");
|
|
}
|
|
|
|
+ /// mapSectionAddress - map a section to its target address space value.
|
|
+ /// Map a JIT section with a given ID to the address in the target process
|
|
+ /// as the running code will see it. This is the address which will be used
|
|
+ /// for relocation resolution.
|
|
+ virtual void mapSectionAddress(unsigned SectionID,
|
|
+ uint64_t TargetAddress) {
|
|
+ llvm_unreachable("Re-mapping of section addresses not supported with this "
|
|
+ "EE!");
|
|
+ }
|
|
+
|
|
/// generateCodeForModule - Run code generation for the specified module and
|
|
/// load it into memory.
|
|
///
|
|
diff --git a/include/llvm/ExecutionEngine/JITSymbol.h b/include/llvm/ExecutionEngine/JITSymbol.h
|
|
index 86ab17363e1..257ed03371b 100644
|
|
--- a/include/llvm/ExecutionEngine/JITSymbol.h
|
|
+++ b/include/llvm/ExecutionEngine/JITSymbol.h
|
|
@@ -297,7 +297,17 @@ public:
|
|
/// missing. Instead, that symbol will be left out of the result map.
|
|
virtual Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) = 0;
|
|
|
|
+ /// Specify if this resolver can return valid symbols with zero value.
|
|
+ virtual void setAllowsZeroSymbols(bool Value = true) {
|
|
+ AllowsZeroSymbols = Value;
|
|
+ }
|
|
+
|
|
+ /// Return true if the resolver can return a valid symbol with zero value.
|
|
+ virtual bool allowsZeroSymbols() { return AllowsZeroSymbols; }
|
|
+
|
|
private:
|
|
+ bool AllowsZeroSymbols = false;
|
|
+
|
|
virtual void anchor();
|
|
};
|
|
|
|
diff --git a/include/llvm/ExecutionEngine/Orc/Core.h b/include/llvm/ExecutionEngine/Orc/Core.h
|
|
index 26fec8b359f..c5330034335 100644
|
|
--- a/include/llvm/ExecutionEngine/Orc/Core.h
|
|
+++ b/include/llvm/ExecutionEngine/Orc/Core.h
|
|
@@ -110,7 +110,17 @@ public:
|
|
virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
|
|
SymbolNameSet Symbols) = 0;
|
|
|
|
+ /// Specify if this resolver can return valid symbols with zero value.
|
|
+ virtual void setAllowsZeroSymbols(bool Value = true) {
|
|
+ AllowsZeroSymbols = Value;
|
|
+ }
|
|
+
|
|
+ /// Return true if the resolver can return a valid symbol with zero value.
|
|
+ virtual bool allowsZeroSymbols() { return AllowsZeroSymbols; }
|
|
+
|
|
private:
|
|
+ bool AllowsZeroSymbols = false;
|
|
+
|
|
virtual void anchor();
|
|
};
|
|
|
|
diff --git a/include/llvm/ExecutionEngine/Orc/Legacy.h b/include/llvm/ExecutionEngine/Orc/Legacy.h
|
|
index b2b389ad339..7c108ef848f 100644
|
|
--- a/include/llvm/ExecutionEngine/Orc/Legacy.h
|
|
+++ b/include/llvm/ExecutionEngine/Orc/Legacy.h
|
|
@@ -25,6 +25,10 @@ public:
|
|
JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R);
|
|
Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) override;
|
|
Expected<LookupResult> lookup(const LookupSet &Symbols) override;
|
|
+ bool allowsZeroSymbols() override { return R.allowsZeroSymbols(); }
|
|
+ void setAllowsZeroSymbols(bool Value) override {
|
|
+ R.setAllowsZeroSymbols(Value);
|
|
+ }
|
|
|
|
private:
|
|
ExecutionSession &ES;
|
|
@@ -70,11 +74,13 @@ Expected<SymbolNameSet> lookupFlagsWithLegacyFn(SymbolFlagsMap &SymbolFlags,
|
|
template <typename FindSymbolFn>
|
|
SymbolNameSet lookupWithLegacyFn(AsynchronousSymbolQuery &Query,
|
|
const SymbolNameSet &Symbols,
|
|
- FindSymbolFn FindSymbol) {
|
|
+ FindSymbolFn FindSymbol,
|
|
+ bool AllowZeroSymbols = false) {
|
|
SymbolNameSet SymbolsNotFound;
|
|
|
|
for (auto &S : Symbols) {
|
|
- if (JITSymbol Sym = FindSymbol(*S)) {
|
|
+ JITSymbol Sym = FindSymbol(*S);
|
|
+ if (Sym || (AllowZeroSymbols && !Sym.getFlags().hasError())) {
|
|
if (auto Addr = Sym.getAddress()) {
|
|
Query.setDefinition(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
|
|
Query.notifySymbolFinalized();
|
|
@@ -116,7 +122,8 @@ public:
|
|
|
|
SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
|
|
SymbolNameSet Symbols) final {
|
|
- return lookupWithLegacyFn(*Query, Symbols, LegacyLookup);
|
|
+ return lookupWithLegacyFn(*Query, Symbols, LegacyLookup,
|
|
+ this->allowsZeroSymbols());
|
|
}
|
|
|
|
private:
|
|
diff --git a/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
|
|
index cfc3922ebb5..c0b43ce8639 100644
|
|
--- a/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
|
|
+++ b/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
|
|
@@ -80,6 +80,12 @@ public:
|
|
BaseLayer.mapSectionAddress(K, LocalAddress, TargetAddr);
|
|
}
|
|
|
|
+ /// @brief Map section addresses for the objects associated with the handle H.
|
|
+ void mapSectionAddress(VModuleKey K, unsigned SectionID,
|
|
+ JITTargetAddress TargetAddr) {
|
|
+ BaseLayer.mapSectionAddress(K, SectionID, TargetAddr);
|
|
+ }
|
|
+
|
|
/// @brief Access the transform functor directly.
|
|
TransformFtor &getTransform() { return Transform; }
|
|
|
|
diff --git a/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
|
|
index 8f0d9fa6eb6..ada93a275e5 100644
|
|
--- a/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
|
|
+++ b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
|
|
@@ -62,6 +62,8 @@ protected:
|
|
|
|
virtual void mapSectionAddress(const void *LocalAddress,
|
|
JITTargetAddress TargetAddr) const = 0;
|
|
+ virtual void mapSectionAddress(unsigned SectionID,
|
|
+ JITTargetAddress TargetAddr) const = 0;
|
|
|
|
JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
|
|
auto SymEntry = SymbolTable.find(Name);
|
|
@@ -133,6 +135,9 @@ private:
|
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
|
|
PFC->RTDyld->loadObject(*PFC->Obj.getBinary());
|
|
|
|
+ if (PFC->Parent.NotifyLoaded)
|
|
+ PFC->Parent.NotifyLoaded(PFC->K, *PFC->Obj.getBinary(), *Info);
|
|
+
|
|
// Copy the symbol table out of the RuntimeDyld instance.
|
|
{
|
|
auto SymTab = PFC->RTDyld->getSymbolTable();
|
|
@@ -140,9 +145,6 @@ private:
|
|
SymbolTable[KV.first] = KV.second;
|
|
}
|
|
|
|
- if (PFC->Parent.NotifyLoaded)
|
|
- PFC->Parent.NotifyLoaded(PFC->K, *PFC->Obj.getBinary(), *Info);
|
|
-
|
|
PFC->RTDyld->finalizeWithMemoryManagerLocking();
|
|
|
|
if (PFC->RTDyld->hasError())
|
|
@@ -175,6 +177,13 @@ private:
|
|
PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
|
|
}
|
|
|
|
+ void mapSectionAddress(unsigned SectionID,
|
|
+ JITTargetAddress TargetAddr) const override {
|
|
+ assert(PFC && "mapSectionAddress called on finalized LinkedObject");
|
|
+ assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject");
|
|
+ PFC->RTDyld->mapSectionAddress(SectionID, TargetAddr);
|
|
+ }
|
|
+
|
|
private:
|
|
void buildInitialSymbolTable(const OwnedObject &Obj) {
|
|
for (auto &Symbol : Obj.getBinary()->symbols()) {
|
|
@@ -325,6 +334,13 @@ public:
|
|
LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
|
|
}
|
|
|
|
+ /// @brief Map section addresses for the objects associated with the handle H.
|
|
+ void mapSectionAddress(VModuleKey K, unsigned SectionID,
|
|
+ JITTargetAddress TargetAddr) {
|
|
+ assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
|
|
+ LinkedObjects[K]->mapSectionAddress(SectionID, TargetAddr);
|
|
+ }
|
|
+
|
|
/// @brief Immediately emit and finalize the object represented by the given
|
|
/// VModuleKey.
|
|
/// @param K VModuleKey for object to emit/finalize.
|
|
diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h
|
|
index 14da5af0206..27b02437b98 100644
|
|
--- a/include/llvm/ExecutionEngine/RuntimeDyld.h
|
|
+++ b/include/llvm/ExecutionEngine/RuntimeDyld.h
|
|
@@ -112,6 +112,14 @@ public:
|
|
StringRef SectionName,
|
|
bool IsReadOnly) = 0;
|
|
|
|
+ /// Notify that a comment/note section exists and where it's located
|
|
+ /// in case the user needs to look up extra information about the
|
|
+ /// code, e.g. debugging information.
|
|
+ virtual uint8_t *recordNoteSection(const uint8_t *Data, uintptr_t Size,
|
|
+ unsigned Alignment,
|
|
+ unsigned SectionID,
|
|
+ StringRef SectionName) { return nullptr;}
|
|
+
|
|
/// Inform the memory manager about the total amount of memory required to
|
|
/// allocate all sections to be loaded:
|
|
/// \p CodeSize - the total size of all code sections
|
|
@@ -129,6 +137,11 @@ public:
|
|
/// Override to return true to enable the reserveAllocationSpace callback.
|
|
virtual bool needsToReserveAllocationSpace() { return false; }
|
|
|
|
+ /// Override to return false to tell LLVM no stub space will be needed.
|
|
+ /// This requires some guarantees depending on architecuture, but when
|
|
+ /// you know what you are doing it saves allocated space.
|
|
+ virtual bool allowStubAllocation() const { return true; }
|
|
+
|
|
/// Register the EH frames with the runtime so that c++ exceptions work.
|
|
///
|
|
/// \p Addr parameter provides the local address of the EH frame section
|
|
@@ -205,6 +218,12 @@ public:
|
|
/// This is the address which will be used for relocation resolution.
|
|
void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress);
|
|
|
|
+ /// Map a section to its target address space value.
|
|
+ /// Map a JIT section with a given ID to the address in the target process as
|
|
+ /// the running code will see it. This is the address which will be used for
|
|
+ /// relocation resolution.
|
|
+ void mapSectionAddress(unsigned SectionID, uint64_t TargetAddress);
|
|
+
|
|
/// Register any EH frame sections that have been loaded but not previously
|
|
/// registered with the memory manager. Note, RuntimeDyld is responsible
|
|
/// for identifying the EH frame and calling the memory manager with the
|
|
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
|
|
index c538c46fc07..7b168971a3d 100644
|
|
--- a/include/llvm/MC/MCAsmInfo.h
|
|
+++ b/include/llvm/MC/MCAsmInfo.h
|
|
@@ -225,6 +225,10 @@ protected:
|
|
/// result of a alignment directive. Defaults to 0
|
|
unsigned TextAlignFillValue = 0;
|
|
|
|
+ /// If non-zero, this is used to fill the executable space with instructions
|
|
+ /// that will trap. Defaults to 0
|
|
+ unsigned TrapFillValue = 0;
|
|
+
|
|
//===--- Global Variable Emission Directives --------------------------===//
|
|
|
|
/// This is the directive used to declare a global entity. Defaults to
|
|
@@ -504,6 +508,7 @@ public:
|
|
const char *getAscizDirective() const { return AscizDirective; }
|
|
bool getAlignmentIsInBytes() const { return AlignmentIsInBytes; }
|
|
unsigned getTextAlignFillValue() const { return TextAlignFillValue; }
|
|
+ unsigned getTrapFillValue() const { return TrapFillValue; }
|
|
const char *getGlobalDirective() const { return GlobalDirective; }
|
|
|
|
bool doesSetDirectiveSuppressReloc() const {
|
|
diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h
|
|
index c110ffd3a77..a29f32091ca 100644
|
|
--- a/include/llvm/MC/MCContext.h
|
|
+++ b/include/llvm/MC/MCContext.h
|
|
@@ -506,6 +506,10 @@ namespace llvm {
|
|
return MCDwarfLineTablesCUMap;
|
|
}
|
|
|
|
+ std::map<unsigned, MCDwarfLineTable> &getMCDwarfLineTables() {
|
|
+ return MCDwarfLineTablesCUMap;
|
|
+ }
|
|
+
|
|
MCDwarfLineTable &getMCDwarfLineTable(unsigned CUID) {
|
|
return MCDwarfLineTablesCUMap[CUID];
|
|
}
|
|
@@ -552,13 +556,14 @@ namespace llvm {
|
|
/// instruction will be created.
|
|
void setCurrentDwarfLoc(unsigned FileNum, unsigned Line, unsigned Column,
|
|
unsigned Flags, unsigned Isa,
|
|
- unsigned Discriminator) {
|
|
+ unsigned Discriminator, uint64_t Addr = -1ULL) {
|
|
CurrentDwarfLoc.setFileNum(FileNum);
|
|
CurrentDwarfLoc.setLine(Line);
|
|
CurrentDwarfLoc.setColumn(Column);
|
|
CurrentDwarfLoc.setFlags(Flags);
|
|
CurrentDwarfLoc.setIsa(Isa);
|
|
CurrentDwarfLoc.setDiscriminator(Discriminator);
|
|
+ CurrentDwarfLoc.setAbsoluteAddr(Addr);
|
|
DwarfLocSeen = true;
|
|
}
|
|
|
|
diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h
|
|
index 5cdb176e8e2..cd466322894 100644
|
|
--- a/include/llvm/MC/MCDwarf.h
|
|
+++ b/include/llvm/MC/MCDwarf.h
|
|
@@ -73,6 +73,7 @@ class MCDwarfLoc {
|
|
uint8_t Flags;
|
|
uint8_t Isa;
|
|
uint32_t Discriminator;
|
|
+ uint64_t AbsoluteAddr;
|
|
|
|
// Flag that indicates the initial value of the is_stmt_start flag.
|
|
#define DWARF2_LINE_DEFAULT_IS_STMT 1
|
|
@@ -87,14 +88,17 @@ private: // MCContext manages these
|
|
friend class MCDwarfLineEntry;
|
|
|
|
MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags,
|
|
- unsigned isa, unsigned discriminator)
|
|
+ unsigned isa, unsigned discriminator, uint64_t addr=-1ULL)
|
|
: FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa),
|
|
- Discriminator(discriminator) {}
|
|
+ Discriminator(discriminator), AbsoluteAddr(addr) {}
|
|
|
|
// Allow the default copy constructor and assignment operator to be used
|
|
// for an MCDwarfLoc object.
|
|
|
|
public:
|
|
+ /// \brief Get the AbsoluteAddr of this MCDwarfLoc.
|
|
+ uint64_t getAbsoluteAddr() const { return AbsoluteAddr; }
|
|
+
|
|
/// \brief Get the FileNum of this MCDwarfLoc.
|
|
unsigned getFileNum() const { return FileNum; }
|
|
|
|
@@ -141,6 +145,11 @@ public:
|
|
void setDiscriminator(unsigned discriminator) {
|
|
Discriminator = discriminator;
|
|
}
|
|
+
|
|
+ /// \brief Set the AbsoluteAddr of this MCDwarfLoc.
|
|
+ void setAbsoluteAddr(uint64_t addr) {
|
|
+ AbsoluteAddr = addr;
|
|
+ }
|
|
};
|
|
|
|
/// \brief Instances of this class represent the line information for
|
|
@@ -274,7 +283,7 @@ public:
|
|
|
|
// This emits the Dwarf file and the line tables for a given Compile Unit.
|
|
void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params,
|
|
- Optional<MCDwarfLineStr> &LineStr) const;
|
|
+ Optional<MCDwarfLineStr> &LineStr);
|
|
|
|
Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
|
|
MD5::MD5Result *Checksum,
|
|
@@ -380,6 +389,57 @@ public:
|
|
SMLoc &Loc);
|
|
};
|
|
|
|
+/// \brief A sequence of MCDwarfOperations corresponds to a DWARF expression,
|
|
+/// used as operand in some MCCFIInstructions.
|
|
+struct MCDwarfOperation {
|
|
+ uint8_t Operation{0};
|
|
+ uint64_t Operand0{0};
|
|
+ uint64_t Operand1{0};
|
|
+
|
|
+ MCDwarfOperation(uint8_t O, uint64_t O0, uint64_t O1)
|
|
+ : Operation(O), Operand0(O0), Operand1(O1) {}
|
|
+
|
|
+ bool operator==(const MCDwarfOperation &Other) const {
|
|
+ return (Other.Operation == Operation && Other.Operand0 == Operand0 &&
|
|
+ Other.Operand1 == Operand1);
|
|
+ }
|
|
+};
|
|
+typedef std::vector<MCDwarfOperation> MCDwarfExpression;
|
|
+
|
|
+/// \brief This builder should be used to create MCDwarfExpression objects
|
|
+/// before feeding them to a CFIInstruction factory method.
|
|
+class MCDwarfExprBuilder {
|
|
+public:
|
|
+ MCDwarfExprBuilder() {}
|
|
+
|
|
+private:
|
|
+ MCDwarfExpression Expr;
|
|
+
|
|
+public:
|
|
+ MCDwarfExprBuilder &appendOperation(uint8_t Operation) {
|
|
+ Expr.push_back(MCDwarfOperation(Operation, 0, 0));
|
|
+ return *this;
|
|
+ }
|
|
+
|
|
+ MCDwarfExprBuilder &appendOperation(uint8_t Operation, uint64_t Op0) {
|
|
+ Expr.push_back(MCDwarfOperation(Operation, Op0, 0));
|
|
+ return *this;
|
|
+ }
|
|
+
|
|
+ MCDwarfExprBuilder &appendOperation(uint8_t Operation, uint64_t Op0,
|
|
+ uint64_t Op1) {
|
|
+ Expr.push_back(MCDwarfOperation(Operation, Op0, Op1));
|
|
+ return *this;
|
|
+ }
|
|
+
|
|
+ /// \brief Return the resulting expression and reset internal state
|
|
+ MCDwarfExpression take() {
|
|
+ MCDwarfExpression Res;
|
|
+ std::swap(Res, Expr);
|
|
+ return Res;
|
|
+ }
|
|
+};
|
|
+
|
|
class MCCFIInstruction {
|
|
public:
|
|
enum OpType {
|
|
@@ -397,6 +457,9 @@ public:
|
|
OpUndefined,
|
|
OpRegister,
|
|
OpWindowSave,
|
|
+ OpExpression,
|
|
+ OpDefCfaExpression,
|
|
+ OpValExpression,
|
|
OpGnuArgsSize
|
|
};
|
|
|
|
@@ -409,11 +472,13 @@ private:
|
|
unsigned Register2;
|
|
};
|
|
std::vector<char> Values;
|
|
+ MCDwarfExpression Expression;
|
|
|
|
MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V)
|
|
: Operation(Op), Label(L), Register(R), Offset(O),
|
|
Values(V.begin(), V.end()) {
|
|
- assert(Op != OpRegister);
|
|
+ assert(Op != OpRegister && Op != OpDefCfaExpression &&
|
|
+ Op != OpValExpression && Op != OpExpression);
|
|
}
|
|
|
|
MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2)
|
|
@@ -421,6 +486,20 @@ private:
|
|
assert(Op == OpRegister);
|
|
}
|
|
|
|
+ MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R,
|
|
+ const MCDwarfExpression &E)
|
|
+ : Operation(Op), Label(L), Register(R), Offset(0), Expression(E) {
|
|
+ assert(Op == OpDefCfaExpression || Op == OpValExpression ||
|
|
+ Op == OpExpression);
|
|
+ }
|
|
+
|
|
+ MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, MCDwarfExpression &&E)
|
|
+ : Operation(Op), Label(L), Register(R), Offset(0),
|
|
+ Expression(std::move(E)) {
|
|
+ assert(Op == OpDefCfaExpression || Op == OpValExpression ||
|
|
+ Op == OpExpression);
|
|
+ }
|
|
+
|
|
public:
|
|
/// \brief .cfi_def_cfa defines a rule for computing CFA as: take address from
|
|
/// Register and add Offset to it.
|
|
@@ -516,14 +595,56 @@ public:
|
|
return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
|
|
}
|
|
|
|
+ /// \brief MCCFIInstructions that refer to an expression, expression object is
|
|
+ /// created by copying
|
|
+ static MCCFIInstruction createDefCfaExpression(MCSymbol *L,
|
|
+ const MCDwarfExpression &E) {
|
|
+ return MCCFIInstruction(OpDefCfaExpression, L, 0, E);
|
|
+ }
|
|
+
|
|
+ static MCCFIInstruction createValExpression(MCSymbol *L, unsigned R,
|
|
+ const MCDwarfExpression &E) {
|
|
+ return MCCFIInstruction(OpValExpression, L, R, E);
|
|
+ }
|
|
+
|
|
+ static MCCFIInstruction createExpression(MCSymbol *L, unsigned R,
|
|
+ const MCDwarfExpression &E) {
|
|
+ return MCCFIInstruction(OpExpression, L, R, E);
|
|
+ }
|
|
+
|
|
+ /// \brief MCCFIInstructions that refer to an expression, expression object is
|
|
+ /// moved from an r-value
|
|
+ static MCCFIInstruction createDefCfaExpression(MCSymbol *L,
|
|
+ MCDwarfExpression &&E) {
|
|
+ return MCCFIInstruction(OpDefCfaExpression, L, 0, E);
|
|
+ }
|
|
+
|
|
+ static MCCFIInstruction createValExpression(MCSymbol *L, unsigned R,
|
|
+ MCDwarfExpression &&E) {
|
|
+ return MCCFIInstruction(OpValExpression, L, R, E);
|
|
+ }
|
|
+
|
|
+ static MCCFIInstruction createExpression(MCSymbol *L, unsigned R,
|
|
+ MCDwarfExpression &&E) {
|
|
+ return MCCFIInstruction(OpExpression, L, R, E);
|
|
+ }
|
|
+
|
|
+ bool operator==(const MCCFIInstruction &Other) const {
|
|
+ return (Other.Operation == Operation && Other.Label == Label &&
|
|
+ Other.Offset == Offset && Other.Register == Register &&
|
|
+ Other.Expression == Expression);
|
|
+ }
|
|
+
|
|
OpType getOperation() const { return Operation; }
|
|
MCSymbol *getLabel() const { return Label; }
|
|
+ void setLabel(MCSymbol *L) { Label = L; }
|
|
|
|
unsigned getRegister() const {
|
|
assert(Operation == OpDefCfa || Operation == OpOffset ||
|
|
Operation == OpRestore || Operation == OpUndefined ||
|
|
Operation == OpSameValue || Operation == OpDefCfaRegister ||
|
|
- Operation == OpRelOffset || Operation == OpRegister);
|
|
+ Operation == OpRelOffset || Operation == OpRegister ||
|
|
+ Operation == OpExpression || Operation == OpValExpression);
|
|
return Register;
|
|
}
|
|
|
|
@@ -539,6 +660,33 @@ public:
|
|
return Offset;
|
|
}
|
|
|
|
+ void setOffset(int NewOffset) {
|
|
+ assert(Operation == OpDefCfa || Operation == OpOffset ||
|
|
+ Operation == OpRelOffset || Operation == OpDefCfaOffset ||
|
|
+ Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize);
|
|
+ Offset = NewOffset;
|
|
+ }
|
|
+
|
|
+ void setRegister(unsigned NewReg) {
|
|
+ assert(Operation == OpDefCfa || Operation == OpOffset ||
|
|
+ Operation == OpRestore || Operation == OpUndefined ||
|
|
+ Operation == OpSameValue || Operation == OpDefCfaRegister ||
|
|
+ Operation == OpRelOffset || Operation == OpRegister ||
|
|
+ Operation == OpExpression || Operation == OpValExpression);
|
|
+ Register = NewReg;
|
|
+ }
|
|
+
|
|
+ void setRegister2(unsigned NewReg) {
|
|
+ assert(Operation == OpRegister);
|
|
+ Register2 = NewReg;
|
|
+ }
|
|
+
|
|
+ const MCDwarfExpression &getExpression() const {
|
|
+ assert(Operation == OpDefCfaExpression || Operation == OpExpression ||
|
|
+ Operation == OpValExpression);
|
|
+ return Expression;
|
|
+ }
|
|
+
|
|
StringRef getValues() const {
|
|
assert(Operation == OpEscape);
|
|
return StringRef(&Values[0], Values.size());
|
|
diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h
|
|
index fcbbe650d26..25847aa2946 100644
|
|
--- a/include/llvm/MC/MCExpr.h
|
|
+++ b/include/llvm/MC/MCExpr.h
|
|
@@ -123,6 +123,9 @@ public:
|
|
/// expression.
|
|
MCFragment *findAssociatedFragment() const;
|
|
|
|
+ /// Helper method that returns the Symbol of an MCSymbolRef Expression.
|
|
+ const MCSymbol &getSymbol() const;
|
|
+
|
|
/// @}
|
|
};
|
|
|
|
diff --git a/include/llvm/MC/MCFragment.h b/include/llvm/MC/MCFragment.h
|
|
index 38c365538e3..dec295707e9 100644
|
|
--- a/include/llvm/MC/MCFragment.h
|
|
+++ b/include/llvm/MC/MCFragment.h
|
|
@@ -34,6 +34,7 @@ class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
|
|
public:
|
|
enum FragmentType : uint8_t {
|
|
FT_Align,
|
|
+ FT_NeverAlign,
|
|
FT_Data,
|
|
FT_CompactEncodedInst,
|
|
FT_Fill,
|
|
@@ -325,6 +326,46 @@ public:
|
|
}
|
|
};
|
|
|
|
+class MCNeverAlignFragment : public MCFragment {
|
|
+ /// Alignment - The alignment the end of the next fragment should avoid
|
|
+ unsigned Alignment;
|
|
+
|
|
+ /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead
|
|
+ /// of using the provided value. The exact interpretation of this flag is
|
|
+ /// target dependent.
|
|
+ bool EmitNops : 1;
|
|
+
|
|
+ /// Value - Value to use for filling padding bytes.
|
|
+ int64_t Value;
|
|
+
|
|
+ /// ValueSize - The size of the integer (in bytes) of \p Value.
|
|
+ unsigned ValueSize;
|
|
+
|
|
+ public:
|
|
+ MCNeverAlignFragment(unsigned Alignment,
|
|
+ int64_t Value, unsigned ValueSize, MCSection *Sec = nullptr)
|
|
+ : MCFragment(FT_NeverAlign, false, 0, Sec), Alignment(Alignment),
|
|
+ EmitNops(false), Value(Value), ValueSize(ValueSize) {}
|
|
+
|
|
+ /// \name Accessors
|
|
+ /// @{
|
|
+
|
|
+ unsigned getAlignment() const { return Alignment; }
|
|
+
|
|
+ int64_t getValue() const { return Value; }
|
|
+
|
|
+ unsigned getValueSize() const { return ValueSize; }
|
|
+
|
|
+ bool hasEmitNops() const { return EmitNops; }
|
|
+ void setEmitNops(bool Value) { EmitNops = Value; }
|
|
+
|
|
+ /// @}
|
|
+
|
|
+ static bool classof(const MCFragment *F) {
|
|
+ return F->getKind() == MCFragment::FT_NeverAlign;
|
|
+ }
|
|
+};
|
|
+
|
|
/// Fragment for adding required padding.
|
|
/// This fragment is always inserted before an instruction, and holds that
|
|
/// instruction as context information (as well as a mask of kinds) for
|
|
diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h
|
|
index db28fd0fd6d..e136a10b264 100644
|
|
--- a/include/llvm/MC/MCInst.h
|
|
+++ b/include/llvm/MC/MCInst.h
|
|
@@ -187,7 +187,7 @@ public:
|
|
using const_iterator = SmallVectorImpl<MCOperand>::const_iterator;
|
|
|
|
void clear() { Operands.clear(); }
|
|
- void erase(iterator I) { Operands.erase(I); }
|
|
+ iterator erase(iterator I) { return Operands.erase(I); }
|
|
size_t size() const { return Operands.size(); }
|
|
iterator begin() { return Operands.begin(); }
|
|
const_iterator begin() const { return Operands.begin(); }
|
|
diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h
|
|
index c99f2521f8f..e6b4a88f469 100644
|
|
--- a/include/llvm/MC/MCObjectFileInfo.h
|
|
+++ b/include/llvm/MC/MCObjectFileInfo.h
|
|
@@ -65,6 +65,9 @@ protected:
|
|
/// constants.
|
|
MCSection *ReadOnlySection;
|
|
|
|
+ /// Same as the above but for infrequently used data.
|
|
+ MCSection *ReadOnlyColdSection;
|
|
+
|
|
/// If exception handling is supported by the target, this is the section the
|
|
/// Language Specific Data Area information is emitted to.
|
|
MCSection *LSDASection;
|
|
@@ -230,6 +233,7 @@ public:
|
|
MCSection *getDataSection() const { return DataSection; }
|
|
MCSection *getBSSSection() const { return BSSSection; }
|
|
MCSection *getReadOnlySection() const { return ReadOnlySection; }
|
|
+ MCSection *getReadOnlyColdSection() const { return ReadOnlyColdSection; }
|
|
MCSection *getLSDASection() const { return LSDASection; }
|
|
MCSection *getCompactUnwindSection() const { return CompactUnwindSection; }
|
|
MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; }
|
|
diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h
|
|
index 8e9b4ac5632..d2c569e3399 100644
|
|
--- a/include/llvm/MC/MCObjectStreamer.h
|
|
+++ b/include/llvm/MC/MCObjectStreamer.h
|
|
@@ -121,6 +121,8 @@ public:
|
|
unsigned MaxBytesToEmit = 0) override;
|
|
void EmitCodeAlignment(unsigned ByteAlignment,
|
|
unsigned MaxBytesToEmit = 0) override;
|
|
+ void EmitNeverAlignCodeAtEnd(unsigned ByteAlignment, int64_t Value = 0,
|
|
+ unsigned ValueSize = 1) override;
|
|
void emitValueToOffset(const MCExpr *Offset, unsigned char Value,
|
|
SMLoc Loc) override;
|
|
void
|
|
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
|
|
index 582a836023b..f1e341bd624 100644
|
|
--- a/include/llvm/MC/MCStreamer.h
|
|
+++ b/include/llvm/MC/MCStreamer.h
|
|
@@ -199,7 +199,7 @@ class MCStreamer {
|
|
|
|
/// \brief Tracks an index to represent the order a symbol was emitted in.
|
|
/// Zero means we did not emit that symbol.
|
|
- DenseMap<const MCSymbol *, unsigned> SymbolOrdering;
|
|
+ unsigned SymbolOrdering = 1;
|
|
|
|
/// \brief This is stack of current and previous section values saved by
|
|
/// PushSection.
|
|
@@ -338,9 +338,7 @@ public:
|
|
|
|
/// \brief Returns an index to represent the order a symbol was emitted in.
|
|
/// (zero if we did not emit that symbol)
|
|
- unsigned GetSymbolOrder(const MCSymbol *Sym) const {
|
|
- return SymbolOrdering.lookup(Sym);
|
|
- }
|
|
+ unsigned GetSymbolOrder(const MCSymbol *Sym) const;
|
|
|
|
/// \brief Update streamer for a new active section.
|
|
///
|
|
@@ -608,6 +606,10 @@ public:
|
|
|
|
virtual void EmitSLEB128Value(const MCExpr *Value);
|
|
|
|
+ /// \brief Like EmitULEB128Value but pads the output to specific number of
|
|
+ /// bytes.
|
|
+ void EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo);
|
|
+
|
|
/// \brief Special case of EmitULEB128Value that avoids the client having to
|
|
/// pass in a MCExpr for constant integers.
|
|
void EmitULEB128IntValue(uint64_t Value);
|
|
@@ -726,6 +728,12 @@ public:
|
|
virtual void EmitCodeAlignment(unsigned ByteAlignment,
|
|
unsigned MaxBytesToEmit = 0);
|
|
|
|
+ /// \brief If the end of the following fragment ever gets aligned to
|
|
+ /// \p ByteAlignment, emit a single nop or \t Value to break this alignment.
|
|
+ virtual void EmitNeverAlignCodeAtEnd(unsigned ByteAlignment,
|
|
+ int64_t Value = 0,
|
|
+ unsigned ValueSize = 1);
|
|
+
|
|
/// \brief Emit some number of copies of \p Value until the byte offset \p
|
|
/// Offset is reached.
|
|
///
|
|
@@ -904,6 +912,8 @@ public:
|
|
|
|
virtual void EmitSyntaxDirective();
|
|
|
|
+ virtual void EmitCFIInstruction(const MCCFIInstruction &Inst);
|
|
+
|
|
/// \brief Emit a .reloc directive.
|
|
/// Returns true if the relocation could not be emitted because Name is not
|
|
/// known.
|
|
diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h
|
|
index cc8fc02968a..7b7835e83d8 100644
|
|
--- a/include/llvm/MC/MCSymbol.h
|
|
+++ b/include/llvm/MC/MCSymbol.h
|
|
@@ -120,10 +120,15 @@ protected:
|
|
|
|
/// The Flags field is used by object file implementations to store
|
|
/// additional per symbol information which is not easily classified.
|
|
- enum : unsigned { NumFlagsBits = 16 };
|
|
+ enum : unsigned { NumFlagsBits = 15 };
|
|
mutable uint32_t Flags : NumFlagsBits;
|
|
|
|
- /// Index field, for use by the object file implementation.
|
|
+ /// Indicates if the next field is used for Index or Order.
|
|
+ mutable bool IsIndex : 1;
|
|
+
|
|
+ /// Index field for use by the object file implementation. It is also used to
|
|
+ /// represent order of the symbol. The semantics of the current value is
|
|
+ /// indicated by IsIndex field.
|
|
mutable uint32_t Index = 0;
|
|
|
|
union {
|
|
@@ -154,7 +159,7 @@ protected:
|
|
: IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false),
|
|
IsRegistered(false), IsExternal(false), IsPrivateExtern(false),
|
|
Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset),
|
|
- CommonAlignLog2(0), Flags(0) {
|
|
+ CommonAlignLog2(0), Flags(0), IsIndex{false} {
|
|
Offset = 0;
|
|
FragmentAndHasName.setInt(!!Name);
|
|
if (Name)
|
|
@@ -308,11 +313,27 @@ public:
|
|
|
|
/// Get the (implementation defined) index.
|
|
uint32_t getIndex() const {
|
|
+ assert(IsIndex && "Index unavailable");
|
|
return Index;
|
|
}
|
|
|
|
/// Set the (implementation defined) index.
|
|
void setIndex(uint32_t Value) const {
|
|
+ assert((IsIndex = true, true) && "assertion-specific code");
|
|
+ Index = Value;
|
|
+ }
|
|
+
|
|
+ bool hasIndex() const { return IsIndex; }
|
|
+
|
|
+ /// Get the (implementation defined) order.
|
|
+ uint32_t getOrder() const {
|
|
+ assert(!IsIndex && "Order unavailable");
|
|
+ return Index;
|
|
+ }
|
|
+
|
|
+ /// Set the (implementation defined) order.
|
|
+ void setOrder(uint32_t Value) const {
|
|
+ assert((IsIndex = false, true) && "assertion-specific code");
|
|
Index = Value;
|
|
}
|
|
|
|
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
|
|
index 9190149f382..25646fe0241 100644
|
|
--- a/include/llvm/Object/COFF.h
|
|
+++ b/include/llvm/Object/COFF.h
|
|
@@ -899,6 +899,7 @@ protected:
|
|
bool isSectionData(DataRefImpl Sec) const override;
|
|
bool isSectionBSS(DataRefImpl Sec) const override;
|
|
bool isSectionVirtual(DataRefImpl Sec) const override;
|
|
+ bool isSectionReadOnly(DataRefImpl Sec) const override;
|
|
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
|
|
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
|
|
|
|
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
|
|
index 46504e74bc2..836fd8ddc45 100644
|
|
--- a/include/llvm/Object/ELF.h
|
|
+++ b/include/llvm/Object/ELF.h
|
|
@@ -127,6 +127,18 @@ public:
|
|
getHeader()->getDataEncoding() == ELF::ELFDATA2LSB;
|
|
}
|
|
|
|
+ Expected<const Elf_Dyn *> dynamic_table_begin(const Elf_Phdr *Phdr) const;
|
|
+ Expected<const Elf_Dyn *> dynamic_table_end(const Elf_Phdr *Phdr) const;
|
|
+ Expected<Elf_Dyn_Range> dynamic_table(const Elf_Phdr *Phdr) const {
|
|
+ Expected<const Elf_Dyn *> Begin = dynamic_table_begin(Phdr);
|
|
+ if (!Begin)
|
|
+ return Begin.takeError();
|
|
+ Expected<const Elf_Dyn *> End = dynamic_table_end(Phdr);
|
|
+ if (!End)
|
|
+ return End.takeError();
|
|
+ return makeArrayRef(Begin.get(), End.get());
|
|
+ }
|
|
+
|
|
Expected<Elf_Shdr_Range> sections() const;
|
|
|
|
Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const {
|
|
@@ -397,6 +409,34 @@ void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type,
|
|
}
|
|
|
|
template <class ELFT>
|
|
+Expected<const typename ELFFile<ELFT>::Elf_Dyn *>
|
|
+ELFFile<ELFT>::dynamic_table_begin(const Elf_Phdr *Phdr) const {
|
|
+ if (!Phdr)
|
|
+ return nullptr;
|
|
+ assert(Phdr->p_type == ELF::PT_DYNAMIC && "Got the wrong program header");
|
|
+ uintX_t Offset = Phdr->p_offset;
|
|
+ if (Offset > Buf.size())
|
|
+ return make_error<GenericBinaryError>("Could not read dynamic table");
|
|
+ return reinterpret_cast<const Elf_Dyn *>(base() + Offset);
|
|
+}
|
|
+
|
|
+template <class ELFT>
|
|
+Expected<const typename ELFFile<ELFT>::Elf_Dyn *>
|
|
+ELFFile<ELFT>::dynamic_table_end(const Elf_Phdr *Phdr) const {
|
|
+ if (!Phdr)
|
|
+ return nullptr;
|
|
+ assert(Phdr->p_type == ELF::PT_DYNAMIC && "Got the wrong program header");
|
|
+ uintX_t Size = Phdr->p_filesz;
|
|
+ if (Size % sizeof(Elf_Dyn))
|
|
+ return make_error<GenericBinaryError>("Invalid dynamic table size");
|
|
+ // FIKME: Check for overflow?
|
|
+ uintX_t End = Phdr->p_offset + Size;
|
|
+ if (End > Buf.size())
|
|
+ return make_error<GenericBinaryError>("Could not read dynamic table");
|
|
+ return reinterpret_cast<const Elf_Dyn *>(base() + End);
|
|
+}
|
|
+
|
|
+template <class ELFT>
|
|
Expected<const typename ELFT::Sym *>
|
|
ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel,
|
|
const Elf_Shdr *SymTab) const {
|
|
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
|
|
index 4d001039238..62837bbcaa0 100644
|
|
--- a/include/llvm/Object/ELFObjectFile.h
|
|
+++ b/include/llvm/Object/ELFObjectFile.h
|
|
@@ -254,6 +254,7 @@ protected:
|
|
bool isSectionData(DataRefImpl Sec) const override;
|
|
bool isSectionBSS(DataRefImpl Sec) const override;
|
|
bool isSectionVirtual(DataRefImpl Sec) const override;
|
|
+ bool isSectionReadOnly(DataRefImpl Sec) const override;
|
|
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
|
|
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
|
|
section_iterator getRelocatedSection(DataRefImpl Sec) const override;
|
|
@@ -717,6 +718,14 @@ bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const {
|
|
}
|
|
|
|
template <class ELFT>
|
|
+bool ELFObjectFile<ELFT>::isSectionReadOnly(DataRefImpl Sec) const {
|
|
+ const Elf_Shdr *EShdr = getSection(Sec);
|
|
+ return EShdr->sh_flags & ELF::SHF_ALLOC &&
|
|
+ !(EShdr->sh_flags & ELF::SHF_WRITE) &&
|
|
+ EShdr->sh_type == ELF::SHT_PROGBITS;
|
|
+}
|
|
+
|
|
+template <class ELFT>
|
|
relocation_iterator
|
|
ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const {
|
|
DataRefImpl RelData;
|
|
@@ -751,9 +760,6 @@ ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const {
|
|
template <class ELFT>
|
|
section_iterator
|
|
ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
|
|
- if (EF.getHeader()->e_type != ELF::ET_REL)
|
|
- return section_end();
|
|
-
|
|
const Elf_Shdr *EShdr = getSection(Sec);
|
|
uintX_t Type = EShdr->sh_type;
|
|
if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA)
|
|
@@ -762,6 +768,9 @@ ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
|
|
auto R = EF.getSection(EShdr->sh_info);
|
|
if (!R)
|
|
report_fatal_error(errorToErrorCode(R.takeError()).message());
|
|
+ if (EF.getHeader()->e_type != ELF::ET_REL &&
|
|
+ !((*R)->sh_flags & ELF::SHF_ALLOC))
|
|
+ return section_end();
|
|
return section_iterator(SectionRef(toDRI(*R), this));
|
|
}
|
|
|
|
@@ -792,8 +801,6 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
|
|
|
|
template <class ELFT>
|
|
uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const {
|
|
- assert(EF.getHeader()->e_type == ELF::ET_REL &&
|
|
- "Only relocatable object files have relocation offsets");
|
|
const Elf_Shdr *sec = getRelSection(Rel);
|
|
if (sec->sh_type == ELF::SHT_REL)
|
|
return getRel(Rel)->r_offset;
|
|
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
|
|
index bfd3462bf69..52bc210b577 100644
|
|
--- a/include/llvm/Object/MachO.h
|
|
+++ b/include/llvm/Object/MachO.h
|
|
@@ -320,6 +320,7 @@ public:
|
|
/// from offset 0 (i.e. the Mach-O header at the beginning of the file).
|
|
bool isSectionStripped(DataRefImpl Sec) const override;
|
|
|
|
+ bool isSectionReadOnly(DataRefImpl Sec) const override;
|
|
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
|
|
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
|
|
|
|
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
|
|
index 9c4ae94d3a6..64342723371 100644
|
|
--- a/include/llvm/Object/ObjectFile.h
|
|
+++ b/include/llvm/Object/ObjectFile.h
|
|
@@ -110,6 +110,7 @@ public:
|
|
bool isVirtual() const;
|
|
bool isBitcode() const;
|
|
bool isStripped() const;
|
|
+ bool isReadOnly() const;
|
|
|
|
bool containsSymbol(SymbolRef S) const;
|
|
|
|
@@ -238,6 +239,7 @@ protected:
|
|
virtual bool isSectionVirtual(DataRefImpl Sec) const = 0;
|
|
virtual bool isSectionBitcode(DataRefImpl Sec) const;
|
|
virtual bool isSectionStripped(DataRefImpl Sec) const;
|
|
+ virtual bool isSectionReadOnly(DataRefImpl Sec) const = 0;
|
|
virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0;
|
|
virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0;
|
|
virtual section_iterator getRelocatedSection(DataRefImpl Sec) const;
|
|
@@ -442,6 +444,10 @@ inline bool SectionRef::isStripped() const {
|
|
return OwningObject->isSectionStripped(SectionPimpl);
|
|
}
|
|
|
|
+inline bool SectionRef::isReadOnly() const {
|
|
+ return OwningObject->isSectionReadOnly(SectionPimpl);
|
|
+}
|
|
+
|
|
inline relocation_iterator SectionRef::relocation_begin() const {
|
|
return OwningObject->section_rel_begin(SectionPimpl);
|
|
}
|
|
diff --git a/include/llvm/Object/Wasm.h b/include/llvm/Object/Wasm.h
|
|
index d49acf3a38a..5929a22e1f3 100644
|
|
--- a/include/llvm/Object/Wasm.h
|
|
+++ b/include/llvm/Object/Wasm.h
|
|
@@ -177,6 +177,7 @@ public:
|
|
bool isSectionText(DataRefImpl Sec) const override;
|
|
bool isSectionData(DataRefImpl Sec) const override;
|
|
bool isSectionBSS(DataRefImpl Sec) const override;
|
|
+ bool isSectionReadOnly(DataRefImpl Sec) const override;
|
|
bool isSectionVirtual(DataRefImpl Sec) const override;
|
|
bool isSectionBitcode(DataRefImpl Sec) const override;
|
|
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
|
|
diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h
|
|
index 7fd5f20ee4e..2a47ef1bfdb 100644
|
|
--- a/include/llvm/Support/ToolOutputFile.h
|
|
+++ b/include/llvm/Support/ToolOutputFile.h
|
|
@@ -46,7 +46,7 @@ public:
|
|
/// This constructor's arguments are passed to raw_fd_ostream's
|
|
/// constructor.
|
|
ToolOutputFile(StringRef Filename, std::error_code &EC,
|
|
- sys::fs::OpenFlags Flags);
|
|
+ sys::fs::OpenFlags Flags, unsigned Mode = 0666);
|
|
|
|
ToolOutputFile(StringRef Filename, int FD);
|
|
|
|
diff --git a/include/llvm/Support/X86DisassemblerDecoderCommon.h b/include/llvm/Support/X86DisassemblerDecoderCommon.h
|
|
index eeffb9c0167..2ec249671eb 100644
|
|
--- a/include/llvm/Support/X86DisassemblerDecoderCommon.h
|
|
+++ b/include/llvm/Support/X86DisassemblerDecoderCommon.h
|
|
@@ -62,7 +62,8 @@ namespace X86Disassembler {
|
|
ENUM_ENTRY(ATTR_EVEXL2, (0x1 << 10)) \
|
|
ENUM_ENTRY(ATTR_EVEXK, (0x1 << 11)) \
|
|
ENUM_ENTRY(ATTR_EVEXKZ, (0x1 << 12)) \
|
|
- ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13))
|
|
+ ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13)) \
|
|
+ ENUM_ENTRY(ATTR_3DNOW, (0x1 << 14))
|
|
|
|
#define ENUM_ENTRY(n, v) n = v,
|
|
enum attributeBits {
|
|
@@ -272,7 +273,8 @@ enum attributeBits {
|
|
ENUM_ENTRY(IC_EVEX_L2_W_KZ, 3, "requires EVEX_KZ, L2 and W") \
|
|
ENUM_ENTRY(IC_EVEX_L2_W_XS_KZ, 4, "requires EVEX_KZ, L2, W and XS prefix") \
|
|
ENUM_ENTRY(IC_EVEX_L2_W_XD_KZ, 4, "requires EVEX_KZ, L2, W and XD prefix") \
|
|
- ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, W and OpSize")
|
|
+ ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, W and OpSize") \
|
|
+ ENUM_ENTRY(IC_3DNOW, 8, "requires AMD 3DNow prefix 0f0f")
|
|
|
|
#define ENUM_ENTRY(n, r, d) n,
|
|
enum InstructionContext {
|
|
diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h
|
|
index d11f5a83779..0ad115c886b 100644
|
|
--- a/include/llvm/Support/raw_ostream.h
|
|
+++ b/include/llvm/Support/raw_ostream.h
|
|
@@ -393,7 +393,7 @@ public:
|
|
/// STDOUT_FILENO instead of opening a file. This will not close the stdout
|
|
/// descriptor.
|
|
raw_fd_ostream(StringRef Filename, std::error_code &EC,
|
|
- sys::fs::OpenFlags Flags);
|
|
+ sys::fs::OpenFlags Flags, unsigned Mode = 0666);
|
|
|
|
/// FD is the file descriptor that this writes to. If ShouldClose is true,
|
|
/// this closes the file when the stream is destroyed. If FD is for stdout or
|
|
diff --git a/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
|
|
index adada672af0..b3d68ed66af 100644
|
|
--- a/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
|
|
+++ b/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
|
|
@@ -61,13 +61,15 @@ DWARFAbbreviationDeclaration::extract(DataExtractor Data,
|
|
|
|
// Read all of the abbreviation attributes and forms.
|
|
while (true) {
|
|
+ uint32_t AOff = *OffsetPtr;
|
|
auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr));
|
|
+ uint32_t FOff = *OffsetPtr;
|
|
auto F = static_cast<Form>(Data.getULEB128(OffsetPtr));
|
|
if (A && F) {
|
|
bool IsImplicitConst = (F == DW_FORM_implicit_const);
|
|
if (IsImplicitConst) {
|
|
int64_t V = Data.getSLEB128(OffsetPtr);
|
|
- AttributeSpecs.push_back(AttributeSpec(A, F, V));
|
|
+ AttributeSpecs.push_back(AttributeSpec(A, F, V, AOff, FOff));
|
|
continue;
|
|
}
|
|
Optional<uint8_t> ByteSize;
|
|
@@ -109,7 +111,7 @@ DWARFAbbreviationDeclaration::extract(DataExtractor Data,
|
|
break;
|
|
}
|
|
// Record this attribute and its fixed size if it has one.
|
|
- AttributeSpecs.push_back(AttributeSpec(A, F, ByteSize));
|
|
+ AttributeSpecs.push_back(AttributeSpec(A, F, ByteSize, AOff, FOff));
|
|
} else if (A == 0 && F == 0) {
|
|
// We successfully reached the end of this abbreviation declaration
|
|
// since both attribute and form are zero.
|
|
@@ -139,6 +141,15 @@ void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
|
|
OS << '\n';
|
|
}
|
|
|
|
+const DWARFAbbreviationDeclaration::AttributeSpec *
|
|
+DWARFAbbreviationDeclaration::findAttribute(dwarf::Attribute Attr) const {
|
|
+ for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) {
|
|
+ if (AttributeSpecs[i].Attr == Attr)
|
|
+ return &AttributeSpecs[i];
|
|
+ }
|
|
+ return nullptr;
|
|
+}
|
|
+
|
|
Optional<uint32_t>
|
|
DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const {
|
|
for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) {
|
|
@@ -150,7 +161,7 @@ DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const {
|
|
|
|
Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue(
|
|
const uint32_t DIEOffset, const dwarf::Attribute Attr,
|
|
- const DWARFUnit &U) const {
|
|
+ const DWARFUnit &U, uint32_t *OffsetPtr) const {
|
|
Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr);
|
|
if (!MatchAttrIndex)
|
|
return None;
|
|
@@ -164,6 +175,8 @@ Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue(
|
|
for (const auto &Spec : AttributeSpecs) {
|
|
if (*MatchAttrIndex == AttrIndex) {
|
|
// We have arrived at the attribute to extract, extract if from Offset.
|
|
+ if (OffsetPtr)
|
|
+ *OffsetPtr = Offset;
|
|
DWARFFormValue FormValue(Spec.Form);
|
|
if (Spec.isImplicitConst()) {
|
|
FormValue.setSValue(Spec.getImplicitConstValue());
|
|
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp
|
|
index 3a974dddc4e..65bd4a69db8 100644
|
|
--- a/lib/DebugInfo/DWARF/DWARFContext.cpp
|
|
+++ b/lib/DebugInfo/DWARF/DWARFContext.cpp
|
|
@@ -681,6 +681,15 @@ const DWARFDebugLoc *DWARFContext::getDebugLoc() {
|
|
return Loc.get();
|
|
}
|
|
|
|
+Optional<DWARFDebugLoc::LocationList>
|
|
+DWARFContext::getOneDebugLocList(uint32_t *Offset) {
|
|
+ DWARFDebugLoc L;
|
|
+ DWARFDataExtractor LocData(*DObj, DObj->getLocSection(), isLittleEndian(),
|
|
+ getCompileUnitAtIndex(0)->getAddressByteSize());
|
|
+
|
|
+ return L.parseOneLocationList(LocData, Offset);
|
|
+}
|
|
+
|
|
const DWARFDebugLocDWO *DWARFContext::getDebugLocDWO() {
|
|
if (LocDWO)
|
|
return LocDWO.get();
|
|
@@ -726,7 +735,8 @@ const DWARFDebugFrame *DWARFContext::getEHFrame() {
|
|
|
|
DWARFDataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(),
|
|
DObj->getAddressSize());
|
|
- DebugFrame.reset(new DWARFDebugFrame(true /* IsEH */));
|
|
+ DebugFrame.reset(
|
|
+ new DWARFDebugFrame(true /* IsEH */, DObj->getEHFrameAddress()));
|
|
DebugFrame->parse(debugFrameData);
|
|
return DebugFrame.get();
|
|
}
|
|
@@ -809,6 +819,19 @@ DWARFContext::getLineTableForUnit(DWARFUnit *U) {
|
|
return Line->getOrParseLineTable(lineData, stmtOffset, *this, U);
|
|
}
|
|
|
|
+uint32_t DWARFContext::getAttrFieldOffsetForUnit(DWARFUnit *U,
|
|
+ dwarf::Attribute Attr) const {
|
|
+ const auto UnitDIE = U->getUnitDIE();
|
|
+ if (!UnitDIE)
|
|
+ return 0;
|
|
+
|
|
+ uint32_t Offset = 0;
|
|
+ if (!UnitDIE.find(Attr, &Offset))
|
|
+ return 0;
|
|
+
|
|
+ return Offset;
|
|
+}
|
|
+
|
|
void DWARFContext::parseCompileUnits() {
|
|
CUs.parse(*this, DObj->getInfoSection());
|
|
}
|
|
@@ -1244,6 +1267,9 @@ class DWARFObjInMemory final : public DWARFObject {
|
|
|
|
SmallVector<SmallString<32>, 4> UncompressedSections;
|
|
|
|
+ uint64_t EHFrameAddress{0};
|
|
+ bool UsesRelocs{true};
|
|
+
|
|
StringRef *mapSectionToMember(StringRef Name) {
|
|
if (DWARFSection *Sec = mapNameToDWARFSection(Name))
|
|
return &Sec->Data;
|
|
@@ -1300,10 +1326,11 @@ public:
|
|
}
|
|
}
|
|
DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
|
|
- function_ref<ErrorPolicy(Error)> HandleError)
|
|
+ function_ref<ErrorPolicy(Error)> HandleError,
|
|
+ bool UsesRelocs = true)
|
|
: IsLittleEndian(Obj.isLittleEndian()),
|
|
AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()),
|
|
- Obj(&Obj) {
|
|
+ Obj(&Obj), UsesRelocs(UsesRelocs) {
|
|
|
|
StringMap<unsigned> SectionAmountMap;
|
|
for (const SectionRef &Section : Obj.sections()) {
|
|
@@ -1350,6 +1377,8 @@ public:
|
|
if (Name == "debug_ranges") {
|
|
// FIXME: Use the other dwo range section when we emit it.
|
|
RangeDWOSection.Data = Data;
|
|
+ } else if (Name == "eh_frame") {
|
|
+ EHFrameAddress = Section.getAddress();
|
|
}
|
|
} else if (Name == "debug_types") {
|
|
// Find debug_types data by section rather than name as there are
|
|
@@ -1402,7 +1431,7 @@ public:
|
|
continue;
|
|
}
|
|
|
|
- if (Section.relocation_begin() == Section.relocation_end())
|
|
+ if (Section.relocation_begin() == Section.relocation_end() || !UsesRelocs)
|
|
continue;
|
|
|
|
// Symbol to [address, section index] cache mapping.
|
|
@@ -1445,6 +1474,8 @@ public:
|
|
|
|
Optional<RelocAddrEntry> find(const DWARFSection &S,
|
|
uint64_t Pos) const override {
|
|
+ if (!UsesRelocs)
|
|
+ return None;
|
|
auto &Sec = static_cast<const DWARFSectionMap &>(S);
|
|
RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos);
|
|
if (AI == Sec.Relocs.end())
|
|
@@ -1499,6 +1530,7 @@ public:
|
|
StringRef getARangeSection() const override { return ARangeSection; }
|
|
StringRef getDebugFrameSection() const override { return DebugFrameSection; }
|
|
StringRef getEHFrameSection() const override { return EHFrameSection; }
|
|
+ uint64_t getEHFrameAddress() const override { return EHFrameAddress; }
|
|
const DWARFSection &getLineSection() const override { return LineSection; }
|
|
StringRef getStringSection() const override { return StringSection; }
|
|
const DWARFSection &getRangeSection() const override { return RangeSection; }
|
|
@@ -1544,8 +1576,9 @@ public:
|
|
std::unique_ptr<DWARFContext>
|
|
DWARFContext::create(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
|
|
function_ref<ErrorPolicy(Error)> HandleError,
|
|
- std::string DWPName) {
|
|
- auto DObj = llvm::make_unique<DWARFObjInMemory>(Obj, L, HandleError);
|
|
+ std::string DWPName, bool UsesRelocs) {
|
|
+ auto DObj =
|
|
+ llvm::make_unique<DWARFObjInMemory>(Obj, L, HandleError, UsesRelocs);
|
|
return llvm::make_unique<DWARFContext>(std::move(DObj), std::move(DWPName));
|
|
}
|
|
|
|
diff --git a/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp b/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
|
|
index 03e31746139..0436778e2e4 100644
|
|
--- a/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
|
|
+++ b/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
|
|
@@ -7,6 +7,7 @@
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
+#include "llvm/BinaryFormat/Dwarf.h"
|
|
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
|
|
#include "llvm/BinaryFormat/Dwarf.h"
|
|
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
|
diff --git a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
|
|
index b9dc2151e06..f3c7c81bb10 100644
|
|
--- a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
|
|
+++ b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
|
|
@@ -352,7 +352,8 @@ static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset,
|
|
report_fatal_error(Str);
|
|
}
|
|
|
|
-void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
|
|
+void DWARFDebugFrame::parse(DWARFDataExtractor Data,
|
|
+ RefHandlerType RefHandler) {
|
|
uint32_t Offset = 0;
|
|
DenseMap<uint32_t, CIE *> CIEs;
|
|
|
|
@@ -369,6 +370,9 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
|
|
// length.
|
|
IsDWARF64 = true;
|
|
Length = Data.getU64(&Offset);
|
|
+ } else if (Length == 0) {
|
|
+ // Skip empty entry.
|
|
+ continue;
|
|
}
|
|
|
|
// At this point, Offset points to the next field after Length.
|
|
@@ -399,7 +403,7 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
|
|
|
|
// Parse the augmentation data for EH CIEs
|
|
StringRef AugmentationData("");
|
|
- uint32_t FDEPointerEncoding = DW_EH_PE_omit;
|
|
+ uint32_t FDEPointerEncoding = DW_EH_PE_absptr;
|
|
uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
|
|
Optional<uint64_t> Personality;
|
|
Optional<uint32_t> PersonalityEncoding;
|
|
@@ -425,11 +429,16 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
|
|
Personality = Data.getEncodedPointer(
|
|
&Offset, *PersonalityEncoding,
|
|
EHFrameAddress ? EHFrameAddress + Offset : 0);
|
|
+ if (RefHandler)
|
|
+ RefHandler(*Personality, Offset, *PersonalityEncoding);
|
|
break;
|
|
}
|
|
case 'R':
|
|
FDEPointerEncoding = Data.getU8(&Offset);
|
|
break;
|
|
+ case 'S':
|
|
+ // Current frame is a signal trampoline.
|
|
+ break;
|
|
case 'z':
|
|
if (i)
|
|
ReportError(StartOffset,
|
|
@@ -478,6 +487,8 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
|
|
EHFrameAddress ? EHFrameAddress + Offset : 0)) {
|
|
InitialLocation = *Val;
|
|
}
|
|
+ if (RefHandler)
|
|
+ RefHandler(InitialLocation, Offset, Cie->getFDEPointerEncoding());
|
|
if (auto Val = Data.getEncodedPointer(
|
|
&Offset, Cie->getFDEPointerEncoding(), 0)) {
|
|
AddressRange = *Val;
|
|
@@ -496,6 +507,8 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
|
|
LSDAAddress = Data.getEncodedPointer(
|
|
&Offset, Cie->getLSDAPointerEncoding(),
|
|
EHFrameAddress ? Offset + EHFrameAddress : 0);
|
|
+ if (RefHandler)
|
|
+ RefHandler(*LSDAAddress, Offset, Cie->getLSDAPointerEncoding());
|
|
}
|
|
|
|
if (Offset != EndAugmentationOffset)
|
|
@@ -531,6 +544,13 @@ FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {
|
|
return nullptr;
|
|
}
|
|
|
|
+void DWARFDebugFrame::for_each_FDE(FDEFunction F) const {
|
|
+ for (const auto &Entry : Entries) {
|
|
+ if (const auto *FDE = dyn_cast<dwarf::FDE>(Entry.get()))
|
|
+ F(FDE);
|
|
+ }
|
|
+}
|
|
+
|
|
void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
|
|
Optional<uint64_t> Offset) const {
|
|
if (Offset) {
|
|
diff --git a/lib/DebugInfo/DWARF/DWARFDie.cpp b/lib/DebugInfo/DWARF/DWARFDie.cpp
|
|
index 7ae38e6e053..f1fd34af238 100644
|
|
--- a/lib/DebugInfo/DWARF/DWARFDie.cpp
|
|
+++ b/lib/DebugInfo/DWARF/DWARFDie.cpp
|
|
@@ -270,12 +270,13 @@ bool DWARFDie::isSubroutineDIE() const {
|
|
return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine;
|
|
}
|
|
|
|
-Optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr) const {
|
|
+Optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr,
|
|
+ uint32_t *OffsetPtr) const {
|
|
if (!isValid())
|
|
return None;
|
|
auto AbbrevDecl = getAbbreviationDeclarationPtr();
|
|
if (AbbrevDecl)
|
|
- return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U);
|
|
+ return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U, OffsetPtr);
|
|
return None;
|
|
}
|
|
|
|
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
|
|
index 3d274b63a4f..cef29f4b41d 100644
|
|
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
|
|
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
|
|
@@ -175,6 +175,12 @@ static Error getOffset(const SymbolRef &Sym, SectionRef Sec,
|
|
return Error::success();
|
|
}
|
|
|
|
+void RuntimeDyldImpl::mapSectionAddress(unsigned SectionID,
|
|
+ uint64_t TargetAddress) {
|
|
+ MutexGuard locked(lock);
|
|
+ reassignSectionAddress(SectionID, TargetAddress);
|
|
+}
|
|
+
|
|
Expected<RuntimeDyldImpl::ObjSectionToIDMap>
|
|
RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
|
MutexGuard locked(lock);
|
|
@@ -585,6 +591,10 @@ unsigned RuntimeDyldImpl::computeGOTSize(const ObjectFile &Obj) {
|
|
// compute stub buffer size for the given section
|
|
unsigned RuntimeDyldImpl::computeSectionStubBufSize(const ObjectFile &Obj,
|
|
const SectionRef &Section) {
|
|
+ if (!MemMgr.allowStubAllocation()) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
unsigned StubSize = getMaxStubSize();
|
|
if (StubSize == 0) {
|
|
return 0;
|
|
@@ -795,9 +805,12 @@ RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
|
|
// to handle later processing (and by 'handle' I mean don't do anything
|
|
// with these sections).
|
|
Allocate = 0;
|
|
- Addr = nullptr;
|
|
+ Addr =
|
|
+ MemMgr.recordNoteSection(reinterpret_cast<const uint8_t *>(data.data()),
|
|
+ DataSize, Alignment, SectionID, Name);
|
|
DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name
|
|
- << " obj addr: " << format("%p", data.data()) << " new addr: 0"
|
|
+ << " obj addr: " << format("%p", data.data())
|
|
+ << " new addr: " << format("%p", Addr)
|
|
<< " DataSize: " << DataSize << " StubBufSize: " << StubBufSize
|
|
<< " Allocate: " << Allocate << "\n");
|
|
}
|
|
@@ -1064,7 +1077,7 @@ Error RuntimeDyldImpl::resolveExternalSymbols() {
|
|
}
|
|
|
|
// FIXME: Implement error handling that doesn't kill the host program!
|
|
- if (!Addr)
|
|
+ if (!Addr && !Resolver.allowsZeroSymbols())
|
|
report_fatal_error("Program used external function '" + Name +
|
|
"' which could not be resolved!");
|
|
|
|
@@ -1215,6 +1228,11 @@ void RuntimeDyld::mapSectionAddress(const void *LocalAddress,
|
|
Dyld->mapSectionAddress(LocalAddress, TargetAddress);
|
|
}
|
|
|
|
+void RuntimeDyld::mapSectionAddress(unsigned SectionID,
|
|
+ uint64_t TargetAddress) {
|
|
+ Dyld->mapSectionAddress(SectionID, TargetAddress);
|
|
+}
|
|
+
|
|
bool RuntimeDyld::hasError() { return Dyld->hasError(); }
|
|
|
|
StringRef RuntimeDyld::getErrorString() { return Dyld->getErrorString(); }
|
|
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
|
|
index 36b43ec9b78..1a56e590014 100644
|
|
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
|
|
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
|
|
@@ -270,6 +270,25 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
|
|
break;
|
|
case ELF::R_X86_64_NONE:
|
|
break;
|
|
+ case ELF::R_X86_64_8: {
|
|
+ Value += Addend;
|
|
+ assert((int64_t)Value <= INT8_MAX && (int64_t)Value >= INT8_MIN);
|
|
+ uint8_t TruncatedAddr = (Value & 0xFF);
|
|
+ *Section.getAddressWithOffset(Offset) = TruncatedAddr;
|
|
+ DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at "
|
|
+ << format("%p\n", Section.getAddressWithOffset(Offset)));
|
|
+ break;
|
|
+ }
|
|
+ case ELF::R_X86_64_16: {
|
|
+ Value += Addend;
|
|
+ assert((int64_t)Value <= INT16_MAX && (int64_t)Value >= INT16_MIN);
|
|
+ uint16_t TruncatedAddr = (Value & 0xFFFF);
|
|
+ support::ulittle16_t::ref(Section.getAddressWithOffset(Offset)) =
|
|
+ TruncatedAddr;
|
|
+ DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at "
|
|
+ << format("%p\n", Section.getAddressWithOffset(Offset)));
|
|
+ break;
|
|
+ }
|
|
case ELF::R_X86_64_64: {
|
|
support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) =
|
|
Value + Addend;
|
|
@@ -390,6 +409,26 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,
|
|
case ELF::R_AARCH64_PREL64:
|
|
write(isBE, TargetPtr, Value + Addend - FinalAddress);
|
|
break;
|
|
+ case ELF::R_AARCH64_CONDBR19: {
|
|
+ uint64_t BranchImm = Value + Addend - FinalAddress;
|
|
+
|
|
+ assert(isInt<21>(BranchImm));
|
|
+
|
|
+ *TargetPtr &= 0xff00001fU;
|
|
+ // Immediate:20:2 goes in bits 23:5 of Bcc, CBZ, CBNZ
|
|
+ *TargetPtr |= static_cast<uint32_t>(BranchImm & 0x1ffffcU) << 3;
|
|
+ break;
|
|
+ }
|
|
+ case ELF::R_AARCH64_TSTBR14: {
|
|
+ uint64_t BranchImm = Value + Addend - FinalAddress;
|
|
+
|
|
+ assert(isInt<16>(BranchImm));
|
|
+
|
|
+ *TargetPtr &= 0xfff8001fU;
|
|
+ // Immediate:15:2 goes in bits 18:5 of TBZ, TBNZ
|
|
+ *TargetPtr |= static_cast<uint32_t>(BranchImm & 0xffffffcU) << 3;
|
|
+ break;
|
|
+ }
|
|
case ELF::R_AARCH64_CALL26: // fallthrough
|
|
case ELF::R_AARCH64_JUMP26: {
|
|
// Operation: S+A-P. Set Call or B immediate value to bits fff_fffc of the
|
|
@@ -462,6 +501,33 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,
|
|
// from bits 11:4 of X
|
|
or32AArch64Imm(TargetPtr, getBits(Value + Addend, 4, 11));
|
|
break;
|
|
+ case ELF::R_AARCH64_LD_PREL_LO19: {
|
|
+ // Operation: S + A - P
|
|
+ uint64_t Result = Value + Addend - FinalAddress;
|
|
+
|
|
+ // "Check that -2^20 <= result < 2^20".
|
|
+ assert(isInt<21>(Result));
|
|
+
|
|
+ *TargetPtr &= 0xff00001fU;
|
|
+ // Immediate goes in bits 23:5 of LD imm instruction, taken
|
|
+ // from bits 20:2 of X
|
|
+ *TargetPtr |= ((Result & 0xffc) << (5 - 2));
|
|
+ break;
|
|
+ }
|
|
+ case ELF::R_AARCH64_ADR_PREL_LO21: {
|
|
+ // Operation: S + A - P
|
|
+ uint64_t Result = Value + Addend - FinalAddress;
|
|
+
|
|
+ // "Check that -2^20 <= result < 2^20".
|
|
+ assert(isInt<21>(Result));
|
|
+
|
|
+ *TargetPtr &= 0x9f00001fU;
|
|
+ // Immediate goes in bits 23:5, 30:29 of ADR imm instruction, taken
|
|
+ // from bits 20:0 of X
|
|
+ *TargetPtr |= ((Result & 0xffc) << (5 - 2));
|
|
+ *TargetPtr |= (Result & 0x3) << 29;
|
|
+ break;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -1173,7 +1239,9 @@ RuntimeDyldELF::processRelocationRef(
|
|
DEBUG(dbgs() << "\t\tSectionID: " << SectionID << " Offset: " << Offset
|
|
<< "\n");
|
|
if ((Arch == Triple::aarch64 || Arch == Triple::aarch64_be)) {
|
|
- if (RelType == ELF::R_AARCH64_CALL26 || RelType == ELF::R_AARCH64_JUMP26) {
|
|
+ if ((RelType == ELF::R_AARCH64_CALL26 ||
|
|
+ RelType == ELF::R_AARCH64_JUMP26) &&
|
|
+ MemMgr.allowStubAllocation()) {
|
|
resolveAArch64Branch(SectionID, Value, RelI, Stubs);
|
|
} else if (RelType == ELF::R_AARCH64_ADR_GOT_PAGE) {
|
|
// Craete new GOT entry or find existing one. If GOT entry is
|
|
@@ -1632,7 +1700,7 @@ RuntimeDyldELF::processRelocationRef(
|
|
// equivalent to the usual PLT implementation except that we use the stub
|
|
// mechanism in RuntimeDyld (which puts stubs at the end of the section)
|
|
// rather than allocating a PLT section.
|
|
- if (Value.SymbolName) {
|
|
+ if (Value.SymbolName && MemMgr.allowStubAllocation()) {
|
|
// This is a call to an external function.
|
|
// Look for an existing stub.
|
|
SectionEntry &Section = Sections[SectionID];
|
|
@@ -1674,9 +1742,8 @@ RuntimeDyldELF::processRelocationRef(
|
|
resolveRelocation(Section, Offset, StubAddress, ELF::R_X86_64_PC32,
|
|
Addend);
|
|
} else {
|
|
- RelocationEntry RE(SectionID, Offset, ELF::R_X86_64_PC32, Value.Addend,
|
|
- Value.Offset);
|
|
- addRelocationForSection(RE, Value.SectionID);
|
|
+ Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset));
|
|
+ processSimpleRelocation(SectionID, Offset, ELF::R_X86_64_PC32, Value);
|
|
}
|
|
} else if (RelType == ELF::R_X86_64_GOTPCREL ||
|
|
RelType == ELF::R_X86_64_GOTPCRELX ||
|
|
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
|
|
index 766a9b21cb1..a36c791c843 100644
|
|
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
|
|
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
|
|
@@ -540,6 +540,8 @@ public:
|
|
|
|
void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress);
|
|
|
|
+ void mapSectionAddress(unsigned SectionID, uint64_t TargetAddress);
|
|
+
|
|
// Is the linker in an error state?
|
|
bool hasError() { return HasError; }
|
|
|
|
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
|
|
index a0f9a857e3c..be32963b705 100644
|
|
--- a/lib/MC/MCAssembler.cpp
|
|
+++ b/lib/MC/MCAssembler.cpp
|
|
@@ -318,6 +318,34 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
|
|
return Size;
|
|
}
|
|
|
|
+ case MCFragment::FT_NeverAlign: {
|
|
+ const MCNeverAlignFragment &NAF = cast<MCNeverAlignFragment>(F);
|
|
+ uint64_t Offset = Layout.getFragmentOffset(&NAF);
|
|
+ unsigned Size = 0;
|
|
+ uint64_t OffsetToAvoid = 0;
|
|
+ // Calculate offset to avoid in order to avoid aligning the end of the
|
|
+ // next fragment
|
|
+ if (const auto *NextFrag = dyn_cast<MCRelaxableFragment>(F.getNextNode())) {
|
|
+ OffsetToAvoid = NAF.getAlignment() -
|
|
+ (NextFrag->getContents().size() % NAF.getAlignment());
|
|
+ } else if (const auto *NextFrag =
|
|
+ dyn_cast<MCDataFragment>(F.getNextNode())) {
|
|
+ OffsetToAvoid = NAF.getAlignment() -
|
|
+ (NextFrag->getContents().size() % NAF.getAlignment());
|
|
+ }
|
|
+ // Check if the current offset matches the alignment plus offset we want to
|
|
+ // avoid
|
|
+ if (Offset % NAF.getAlignment() == OffsetToAvoid) {
|
|
+ // Avoid this alignment by introducing one extra byte
|
|
+ Size = 1;
|
|
+ if (Size > 0 && NAF.hasEmitNops()) {
|
|
+ while (Size % getBackend().getMinimumNopSize())
|
|
+ Size += 1;
|
|
+ }
|
|
+ }
|
|
+ return Size;
|
|
+ }
|
|
+
|
|
case MCFragment::FT_Org: {
|
|
const MCOrgFragment &OF = cast<MCOrgFragment>(F);
|
|
MCValue Value;
|
|
@@ -525,6 +553,35 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
|
break;
|
|
}
|
|
|
|
+ case MCFragment::FT_NeverAlign: {
|
|
+ const MCNeverAlignFragment &NAF = cast<MCNeverAlignFragment>(F);
|
|
+ assert(NAF.getValueSize() && "Invalid virtual align in concrete fragment!");
|
|
+
|
|
+ uint64_t Count = FragmentSize / NAF.getValueSize();
|
|
+ if (Count == 0)
|
|
+ break;
|
|
+ assert(Count * NAF.getValueSize() == FragmentSize);
|
|
+
|
|
+ if (NAF.hasEmitNops()) {
|
|
+ if (!Asm.getBackend().writeNopData(Count, OW))
|
|
+ report_fatal_error("unable to write nop sequence of " +
|
|
+ Twine(Count) + " bytes");
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ // Otherwise, write out in multiples of the value size.
|
|
+ for (uint64_t i = 0; i != Count; ++i) {
|
|
+ switch (NAF.getValueSize()) {
|
|
+ default: llvm_unreachable("Invalid size!");
|
|
+ case 1: OW->write8 (uint8_t (NAF.getValue())); break;
|
|
+ case 2: OW->write16(uint16_t(NAF.getValue())); break;
|
|
+ case 4: OW->write32(uint32_t(NAF.getValue())); break;
|
|
+ case 8: OW->write64(uint64_t(NAF.getValue())); break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+
|
|
case MCFragment::FT_Data:
|
|
++stats::EmittedDataFragments;
|
|
OW->writeBytes(cast<MCDataFragment>(F).getContents());
|
|
@@ -651,6 +708,11 @@ void MCAssembler::writeSectionData(const MCSection *Sec,
|
|
cast<MCAlignFragment>(F).getValue() == 0) &&
|
|
"Invalid align in virtual section!");
|
|
break;
|
|
+ case MCFragment::FT_NeverAlign:
|
|
+ assert((cast<MCNeverAlignFragment>(F).getValueSize() == 0 ||
|
|
+ cast<MCNeverAlignFragment>(F).getValue() == 0) &&
|
|
+ "Invalid neveralign in virtual section!");
|
|
+ break;
|
|
case MCFragment::FT_Fill:
|
|
assert((cast<MCFillFragment>(F).getValue() == 0) &&
|
|
"Invalid fill in virtual section!");
|
|
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
|
|
index 0e0ea965d14..49885269d06 100644
|
|
--- a/lib/MC/MCDwarf.cpp
|
|
+++ b/lib/MC/MCDwarf.cpp
|
|
@@ -156,12 +156,36 @@ EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section,
|
|
unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
|
|
unsigned Isa = 0;
|
|
unsigned Discriminator = 0;
|
|
+ uint64_t LastAddress = -1ULL;
|
|
+ (void)LastAddress;
|
|
MCSymbol *LastLabel = nullptr;
|
|
|
|
// Loop through each MCDwarfLineEntry and encode the dwarf line number table.
|
|
- for (const MCDwarfLineEntry &LineEntry : LineEntries) {
|
|
+ for (auto it = LineEntries.begin(),
|
|
+ ie = LineEntries.end();
|
|
+ it != ie; ++it) {
|
|
+ const MCDwarfLineEntry &LineEntry = *it;
|
|
int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
|
|
|
|
+ uint64_t Address = LineEntry.getAbsoluteAddr();
|
|
+ if (Address != -1ULL) {
|
|
+ auto nit = it;
|
|
+ if (++nit == ie) {
|
|
+ // We are using a hacky way to update debug info for functions that we
|
|
+ // didn't rewrite. We don't have a code section context, and should
|
|
+ // emit end_sequence at the address indicated by the last entry.
|
|
+ MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
|
|
+ MCOS->EmitIntValue(8 + 1, 1);
|
|
+ MCOS->EmitIntValue(dwarf::DW_LNE_set_address, 1);
|
|
+ MCOS->EmitIntValue(Address, 8);
|
|
+ MCDwarfLineAddr::Emit(MCOS,
|
|
+ MCOS->getAssembler().getDWARFLinetableParams(),
|
|
+ INT64_MAX,
|
|
+ 0);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (FileNum != LineEntry.getFileNum()) {
|
|
FileNum = LineEntry.getFileNum();
|
|
MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1);
|
|
@@ -197,18 +221,33 @@ EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section,
|
|
if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
|
|
MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
|
|
|
|
- MCSymbol *Label = LineEntry.getLabel();
|
|
+ if (Address == -1ULL) {
|
|
+ assert(LastAddress == -1ULL &&
|
|
+ "Absolute addresses can only be added at the end of the table.");
|
|
+
|
|
+ MCSymbol *Label = LineEntry.getLabel();
|
|
|
|
- // At this point we want to emit/create the sequence to encode the delta in
|
|
- // line numbers and the increment of the address from the previous Label
|
|
- // and the current Label.
|
|
- const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
|
|
- MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
|
|
- asmInfo->getCodePointerSize());
|
|
+ // At this point we want to emit/create the sequence to encode the delta in
|
|
+ // line numbers and the increment of the address from the previous Label
|
|
+ // and the current Label.
|
|
+ const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
|
|
+ MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
|
|
+ asmInfo->getCodePointerSize());
|
|
+ LastLabel = Label;
|
|
+ } else {
|
|
+ MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
|
|
+ // DW_LNE_set_address length: pointer size (8) + 1
|
|
+ MCOS->EmitIntValue(8 + 1, 1);
|
|
+ MCOS->EmitIntValue(dwarf::DW_LNE_set_address, 1);
|
|
+ MCOS->EmitIntValue(Address, 8);
|
|
+ MCOS->EmitIntValue(dwarf::DW_LNS_advance_line, 1);
|
|
+ MCOS->EmitSLEB128IntValue(LineDelta);
|
|
+ MCOS->EmitIntValue(dwarf::DW_LNS_copy, 1);
|
|
+ LastAddress = Address;
|
|
+ }
|
|
|
|
Discriminator = 0;
|
|
LastLine = LineEntry.getLine();
|
|
- LastLabel = Label;
|
|
}
|
|
|
|
// Emit a DW_LNE_end_sequence for the end of the section.
|
|
@@ -250,7 +289,7 @@ void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS,
|
|
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
|
|
|
|
// Handle the rest of the Compile Units.
|
|
- for (const auto &CUIDTablePair : LineTables)
|
|
+ for (auto &CUIDTablePair : LineTables)
|
|
CUIDTablePair.second.EmitCU(MCOS, Params, LineStr);
|
|
|
|
if (LineStr)
|
|
@@ -514,8 +553,12 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
|
|
|
|
void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS,
|
|
MCDwarfLineTableParams Params,
|
|
- Optional<MCDwarfLineStr> &LineStr) const {
|
|
- MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
|
|
+ Optional<MCDwarfLineStr> &LineStr) {
|
|
+ MCSymbol *LineBeginSym;
|
|
+ MCSymbol *LineEndSym;
|
|
+
|
|
+ std::tie(LineBeginSym, LineEndSym) = Header.Emit(MCOS, Params, LineStr);
|
|
+ setLabel(LineBeginSym);
|
|
|
|
// Put out the line tables.
|
|
for (const auto &LineSec : MCLineSections.getMCLineEntries())
|
|
@@ -1253,12 +1296,217 @@ public:
|
|
void EmitCFIInstruction(const MCCFIInstruction &Instr);
|
|
};
|
|
|
|
+// A stripped-down version of MCObjectStreamer that only calculates how many
|
|
+// bytes were written to it. We use it to know in advance how many bytes
|
|
+// DWARF expressions will use.
|
|
+class SizeCalcMCStreamer {
|
|
+ uint64_t TotalSize = {0};
|
|
+
|
|
+public:
|
|
+ SizeCalcMCStreamer() {}
|
|
+
|
|
+ uint64_t getSize() { return TotalSize; }
|
|
+
|
|
+ void EmitIntValue(uint64_t Value, unsigned Size) { TotalSize += Size; }
|
|
+
|
|
+ void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0) {
|
|
+ TotalSize += Padding + getULEB128Size(Value);
|
|
+ }
|
|
+
|
|
+ void EmitSLEB128IntValue(int64_t Value) {
|
|
+ TotalSize += getSLEB128Size(Value);
|
|
+ }
|
|
+};
|
|
+
|
|
} // end anonymous namespace
|
|
|
|
static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) {
|
|
Streamer.EmitIntValue(Encoding, 1);
|
|
}
|
|
|
|
+template <typename T>
|
|
+static void EmitDwarfExpression(T &Streamer,
|
|
+ const MCDwarfExpression &Expr) {
|
|
+ for (const auto &Elem : Expr) {
|
|
+ Streamer.EmitIntValue(Elem.Operation, 1);
|
|
+ switch (Elem.Operation) {
|
|
+ default:
|
|
+ llvm_unreachable("Unrecognized DWARF expression opcode");
|
|
+ case dwarf::DW_OP_addr:
|
|
+ case dwarf::DW_OP_call_ref:
|
|
+ llvm_unreachable("DW_OP_addr & DW_OP_call_ref are unimplemented");
|
|
+ break;
|
|
+ case dwarf::DW_OP_const1u:
|
|
+ case dwarf::DW_OP_const1s:
|
|
+ case dwarf::DW_OP_pick:
|
|
+ case dwarf::DW_OP_deref_size:
|
|
+ case dwarf::DW_OP_xderef_size:
|
|
+ Streamer.EmitIntValue(Elem.Operand0, 1);
|
|
+ break;
|
|
+ case dwarf::DW_OP_const2u:
|
|
+ case dwarf::DW_OP_const2s:
|
|
+ case dwarf::DW_OP_skip:
|
|
+ case dwarf::DW_OP_bra:
|
|
+ case dwarf::DW_OP_call2:
|
|
+ Streamer.EmitIntValue(Elem.Operand0, 2);
|
|
+ break;
|
|
+ case dwarf::DW_OP_const4u:
|
|
+ case dwarf::DW_OP_const4s:
|
|
+ case dwarf::DW_OP_call4:
|
|
+ Streamer.EmitIntValue(Elem.Operand0, 4);
|
|
+ break;
|
|
+ case dwarf::DW_OP_const8u:
|
|
+ case dwarf::DW_OP_const8s:
|
|
+ Streamer.EmitIntValue(Elem.Operand0, 8);
|
|
+ break;
|
|
+ case dwarf::DW_OP_constu:
|
|
+ case dwarf::DW_OP_plus_uconst:
|
|
+ case dwarf::DW_OP_regx:
|
|
+ case dwarf::DW_OP_piece:
|
|
+ case dwarf::DW_OP_GNU_addr_index:
|
|
+ case dwarf::DW_OP_GNU_const_index:
|
|
+ Streamer.EmitULEB128IntValue(Elem.Operand0);
|
|
+ break;
|
|
+ case dwarf::DW_OP_consts:
|
|
+ case dwarf::DW_OP_breg0:
|
|
+ case dwarf::DW_OP_breg1:
|
|
+ case dwarf::DW_OP_breg2:
|
|
+ case dwarf::DW_OP_breg3:
|
|
+ case dwarf::DW_OP_breg4:
|
|
+ case dwarf::DW_OP_breg5:
|
|
+ case dwarf::DW_OP_breg6:
|
|
+ case dwarf::DW_OP_breg7:
|
|
+ case dwarf::DW_OP_breg8:
|
|
+ case dwarf::DW_OP_breg9:
|
|
+ case dwarf::DW_OP_breg10:
|
|
+ case dwarf::DW_OP_breg11:
|
|
+ case dwarf::DW_OP_breg12:
|
|
+ case dwarf::DW_OP_breg13:
|
|
+ case dwarf::DW_OP_breg14:
|
|
+ case dwarf::DW_OP_breg15:
|
|
+ case dwarf::DW_OP_breg16:
|
|
+ case dwarf::DW_OP_breg17:
|
|
+ case dwarf::DW_OP_breg18:
|
|
+ case dwarf::DW_OP_breg19:
|
|
+ case dwarf::DW_OP_breg20:
|
|
+ case dwarf::DW_OP_breg21:
|
|
+ case dwarf::DW_OP_breg22:
|
|
+ case dwarf::DW_OP_breg23:
|
|
+ case dwarf::DW_OP_breg24:
|
|
+ case dwarf::DW_OP_breg25:
|
|
+ case dwarf::DW_OP_breg26:
|
|
+ case dwarf::DW_OP_breg27:
|
|
+ case dwarf::DW_OP_breg28:
|
|
+ case dwarf::DW_OP_breg29:
|
|
+ case dwarf::DW_OP_breg30:
|
|
+ case dwarf::DW_OP_breg31:
|
|
+ case dwarf::DW_OP_fbreg:
|
|
+ Streamer.EmitSLEB128IntValue(Elem.Operand0);
|
|
+ break;
|
|
+ case dwarf::DW_OP_deref:
|
|
+ case dwarf::DW_OP_dup:
|
|
+ case dwarf::DW_OP_drop:
|
|
+ case dwarf::DW_OP_over:
|
|
+ case dwarf::DW_OP_swap:
|
|
+ case dwarf::DW_OP_rot:
|
|
+ case dwarf::DW_OP_xderef:
|
|
+ case dwarf::DW_OP_abs:
|
|
+ case dwarf::DW_OP_and:
|
|
+ case dwarf::DW_OP_div:
|
|
+ case dwarf::DW_OP_minus:
|
|
+ case dwarf::DW_OP_mod:
|
|
+ case dwarf::DW_OP_mul:
|
|
+ case dwarf::DW_OP_neg:
|
|
+ case dwarf::DW_OP_not:
|
|
+ case dwarf::DW_OP_or:
|
|
+ case dwarf::DW_OP_plus:
|
|
+ case dwarf::DW_OP_shl:
|
|
+ case dwarf::DW_OP_shr:
|
|
+ case dwarf::DW_OP_shra:
|
|
+ case dwarf::DW_OP_xor:
|
|
+ case dwarf::DW_OP_eq:
|
|
+ case dwarf::DW_OP_ge:
|
|
+ case dwarf::DW_OP_gt:
|
|
+ case dwarf::DW_OP_le:
|
|
+ case dwarf::DW_OP_lt:
|
|
+ case dwarf::DW_OP_ne:
|
|
+ case dwarf::DW_OP_lit0:
|
|
+ case dwarf::DW_OP_lit1:
|
|
+ case dwarf::DW_OP_lit2:
|
|
+ case dwarf::DW_OP_lit3:
|
|
+ case dwarf::DW_OP_lit4:
|
|
+ case dwarf::DW_OP_lit5:
|
|
+ case dwarf::DW_OP_lit6:
|
|
+ case dwarf::DW_OP_lit7:
|
|
+ case dwarf::DW_OP_lit8:
|
|
+ case dwarf::DW_OP_lit9:
|
|
+ case dwarf::DW_OP_lit10:
|
|
+ case dwarf::DW_OP_lit11:
|
|
+ case dwarf::DW_OP_lit12:
|
|
+ case dwarf::DW_OP_lit13:
|
|
+ case dwarf::DW_OP_lit14:
|
|
+ case dwarf::DW_OP_lit15:
|
|
+ case dwarf::DW_OP_lit16:
|
|
+ case dwarf::DW_OP_lit17:
|
|
+ case dwarf::DW_OP_lit18:
|
|
+ case dwarf::DW_OP_lit19:
|
|
+ case dwarf::DW_OP_lit20:
|
|
+ case dwarf::DW_OP_lit21:
|
|
+ case dwarf::DW_OP_lit22:
|
|
+ case dwarf::DW_OP_lit23:
|
|
+ case dwarf::DW_OP_lit24:
|
|
+ case dwarf::DW_OP_lit25:
|
|
+ case dwarf::DW_OP_lit26:
|
|
+ case dwarf::DW_OP_lit27:
|
|
+ case dwarf::DW_OP_lit28:
|
|
+ case dwarf::DW_OP_lit29:
|
|
+ case dwarf::DW_OP_lit30:
|
|
+ case dwarf::DW_OP_lit31:
|
|
+ case dwarf::DW_OP_reg0:
|
|
+ case dwarf::DW_OP_reg1:
|
|
+ case dwarf::DW_OP_reg2:
|
|
+ case dwarf::DW_OP_reg3:
|
|
+ case dwarf::DW_OP_reg4:
|
|
+ case dwarf::DW_OP_reg5:
|
|
+ case dwarf::DW_OP_reg6:
|
|
+ case dwarf::DW_OP_reg7:
|
|
+ case dwarf::DW_OP_reg8:
|
|
+ case dwarf::DW_OP_reg9:
|
|
+ case dwarf::DW_OP_reg10:
|
|
+ case dwarf::DW_OP_reg11:
|
|
+ case dwarf::DW_OP_reg12:
|
|
+ case dwarf::DW_OP_reg13:
|
|
+ case dwarf::DW_OP_reg14:
|
|
+ case dwarf::DW_OP_reg15:
|
|
+ case dwarf::DW_OP_reg16:
|
|
+ case dwarf::DW_OP_reg17:
|
|
+ case dwarf::DW_OP_reg18:
|
|
+ case dwarf::DW_OP_reg19:
|
|
+ case dwarf::DW_OP_reg20:
|
|
+ case dwarf::DW_OP_reg21:
|
|
+ case dwarf::DW_OP_reg22:
|
|
+ case dwarf::DW_OP_reg23:
|
|
+ case dwarf::DW_OP_reg24:
|
|
+ case dwarf::DW_OP_reg25:
|
|
+ case dwarf::DW_OP_reg26:
|
|
+ case dwarf::DW_OP_reg27:
|
|
+ case dwarf::DW_OP_reg28:
|
|
+ case dwarf::DW_OP_reg29:
|
|
+ case dwarf::DW_OP_reg30:
|
|
+ case dwarf::DW_OP_reg31:
|
|
+ case dwarf::DW_OP_nop:
|
|
+ case dwarf::DW_OP_push_object_address:
|
|
+ case dwarf::DW_OP_form_tls_address:
|
|
+ case dwarf::DW_OP_GNU_push_tls_address:
|
|
+ break;
|
|
+ case dwarf::DW_OP_bregx:
|
|
+ Streamer.EmitULEB128IntValue(Elem.Operand0);
|
|
+ Streamer.EmitSLEB128IntValue(Elem.Operand1);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
|
|
int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
|
|
auto *MRI = Streamer.getContext().getRegisterInfo();
|
|
@@ -1373,7 +1621,28 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
|
|
Streamer.EmitIntValue(dwarf::DW_CFA_GNU_args_size, 1);
|
|
Streamer.EmitULEB128IntValue(Instr.getOffset());
|
|
return;
|
|
-
|
|
+ case MCCFIInstruction::OpDefCfaExpression: {
|
|
+ Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_expression, 1);
|
|
+ SizeCalcMCStreamer FakeStreamer;
|
|
+ EmitDwarfExpression<>(FakeStreamer, Instr.getExpression());
|
|
+ Streamer.EmitULEB128IntValue(FakeStreamer.getSize());
|
|
+ EmitDwarfExpression<>(Streamer, Instr.getExpression());
|
|
+ return;
|
|
+ }
|
|
+ case MCCFIInstruction::OpExpression:
|
|
+ case MCCFIInstruction::OpValExpression: {
|
|
+ unsigned Reg = Instr.getRegister();
|
|
+ Streamer.EmitIntValue(Instr.getOperation() == MCCFIInstruction::OpExpression
|
|
+ ? dwarf::DW_CFA_expression
|
|
+ : dwarf::DW_CFA_val_expression,
|
|
+ 1);
|
|
+ Streamer.EmitULEB128IntValue(Reg);
|
|
+ SizeCalcMCStreamer FakeStreamer;
|
|
+ EmitDwarfExpression<>(FakeStreamer, Instr.getExpression());
|
|
+ Streamer.EmitULEB128IntValue(FakeStreamer.getSize());
|
|
+ EmitDwarfExpression<>(Streamer, Instr.getExpression());
|
|
+ return;
|
|
+ }
|
|
case MCCFIInstruction::OpEscape:
|
|
Streamer.EmitBytes(Instr.getValues());
|
|
return;
|
|
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
|
|
index 65fbe8e8428..4b32cd7c586 100644
|
|
--- a/lib/MC/MCExpr.cpp
|
|
+++ b/lib/MC/MCExpr.cpp
|
|
@@ -834,3 +834,7 @@ MCFragment *MCExpr::findAssociatedFragment() const {
|
|
|
|
llvm_unreachable("Invalid assembly expression kind!");
|
|
}
|
|
+
|
|
+const MCSymbol &MCExpr::getSymbol() const {
|
|
+ return cast<MCSymbolRefExpr>(this)->getSymbol();
|
|
+}
|
|
diff --git a/lib/MC/MCFragment.cpp b/lib/MC/MCFragment.cpp
|
|
index 1aed50aaeb7..e740a0d304a 100644
|
|
--- a/lib/MC/MCFragment.cpp
|
|
+++ b/lib/MC/MCFragment.cpp
|
|
@@ -254,6 +254,9 @@ void MCFragment::destroy() {
|
|
case FT_Align:
|
|
delete cast<MCAlignFragment>(this);
|
|
return;
|
|
+ case FT_NeverAlign:
|
|
+ delete cast<MCNeverAlignFragment>(this);
|
|
+ return;
|
|
case FT_Data:
|
|
delete cast<MCDataFragment>(this);
|
|
return;
|
|
@@ -316,6 +319,7 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
|
|
OS << "<";
|
|
switch (getKind()) {
|
|
case MCFragment::FT_Align: OS << "MCAlignFragment"; break;
|
|
+ case MCFragment::FT_NeverAlign: OS << "MCNeverAlignFragment"; break;
|
|
case MCFragment::FT_Data: OS << "MCDataFragment"; break;
|
|
case MCFragment::FT_CompactEncodedInst:
|
|
OS << "MCCompactEncodedInstFragment"; break;
|
|
@@ -348,6 +352,15 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
|
|
<< " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">";
|
|
break;
|
|
}
|
|
+ case MCFragment::FT_NeverAlign: {
|
|
+ const MCNeverAlignFragment *NAF = cast<MCNeverAlignFragment>(this);
|
|
+ if (NAF->hasEmitNops())
|
|
+ OS << " (emit nops)";
|
|
+ OS << "\n ";
|
|
+ OS << " Alignment:" << NAF->getAlignment()
|
|
+ << " Value:" << NAF->getValue() << " ValueSize:" << NAF->getValueSize();
|
|
+ break;
|
|
+ }
|
|
case MCFragment::FT_Data: {
|
|
const MCDataFragment *DF = cast<MCDataFragment>(this);
|
|
OS << "\n ";
|
|
@@ -480,7 +493,10 @@ LLVM_DUMP_METHOD void MCAssembler::dump() const{
|
|
if (it != symbol_begin()) OS << ",\n ";
|
|
OS << "(";
|
|
it->dump();
|
|
- OS << ", Index:" << it->getIndex() << ", ";
|
|
+ if (it->hasIndex())
|
|
+ OS << ", Index:" << it->getIndex() << ", ";
|
|
+ else
|
|
+ OS << ", Order:" << it->getOrder() << ", ";
|
|
OS << ")";
|
|
}
|
|
OS << "]>\n";
|
|
diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp
|
|
index 83da8ac1bae..820aa688e5f 100644
|
|
--- a/lib/MC/MCObjectFileInfo.cpp
|
|
+++ b/lib/MC/MCObjectFileInfo.cpp
|
|
@@ -480,6 +480,9 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
|
|
ReadOnlySection =
|
|
Ctx->getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
|
|
|
|
+ ReadOnlyColdSection =
|
|
+ Ctx->getELFSection(".rodata.cold", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
|
|
+
|
|
TLSDataSection =
|
|
Ctx->getELFSection(".tdata", ELF::SHT_PROGBITS,
|
|
ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE);
|
|
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
|
|
index 0a684588110..58199c97420 100644
|
|
--- a/lib/MC/MCObjectStreamer.cpp
|
|
+++ b/lib/MC/MCObjectStreamer.cpp
|
|
@@ -494,6 +494,13 @@ void MCObjectStreamer::EmitCodeAlignment(unsigned ByteAlignment,
|
|
cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true);
|
|
}
|
|
|
|
+void MCObjectStreamer::EmitNeverAlignCodeAtEnd(unsigned ByteAlignment,
|
|
+ int64_t Value,
|
|
+ unsigned ValueSize) {
|
|
+ insert(new MCNeverAlignFragment(ByteAlignment, 0, 1));
|
|
+ cast<MCNeverAlignFragment>(getCurrentFragment())->setEmitNops(true);
|
|
+}
|
|
+
|
|
void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
|
|
unsigned char Value,
|
|
SMLoc Loc) {
|
|
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
|
|
index 776569894a5..aa130bb2d6a 100644
|
|
--- a/lib/MC/MCStreamer.cpp
|
|
+++ b/lib/MC/MCStreamer.cpp
|
|
@@ -85,11 +85,15 @@ void MCStreamer::reset() {
|
|
DwarfFrameInfos.clear();
|
|
CurrentWinFrameInfo = nullptr;
|
|
WinFrameInfos.clear();
|
|
- SymbolOrdering.clear();
|
|
+ SymbolOrdering = 1;
|
|
SectionStack.clear();
|
|
SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
|
|
}
|
|
|
|
+unsigned MCStreamer::GetSymbolOrder(const MCSymbol *Symbol) const {
|
|
+ return Symbol->getOrder();
|
|
+}
|
|
+
|
|
raw_ostream &MCStreamer::GetCommentOS() {
|
|
// By default, discard comments.
|
|
return nulls();
|
|
@@ -130,6 +134,13 @@ void MCStreamer::EmitULEB128IntValue(uint64_t Value) {
|
|
EmitBytes(OSE.str());
|
|
}
|
|
|
|
+void MCStreamer::EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo) {
|
|
+ SmallString<128> Tmp;
|
|
+ raw_svector_ostream OSE(Tmp);
|
|
+ encodeULEB128(Value, OSE, PadTo);
|
|
+ EmitBytes(OSE.str());
|
|
+}
|
|
+
|
|
/// EmitSLEB128IntValue - Special case of EmitSLEB128Value that avoids the
|
|
/// client having to pass in a MCExpr for constant integers.
|
|
void MCStreamer::EmitSLEB128IntValue(int64_t Value) {
|
|
@@ -315,7 +326,7 @@ void MCStreamer::AssignFragment(MCSymbol *Symbol, MCFragment *Fragment) {
|
|
|
|
// As we emit symbols into a section, track the order so that they can
|
|
// be sorted upon later. Zero is reserved to mean 'unemitted'.
|
|
- SymbolOrdering[Symbol] = 1 + SymbolOrdering.size();
|
|
+ Symbol->setOrder(SymbolOrdering);
|
|
}
|
|
|
|
void MCStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
|
|
@@ -884,6 +895,14 @@ void MCStreamer::visitUsedExpr(const MCExpr &Expr) {
|
|
}
|
|
}
|
|
|
|
+void MCStreamer::EmitCFIInstruction(const MCCFIInstruction &Inst) {
|
|
+ MCSymbol *Label = EmitCFILabel();
|
|
+ MCCFIInstruction Instruction = Inst;
|
|
+ Instruction.setLabel(Label);
|
|
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
|
|
+ CurFrame->Instructions.push_back(Instruction);
|
|
+}
|
|
+
|
|
void MCStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
|
bool) {
|
|
// Scan for values.
|
|
@@ -961,6 +980,8 @@ void MCStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
|
|
unsigned MaxBytesToEmit) {}
|
|
void MCStreamer::EmitCodeAlignment(unsigned ByteAlignment,
|
|
unsigned MaxBytesToEmit) {}
|
|
+void MCStreamer::EmitNeverAlignCodeAtEnd(unsigned ByteAlignment, int64_t Value,
|
|
+ unsigned ValueSize) {}
|
|
void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value,
|
|
SMLoc Loc) {}
|
|
void MCStreamer::EmitBundleAlignMode(unsigned AlignPow2) {}
|
|
diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp
|
|
index b544fa5c147..c885bf9f037 100644
|
|
--- a/lib/Object/COFFObjectFile.cpp
|
|
+++ b/lib/Object/COFFObjectFile.cpp
|
|
@@ -344,6 +344,11 @@ bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
|
|
return Sec->PointerToRawData == 0;
|
|
}
|
|
|
|
+bool COFFObjectFile::isSectionReadOnly(DataRefImpl Ref) const {
|
|
+ llvm_unreachable("not implemented");
|
|
+ return false;
|
|
+}
|
|
+
|
|
static uint32_t getNumberOfRelocations(const coff_section *Sec,
|
|
MemoryBufferRef M, const uint8_t *base) {
|
|
// The field for the number of relocations in COFF section table is only
|
|
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
|
|
index adc54b42eba..2fcc293a14b 100644
|
|
--- a/lib/Object/MachOObjectFile.cpp
|
|
+++ b/lib/Object/MachOObjectFile.cpp
|
|
@@ -1986,6 +1986,11 @@ bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
|
|
return getSection(Sec).offset == 0;
|
|
}
|
|
|
|
+bool MachOObjectFile::isSectionReadOnly(DataRefImpl Sec) const {
|
|
+ llvm_unreachable("not implemented");
|
|
+ return false;
|
|
+}
|
|
+
|
|
relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
|
|
DataRefImpl Ret;
|
|
Ret.d.a = Sec.d.a;
|
|
diff --git a/lib/Object/WasmObjectFile.cpp b/lib/Object/WasmObjectFile.cpp
|
|
index 0c78631da25..c0dac222978 100644
|
|
--- a/lib/Object/WasmObjectFile.cpp
|
|
+++ b/lib/Object/WasmObjectFile.cpp
|
|
@@ -1140,6 +1140,8 @@ bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
|
|
|
|
bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
|
|
|
|
+bool WasmObjectFile::isSectionReadOnly(DataRefImpl Sec) const { return false; }
|
|
+
|
|
bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
|
|
|
|
relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
|
|
diff --git a/lib/Support/ToolOutputFile.cpp b/lib/Support/ToolOutputFile.cpp
|
|
index e12d9e824f7..1c74d40f094 100644
|
|
--- a/lib/Support/ToolOutputFile.cpp
|
|
+++ b/lib/Support/ToolOutputFile.cpp
|
|
@@ -35,8 +35,8 @@ ToolOutputFile::CleanupInstaller::~CleanupInstaller() {
|
|
}
|
|
|
|
ToolOutputFile::ToolOutputFile(StringRef Filename, std::error_code &EC,
|
|
- sys::fs::OpenFlags Flags)
|
|
- : Installer(Filename), OS(Filename, EC, Flags) {
|
|
+ sys::fs::OpenFlags Flags, unsigned Mode)
|
|
+ : Installer(Filename), OS(Filename, EC, Flags, Mode) {
|
|
// If open fails, no cleanup is needed.
|
|
if (EC)
|
|
Installer.Keep = true;
|
|
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
|
|
index e0261110308..94553799b22 100644
|
|
--- a/lib/Support/raw_ostream.cpp
|
|
+++ b/lib/Support/raw_ostream.cpp
|
|
@@ -490,7 +490,7 @@ void format_object_base::home() {
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
static int getFD(StringRef Filename, std::error_code &EC,
|
|
- sys::fs::OpenFlags Flags) {
|
|
+ sys::fs::OpenFlags Flags, unsigned Mode = 0666) {
|
|
// Handle "-" as stdout. Note that when we do this, we consider ourself
|
|
// the owner of stdout and may set the "binary" flag globally based on Flags.
|
|
if (Filename == "-") {
|
|
@@ -503,7 +503,7 @@ static int getFD(StringRef Filename, std::error_code &EC,
|
|
}
|
|
|
|
int FD;
|
|
- EC = sys::fs::openFileForWrite(Filename, FD, Flags);
|
|
+ EC = sys::fs::openFileForWrite(Filename, FD, Flags, Mode);
|
|
if (EC)
|
|
return -1;
|
|
|
|
@@ -511,8 +511,8 @@ static int getFD(StringRef Filename, std::error_code &EC,
|
|
}
|
|
|
|
raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
|
|
- sys::fs::OpenFlags Flags)
|
|
- : raw_fd_ostream(getFD(Filename, EC, Flags), true) {}
|
|
+ sys::fs::OpenFlags Flags, unsigned Mode)
|
|
+ : raw_fd_ostream(getFD(Filename, EC, Flags, Mode), true) {}
|
|
|
|
/// FD is the file descriptor that this writes to. If ShouldClose is true, this
|
|
/// closes the file when the stream is destroyed.
|
|
diff --git a/lib/Target/X86/CMakeLists.txt b/lib/Target/X86/CMakeLists.txt
|
|
index ed79f4fec4e..95cb71fb867 100644
|
|
--- a/lib/Target/X86/CMakeLists.txt
|
|
+++ b/lib/Target/X86/CMakeLists.txt
|
|
@@ -19,6 +19,7 @@ if (X86_GEN_FOLD_TABLES)
|
|
endif()
|
|
|
|
add_public_tablegen_target(X86CommonTableGen)
|
|
+add_public_tablegen_target(X86GenInstrInfo)
|
|
|
|
set(sources
|
|
X86AsmPrinter.cpp
|
|
diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp
|
|
index c58254ae38c..ab9241e5530 100644
|
|
--- a/lib/Target/X86/Disassembler/X86Disassembler.cpp
|
|
+++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp
|
|
@@ -247,6 +247,8 @@ MCDisassembler::DecodeStatus X86GenericDisassembler::getInstruction(
|
|
// It should not be 'pause' f3 90
|
|
InternalInstr.opcode != 0x90)
|
|
Flags |= X86::IP_HAS_REPEAT;
|
|
+ if (InternalInstr.hasLockPrefix)
|
|
+ Flags |= X86::IP_HAS_LOCK;
|
|
}
|
|
Instr.setFlags(Flags);
|
|
}
|
|
diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
|
|
index 6a10278dc7f..626b1439871 100644
|
|
--- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
|
|
+++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
|
|
@@ -298,6 +298,9 @@ static bool isREX(struct InternalInstruction *insn, uint8_t prefix) {
|
|
static void setPrefixPresent(struct InternalInstruction *insn, uint8_t prefix) {
|
|
uint8_t nextByte;
|
|
switch (prefix) {
|
|
+ case 0xf0:
|
|
+ insn->hasLockPrefix = true;
|
|
+ break;
|
|
case 0xf2:
|
|
case 0xf3:
|
|
if (lookAtByte(insn, &nextByte))
|
|
@@ -1748,7 +1751,7 @@ static int readOperands(struct InternalInstruction* insn) {
|
|
|
|
// If sibIndex was set to SIB_INDEX_NONE, index offset is 4.
|
|
if (insn->sibIndex == SIB_INDEX_NONE)
|
|
- insn->sibIndex = (SIBIndex)4;
|
|
+ insn->sibIndex = (SIBIndex)(insn->sibIndexBase + 4);
|
|
|
|
// If EVEX.v2 is set this is one of the 16-31 registers.
|
|
if (insn->vectorExtensionType == TYPE_EVEX &&
|
|
diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
|
|
index 44422a95f16..d60aa3fd198 100644
|
|
--- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
|
|
+++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
|
|
@@ -563,6 +563,8 @@ struct InternalInstruction {
|
|
bool hasAdSize;
|
|
// Operand-size override
|
|
bool hasOpSize;
|
|
+ // Lock prefix
|
|
+ bool hasLockPrefix;
|
|
// The repeat prefix if any
|
|
uint8_t repeatPrefix;
|
|
|
|
diff --git a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
|
|
index fa7c352a1b6..35d28c19fc2 100644
|
|
--- a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
|
|
+++ b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
|
|
@@ -46,6 +46,8 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T) {
|
|
|
|
TextAlignFillValue = 0x90;
|
|
|
|
+ TrapFillValue = 0xCC;
|
|
+
|
|
if (!is64Bit)
|
|
Data64bitsDirective = nullptr; // we can't emit a 64-bit unit
|
|
|
|
@@ -98,6 +100,8 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) {
|
|
|
|
TextAlignFillValue = 0x90;
|
|
|
|
+ TrapFillValue = 0xCC;
|
|
+
|
|
// Debug Information
|
|
SupportsDebugInformation = true;
|
|
|
|
@@ -141,6 +145,8 @@ X86MCAsmInfoMicrosoft::X86MCAsmInfoMicrosoft(const Triple &Triple) {
|
|
|
|
TextAlignFillValue = 0x90;
|
|
|
|
+ TrapFillValue = 0xCC;
|
|
+
|
|
AllowAtInName = true;
|
|
|
|
UseIntegratedAssembler = true;
|
|
@@ -164,5 +170,7 @@ X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple &Triple) {
|
|
|
|
TextAlignFillValue = 0x90;
|
|
|
|
+ TrapFillValue = 0xCC;
|
|
+
|
|
UseIntegratedAssembler = true;
|
|
}
|
|
diff --git a/lib/Target/X86/X86InstrControl.td b/lib/Target/X86/X86InstrControl.td
|
|
index 9fba65c6cf6..1c8eb2708fc 100644
|
|
--- a/lib/Target/X86/X86InstrControl.td
|
|
+++ b/lib/Target/X86/X86InstrControl.td
|
|
@@ -200,7 +200,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
|
|
}
|
|
|
|
// Loop instructions
|
|
-let SchedRW = [WriteJump] in {
|
|
+let isBranch = 1, isTerminator = 1, SchedRW = [WriteJump] in {
|
|
def LOOP : Ii8PCRel<0xE2, RawFrm, (outs), (ins brtarget8:$dst), "loop\t$dst", [], IIC_LOOP>;
|
|
def LOOPE : Ii8PCRel<0xE1, RawFrm, (outs), (ins brtarget8:$dst), "loope\t$dst", [], IIC_LOOPE>;
|
|
def LOOPNE : Ii8PCRel<0xE0, RawFrm, (outs), (ins brtarget8:$dst), "loopne\t$dst", [], IIC_LOOPNE>;
|
|
@@ -299,12 +299,13 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
|
|
(ins i32imm_pcrel:$dst),
|
|
"jmp\t$dst",
|
|
[], IIC_JMP_REL>;
|
|
-
|
|
- def TAILJMPr : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst),
|
|
- "", [], IIC_JMP_REG>; // FIXME: Remove encoding when JIT is dead.
|
|
- let mayLoad = 1 in
|
|
- def TAILJMPm : I<0xFF, MRM4m, (outs), (ins i32mem_TC:$dst),
|
|
- "jmp{l}\t{*}$dst", [], IIC_JMP_MEM>;
|
|
+ let isIndirectBranch = 1 in {
|
|
+ def TAILJMPr : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst),
|
|
+ "jmp{l}\t{*}$dst", [], IIC_JMP_REG>; // FIXME: Remove encoding when JIT is dead.
|
|
+ let mayLoad = 1 in
|
|
+ def TAILJMPm : I<0xFF, MRM4m, (outs), (ins i32mem_TC:$dst),
|
|
+ "jmp{l}\t{*}$dst", [], IIC_JMP_MEM>;
|
|
+ }
|
|
}
|
|
|
|
// Conditional tail calls are similar to the above, but they are branches
|
|
diff --git a/lib/Target/X86/X86InstrSystem.td b/lib/Target/X86/X86InstrSystem.td
|
|
index f25f1b0e8e4..8a369331256 100644
|
|
--- a/lib/Target/X86/X86InstrSystem.td
|
|
+++ b/lib/Target/X86/X86InstrSystem.td
|
|
@@ -29,7 +29,8 @@ let mayLoad = 1, mayStore = 0, hasSideEffects = 1 in {
|
|
def UD2B : I<0xB9, RawFrm, (outs), (ins), "ud2b", []>, TB;
|
|
}
|
|
|
|
-def HLT : I<0xF4, RawFrm, (outs), (ins), "hlt", [], IIC_HLT>;
|
|
+let isTerminator = 1 in
|
|
+ def HLT : I<0xF4, RawFrm, (outs), (ins), "hlt", [], IIC_HLT>;
|
|
def RSM : I<0xAA, RawFrm, (outs), (ins), "rsm", [], IIC_RSM>, TB;
|
|
|
|
// Interrupt and SysCall Instructions.
|