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 ByteSize) - : Attr(A), Form(F) { + AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional 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 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 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 create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr, function_ref HandleError = defaultErrorHandler, - std::string DWPName = ""); + std::string DWPName = "", bool UsesRelocs = true); static std::unique_ptr create(const StringMap> &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 #include #include @@ -279,9 +280,20 @@ public: void dump(raw_ostream &OS, const MCRegisterInfo *MRI, Optional Offset) const; + using RefHandlerType = + std::function; + /// 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(Entries.begin(), Entries.end()); } + using FDEFunction = std::function; + + /// 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 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 find(dwarf::Attribute Attr) const; + Optional 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 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 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 lookupFlags(const LookupSet &Symbols) override; Expected 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 lookupFlagsWithLegacyFn(SymbolFlagsMap &SymbolFlags, template 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 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 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 &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 &LineStr) const; + Optional &LineStr); Expected 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 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 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 { 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::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 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 dynamic_table_begin(const Elf_Phdr *Phdr) const; + Expected dynamic_table_end(const Elf_Phdr *Phdr) const; + Expected dynamic_table(const Elf_Phdr *Phdr) const { + Expected Begin = dynamic_table_begin(Phdr); + if (!Begin) + return Begin.takeError(); + Expected End = dynamic_table_end(Phdr); + if (!End) + return End.takeError(); + return makeArrayRef(Begin.get(), End.get()); + } + Expected sections() const; Expected symbols(const Elf_Shdr *Sec) const { @@ -397,6 +409,34 @@ void ELFFile::getRelocationTypeName(uint32_t Type, } template +Expected::Elf_Dyn *> +ELFFile::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("Could not read dynamic table"); + return reinterpret_cast(base() + Offset); +} + +template +Expected::Elf_Dyn *> +ELFFile::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("Invalid dynamic table size"); + // FIKME: Check for overflow? + uintX_t End = Phdr->p_offset + Size; + if (End > Buf.size()) + return make_error("Could not read dynamic table"); + return reinterpret_cast(base() + End); +} + +template Expected ELFFile::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::isSectionVirtual(DataRefImpl Sec) const { } template +bool ELFObjectFile::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 relocation_iterator ELFObjectFile::section_rel_begin(DataRefImpl Sec) const { DataRefImpl RelData; @@ -751,9 +760,6 @@ ELFObjectFile::section_rel_end(DataRefImpl Sec) const { template section_iterator ELFObjectFile::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::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::getRelocationSymbol(DataRefImpl Rel) const { template uint64_t ELFObjectFile::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(Data.getULEB128(OffsetPtr)); + uint32_t FOff = *OffsetPtr; auto F = static_cast
(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 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 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 DWARFAbbreviationDeclaration::getAttributeValue( const uint32_t DIEOffset, const dwarf::Attribute Attr, - const DWARFUnit &U) const { + const DWARFUnit &U, uint32_t *OffsetPtr) const { Optional MatchAttrIndex = findAttributeIndex(Attr); if (!MatchAttrIndex) return None; @@ -164,6 +175,8 @@ Optional 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 +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, 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 HandleError) + function_ref HandleError, + bool UsesRelocs = true) : IsLittleEndian(Obj.isLittleEndian()), AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()), - Obj(&Obj) { + Obj(&Obj), UsesRelocs(UsesRelocs) { StringMap 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 find(const DWARFSection &S, uint64_t Pos) const override { + if (!UsesRelocs) + return None; auto &Sec = static_cast(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::create(const object::ObjectFile &Obj, const LoadedObjectInfo *L, function_ref HandleError, - std::string DWPName) { - auto DObj = llvm::make_unique(Obj, L, HandleError); + std::string DWPName, bool UsesRelocs) { + auto DObj = + llvm::make_unique(Obj, L, HandleError, UsesRelocs); return llvm::make_unique(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 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 Personality; Optional 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(Entry.get())) + F(FDE); + } +} + void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI, Optional 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 DWARFDie::find(dwarf::Attribute Attr) const { +Optional 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::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(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(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(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(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(F.getNextNode())) { + OffsetToAvoid = NAF.getAlignment() - + (NextFrag->getContents().size() % NAF.getAlignment()); + } else if (const auto *NextFrag = + dyn_cast(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(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(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(F).getContents()); @@ -651,6 +708,11 @@ void MCAssembler::writeSectionData(const MCSection *Sec, cast(F).getValue() == 0) && "Invalid align in virtual section!"); break; + case MCFragment::FT_NeverAlign: + assert((cast(F).getValueSize() == 0 || + cast(F).getValue() == 0) && + "Invalid neveralign in virtual section!"); + break; case MCFragment::FT_Fill: assert((cast(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(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 &LineStr) const { - MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; + Optional &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 +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(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(this); return; + case FT_NeverAlign: + delete cast(this); + return; case FT_Data: delete cast(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(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(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(getCurrentFragment())->setEmitNops(true); } +void MCObjectStreamer::EmitNeverAlignCodeAtEnd(unsigned ByteAlignment, + int64_t Value, + unsigned ValueSize) { + insert(new MCNeverAlignFragment(ByteAlignment, 0, 1)); + cast(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()); } +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.