mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 00:20:25 +08:00
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. (cherry picked from FBD15064122)
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.
|