From 4b63d2ae1dd1cedbb0b2a61fa0da9559043dfabb Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Fri, 18 May 2012 19:12:01 +0000 Subject: [PATCH] Refactor data-in-code annotations. Use a dedicated MachO load command to annotate data-in-code regions. This is the same format the linker produces for final executable images, allowing consistency of representation and use of introspection tools for both object and executable files. Data-in-code regions are annotated via ".data_region"/".end_data_region" directive pairs, with an optional region type. data_region_directive := ".data_region" { region_type } region_type := "jt8" | "jt16" | "jt32" | "jta32" end_data_region_directive := ".end_data_region" The previous handling of ARM-style "$d.*" labels was broken and has been removed. Specifically, it didn't handle ARM vs. Thumb mode when marking the end of the section. rdar://11459456 llvm-svn: 157062 --- llvm/include/llvm/MC/MCAsmInfo.h | 28 ++----- llvm/include/llvm/MC/MCAssembler.h | 42 +++++++++++ llvm/include/llvm/MC/MCContext.h | 4 + llvm/include/llvm/MC/MCDirectives.h | 8 ++ llvm/include/llvm/MC/MCMachObjectWriter.h | 3 + llvm/include/llvm/MC/MCStreamer.h | 55 +------------- llvm/include/llvm/Object/MachOFormat.h | 18 ++++- llvm/include/llvm/Object/MachOObject.h | 3 + llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 13 +--- llvm/lib/MC/MCAsmInfo.cpp | 7 +- llvm/lib/MC/MCAsmInfoCOFF.cpp | 2 - llvm/lib/MC/MCAsmInfoDarwin.cpp | 7 -- llvm/lib/MC/MCAsmStreamer.cpp | 16 ++++ llvm/lib/MC/MCELFStreamer.cpp | 2 + llvm/lib/MC/MCMachOStreamer.cpp | 44 ++++++++++- llvm/lib/MC/MCParser/DarwinAsmParser.cpp | 42 +++++++++++ llvm/lib/MC/MCStreamer.cpp | 89 +---------------------- llvm/lib/MC/MachObjectWriter.cpp | 53 +++++++++++++- llvm/lib/Object/MachOObject.cpp | 13 ++++ llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 55 ++++++++------ llvm/lib/Target/ARM/ARMAsmPrinter.h | 6 +- llvm/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp | 1 + llvm/lib/Target/X86/X86MCInstLower.cpp | 2 - llvm/test/CodeGen/ARM/data-in-code-annotations.ll | 42 +++++++++++ llvm/test/CodeGen/Thumb2/thumb2-tbb.ll | 4 +- llvm/test/MC/ARM/elf-reloc-01.ll | 2 +- llvm/test/MC/MachO/ARM/data-in-code.s | 33 +++++++++ llvm/tools/macho-dump/macho-dump.cpp | 32 ++++++++ 28 files changed, 411 insertions(+), 215 deletions(-) create mode 100644 llvm/test/CodeGen/ARM/data-in-code-annotations.ll create mode 100644 llvm/test/MC/MachO/ARM/data-in-code.s diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h index 16964c3..ae0dad2 100644 --- a/llvm/include/llvm/MC/MCAsmInfo.h +++ b/llvm/include/llvm/MC/MCAsmInfo.h @@ -147,6 +147,11 @@ namespace llvm { // FIXME: Make this a more general encoding setting? bool AllowUTF8; + /// UseDataRegionDirectives - This is true if data region markers should + /// be printed as ".data_region/.end_data_region" directives. If false, + /// use "$d/$a" labels instead. + bool UseDataRegionDirectives; + //===--- Data Emission Directives -------------------------------------===// /// ZeroDirective - this should be set to the directive used to get some @@ -172,18 +177,6 @@ namespace llvm { const char *Data32bitsDirective; // Defaults to "\t.long\t" const char *Data64bitsDirective; // Defaults to "\t.quad\t" - /// [Data|Code]Begin - These magic labels are used to marked a region as - /// data or code, and are used to provide additional information for - /// correct disassembly on targets that like to mix data and code within - /// a segment. These labels will be implicitly suffixed by the streamer - /// to give them unique names. - const char *DataBegin; // Defaults to "$d." - const char *CodeBegin; // Defaults to "$a." - const char *JT8Begin; // Defaults to "$a." - const char *JT16Begin; // Defaults to "$a." - const char *JT32Begin; // Defaults to "$a." - bool SupportsDataRegions; - /// GPRel64Directive - if non-null, a directive that is used to emit a word /// which should be relocated as a 64-bit GP-relative offset, e.g. .gpdword /// on Mips. @@ -384,14 +377,6 @@ namespace llvm { const char *getGPRel64Directive() const { return GPRel64Directive; } const char *getGPRel32Directive() const { return GPRel32Directive; } - /// [Code|Data]Begin label name accessors. - const char *getCodeBeginLabelName() const { return CodeBegin; } - const char *getDataBeginLabelName() const { return DataBegin; } - const char *getJumpTable8BeginLabelName() const { return JT8Begin; } - const char *getJumpTable16BeginLabelName() const { return JT16Begin; } - const char *getJumpTable32BeginLabelName() const { return JT32Begin; } - bool getSupportsDataRegions() const { return SupportsDataRegions; } - /// getNonexecutableStackSection - Targets can implement this method to /// specify a section to switch to if the translation unit doesn't have any /// trampolines that require an executable stack. @@ -488,6 +473,9 @@ namespace llvm { bool doesAllowUTF8() const { return AllowUTF8; } + bool doesSupportDataRegionDirectives() const { + return UseDataRegionDirectives; + } const char *getZeroDirective() const { return ZeroDirective; } diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index d139173..4ab7f91 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -651,6 +651,16 @@ struct IndirectSymbolData { MCSectionData *SectionData; }; +// FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk +// to one another. +struct DataRegionData { + // This enum should be kept in sync w/ the mach-o definition in + // llvm/Object/MachOFormat.h. + enum KindTy { Data = 1, JumpTable8, JumpTable16, JumpTable32 } Kind; + MCSymbol *Start; + MCSymbol *End; +}; + class MCAssembler { friend class MCAsmLayout; @@ -668,6 +678,10 @@ public: const_indirect_symbol_iterator; typedef std::vector::iterator indirect_symbol_iterator; + typedef std::vector::const_iterator + const_data_region_iterator; + typedef std::vector::iterator data_region_iterator; + private: MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT void operator=(const MCAssembler&); // DO NOT IMPLEMENT @@ -698,6 +712,7 @@ private: std::vector IndirectSymbols; + std::vector DataRegions; /// The set of function symbols for which a .thumb_func directive has /// been seen. // @@ -884,6 +899,33 @@ public: size_t indirect_symbol_size() const { return IndirectSymbols.size(); } /// @} + /// @name Data Region List Access + /// @{ + + // FIXME: This is a total hack, this should not be here. Once things are + // factored so that the streamer has direct access to the .o writer, it can + // disappear. + std::vector &getDataRegions() { + return DataRegions; + } + + data_region_iterator data_region_begin() { + return DataRegions.begin(); + } + const_data_region_iterator data_region_begin() const { + return DataRegions.begin(); + } + + data_region_iterator data_region_end() { + return DataRegions.end(); + } + const_data_region_iterator data_region_end() const { + return DataRegions.end(); + } + + size_t data_region_size() const { return DataRegions.size(); } + + /// @} /// @name Backend Data Access /// @{ diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index b586319..59545d3 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -161,6 +161,10 @@ namespace llvm { /// with a unique but unspecified name. MCSymbol *CreateTempSymbol(); + /// getUniqueSymbolID() - Return a unique identifier for use in constructing + /// symbol names. + unsigned getUniqueSymbolID() { return NextUniqueID++; } + /// CreateDirectionalLocalSymbol - Create the definition of a directional /// local symbol for numbered label (used for "1:" definitions). MCSymbol *CreateDirectionalLocalSymbol(int64_t LocalLabelVal); diff --git a/llvm/include/llvm/MC/MCDirectives.h b/llvm/include/llvm/MC/MCDirectives.h index 9180d1b..0461766 100644 --- a/llvm/include/llvm/MC/MCDirectives.h +++ b/llvm/include/llvm/MC/MCDirectives.h @@ -52,6 +52,14 @@ enum MCAssemblerFlag { MCAF_Code64 ///< .code64 (X86) }; +enum MCDataRegionType { + MCDR_DataRegion, ///< .data_region + MCDR_DataRegionJT8, ///< .data_region jt8 + MCDR_DataRegionJT16, ///< .data_region jt16 + MCDR_DataRegionJT32, ///< .data_region jt32 + MCDR_DataRegionEnd ///< .end_data_region +}; + } // end namespace llvm #endif diff --git a/llvm/include/llvm/MC/MCMachObjectWriter.h b/llvm/include/llvm/MC/MCMachObjectWriter.h index 9bb598f..949d907 100644 --- a/llvm/include/llvm/MC/MCMachObjectWriter.h +++ b/llvm/include/llvm/MC/MCMachObjectWriter.h @@ -179,6 +179,9 @@ public: void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout); + void WriteLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset, + uint32_t DataSize); + // FIXME: We really need to improve the relocation validation. Basically, we // want to implement a separate computation which evaluates the relocation // entry as the linker would, and verifies that the resultant fixup value is diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 2595600..44c5fef 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -69,22 +69,7 @@ namespace llvm { SmallVector, 4> SectionStack; - unsigned UniqueCodeBeginSuffix; - unsigned UniqueDataBeginSuffix; - protected: - /// Indicator of whether the previous data-or-code indicator was for - /// code or not. Used to determine when we need to emit a new indicator. - enum DataType { - Data, - Code, - JumpTable8, - JumpTable16, - JumpTable32 - }; - DataType RegionIndicator; - - MCStreamer(MCContext &Ctx); const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, @@ -241,47 +226,15 @@ namespace llvm { /// used in an assignment. virtual void EmitLabel(MCSymbol *Symbol); - /// EmitDataRegion - Emit a label that marks the beginning of a data - /// region. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitDataRegion(); - - /// EmitJumpTable8Region - Emit a label that marks the beginning of a - /// jump table composed of 8-bit offsets. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitJumpTable8Region(); - - /// EmitJumpTable16Region - Emit a label that marks the beginning of a - /// jump table composed of 16-bit offsets. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitJumpTable16Region(); - - /// EmitJumpTable32Region - Emit a label that marks the beginning of a - /// jump table composed of 32-bit offsets. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitJumpTable32Region(); - - /// EmitCodeRegion - Emit a label that marks the beginning of a code - /// region. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $a.1: - virtual void EmitCodeRegion(); - - /// ForceCodeRegion - Forcibly sets the current region mode to code. Used - /// at function entry points. - void ForceCodeRegion() { RegionIndicator = Code; } - - virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); - /// EmitAssemblerFlag - Note in the output the specified @p Flag + /// EmitAssemblerFlag - Note in the output the specified @p Flag. virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; + /// EmitDataRegion - Note in the output the specified region @p Kind. + virtual void EmitDataRegion(MCDataRegionType Kind) {} + /// EmitThumbFunc - Note in the output that the specified @p Func is /// a Thumb mode function (ARM target only). virtual void EmitThumbFunc(MCSymbol *Func) = 0; diff --git a/llvm/include/llvm/Object/MachOFormat.h b/llvm/include/llvm/Object/MachOFormat.h index 089cde9..f30d431 100644 --- a/llvm/include/llvm/Object/MachOFormat.h +++ b/llvm/include/llvm/Object/MachOFormat.h @@ -97,7 +97,8 @@ namespace macho { DysymtabLoadCommandSize = 80, Nlist32Size = 12, Nlist64Size = 16, - RelocationInfoSize = 8 + RelocationInfoSize = 8, + LinkeditLoadCommandSize = 16 }; /// \brief Constants for header magic field. @@ -140,7 +141,8 @@ namespace macho { LCT_UUID = 0x1b, LCT_CodeSignature = 0x1d, LCT_SegmentSplitInfo = 0x1e, - LCT_FunctionStarts = 0x26 + LCT_FunctionStarts = 0x26, + LCT_DataInCode = 0x29 }; /// \brief Load command structure. @@ -280,6 +282,18 @@ namespace macho { }; /// @} + /// @name Data-in-code Table Entry + /// @{ + + // See . + enum DataRegionType { Data = 1, JumpTable8, JumpTable16, JumpTable32 }; + struct DataInCodeTableEntry { + uint32_t Offset; /* from mach_header to start of data region */ + uint16_t Length; /* number of bytes in data region */ + uint16_t Kind; /* a DataRegionType value */ + }; + + /// @} /// @name Indirect Symbol Table /// @{ diff --git a/llvm/include/llvm/Object/MachOObject.h b/llvm/include/llvm/Object/MachOObject.h index 0560402..86f150a 100644 --- a/llvm/include/llvm/Object/MachOObject.h +++ b/llvm/include/llvm/Object/MachOObject.h @@ -174,6 +174,9 @@ public: void ReadSymbol64TableEntry( uint64_t SymbolTableOffset, unsigned Index, InMemoryStruct &Res) const; + void ReadDataInCodeTableEntry( + uint64_t TableOffset, unsigned Index, + InMemoryStruct &Res) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; /// @} diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index b0b2ff4..ae498dd 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -475,10 +475,8 @@ void AsmPrinter::EmitFunctionHeader() { void AsmPrinter::EmitFunctionEntryLabel() { // The function label could have already been emitted if two symbols end up // conflicting due to asm renaming. Detect this and emit an error. - if (CurrentFnSym->isUndefined()) { - OutStreamer.ForceCodeRegion(); + if (CurrentFnSym->isUndefined()) return OutStreamer.EmitLabel(CurrentFnSym); - } report_fatal_error("'" + Twine(CurrentFnSym->getName()) + "' label emitted multiple times to assembly file"); @@ -1085,15 +1083,6 @@ void AsmPrinter::EmitJumpTableInfo() { EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData()))); - // If we know the form of the jump table, go ahead and tag it as such. - if (!JTInDiffSection) { - if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32) { - OutStreamer.EmitJumpTable32Region(); - } else { - OutStreamer.EmitDataRegion(); - } - } - for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) { const std::vector &JTBBs = JT[JTI].MBBs; diff --git a/llvm/lib/MC/MCAsmInfo.cpp b/llvm/lib/MC/MCAsmInfo.cpp index 2456858..d9c1d51 100644 --- a/llvm/lib/MC/MCAsmInfo.cpp +++ b/llvm/lib/MC/MCAsmInfo.cpp @@ -50,6 +50,7 @@ MCAsmInfo::MCAsmInfo() { AllowNameToStartWithDigit = false; AllowPeriodsInName = true; AllowUTF8 = true; + UseDataRegionDirectives = false; ZeroDirective = "\t.zero\t"; AsciiDirective = "\t.ascii\t"; AscizDirective = "\t.asciz\t"; @@ -57,12 +58,6 @@ MCAsmInfo::MCAsmInfo() { Data16bitsDirective = "\t.short\t"; Data32bitsDirective = "\t.long\t"; Data64bitsDirective = "\t.quad\t"; - DataBegin = "$d."; - CodeBegin = "$a."; - JT8Begin = "$d."; - JT16Begin = "$d."; - JT32Begin = "$d."; - SupportsDataRegions = false; SunStyleELFSectionSwitchSyntax = false; UsesELFSectionDirectiveForBSS = false; AlignDirective = "\t.align\t"; diff --git a/llvm/lib/MC/MCAsmInfoCOFF.cpp b/llvm/lib/MC/MCAsmInfoCOFF.cpp index 8941365..678e75a 100644 --- a/llvm/lib/MC/MCAsmInfoCOFF.cpp +++ b/llvm/lib/MC/MCAsmInfoCOFF.cpp @@ -36,8 +36,6 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() { SupportsDebugInformation = true; DwarfSectionOffsetDirective = "\t.secrel32\t"; HasMicrosoftFastStdCallMangling = true; - - SupportsDataRegions = false; } void MCAsmInfoMicrosoft::anchor() { } diff --git a/llvm/lib/MC/MCAsmInfoDarwin.cpp b/llvm/lib/MC/MCAsmInfoDarwin.cpp index 4d67592..73ef7ba 100644 --- a/llvm/lib/MC/MCAsmInfoDarwin.cpp +++ b/llvm/lib/MC/MCAsmInfoDarwin.cpp @@ -43,13 +43,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { HasMachoTBSSDirective = true; // Uses .tbss HasStaticCtorDtorReferenceInStaticMode = true; - CodeBegin = "L$start$code$"; - DataBegin = "L$start$data$"; - JT8Begin = "L$start$jt8$"; - JT16Begin = "L$start$jt16$"; - JT32Begin = "L$start$jt32$"; - SupportsDataRegions = true; - // FIXME: Darwin 10 and newer don't need this. LinkerRequiresNonEmptyDwarfLines = true; diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 3ce84c2..9497b6b 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -138,6 +138,7 @@ public: virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitDataRegion(MCDataRegionType Kind); virtual void EmitThumbFunc(MCSymbol *Func); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); @@ -352,6 +353,21 @@ void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { EmitEOL(); } +void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { + MCContext &Ctx = getContext(); + const MCAsmInfo &MAI = Ctx.getAsmInfo(); + if (!MAI.doesSupportDataRegionDirectives()) + return; + switch (Kind) { + case MCDR_DataRegion: OS << "\t.data_region"; break; + case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break; + case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break; + case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break; + case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break; + } + EmitEOL(); +} + void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) { // This needs to emit to a temporary string to get properly quoted // MCSymbols when they have spaces in them. diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index 6c4d0e3..6ac9d9d 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -13,6 +13,8 @@ #include "MCELF.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp index bc6cf77..970aa8b 100644 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -1,4 +1,3 @@ -//===- lib/MC/MCMachOStreamer.cpp - Mach-O Object Output ------------===// // // The LLVM Compiler Infrastructure // @@ -33,6 +32,8 @@ class MCMachOStreamer : public MCObjectStreamer { private: virtual void EmitInstToData(const MCInst &Inst); + void EmitDataRegion(DataRegionData::KindTy Kind); + void EmitDataRegionEnd(); public: MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *Emitter) @@ -46,6 +47,7 @@ public: virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitDataRegion(MCDataRegionType Kind); virtual void EmitThumbFunc(MCSymbol *Func); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); @@ -138,6 +140,26 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { SD.setFlags(SD.getFlags() & ~SF_ReferenceTypeMask); } +void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) { + // Create a temporary label to mark the start of the data region. + MCSymbol *Start = getContext().CreateTempSymbol(); + EmitLabel(Start); + // Record the region for the object writer to use. + DataRegionData Data = { Kind, Start, NULL }; + std::vector &Regions = getAssembler().getDataRegions(); + Regions.push_back(Data); +} + +void MCMachOStreamer::EmitDataRegionEnd() { + std::vector &Regions = getAssembler().getDataRegions(); + assert(Regions.size() && "Mismatched .end_data_region!"); + DataRegionData &Data = Regions.back(); + assert(Data.End == NULL && "Mismatched .end_data_region!"); + // Create a temporary label to mark the end of the data region. + Data.End = getContext().CreateTempSymbol(); + EmitLabel(Data.End); +} + void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { // Let the target do whatever target specific stuff it needs to do. getAssembler().getBackend().handleAssemblerFlag(Flag); @@ -153,6 +175,26 @@ void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { } } +void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) { + switch (Kind) { + case MCDR_DataRegion: + EmitDataRegion(DataRegionData::Data); + return; + case MCDR_DataRegionJT8: + EmitDataRegion(DataRegionData::JumpTable8); + return; + case MCDR_DataRegionJT16: + EmitDataRegion(DataRegionData::JumpTable16); + return; + case MCDR_DataRegionJT32: + EmitDataRegion(DataRegionData::JumpTable32); + return; + case MCDR_DataRegionEnd: + EmitDataRegionEnd(); + return; + } +} + void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) { // Remember that the function is a thumb function. Fixup and relocation // values will need adjusted. diff --git a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp index 6f45068..5662fea 100644 --- a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp @@ -14,6 +14,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/MemoryBuffer.h" @@ -56,6 +57,9 @@ public: AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveTBSS>(".tbss"); AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveZerofill>(".zerofill"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegion>(".data_region"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegionEnd>(".end_data_region"); + // Special section directives. AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConst>(".const"); AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstData>(".const_data"); @@ -113,6 +117,8 @@ public: bool ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc); bool ParseDirectiveTBSS(StringRef, SMLoc); bool ParseDirectiveZerofill(StringRef, SMLoc); + bool ParseDirectiveDataRegion(StringRef, SMLoc); + bool ParseDirectiveDataRegionEnd(StringRef, SMLoc); // Named Section Directive bool ParseSectionDirectiveConst(StringRef, SMLoc) { @@ -659,6 +665,42 @@ bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { return false; } +/// ParseDirectiveDataRegion +/// ::= .data_region [ ( jt8 | jt16 | jt32 ) ] +bool DarwinAsmParser::ParseDirectiveDataRegion(StringRef, SMLoc) { + if (getLexer().is(AsmToken::EndOfStatement)) { + Lex(); + getStreamer().EmitDataRegion(MCDR_DataRegion); + return false; + } + StringRef RegionType; + SMLoc Loc = getParser().getTok().getLoc(); + if (getParser().ParseIdentifier(RegionType)) + return TokError("expected region type after '.data_region' directive"); + int Kind = StringSwitch(RegionType) + .Case("jt8", MCDR_DataRegionJT8) + .Case("jt16", MCDR_DataRegionJT16) + .Case("jt32", MCDR_DataRegionJT32) + .Default(-1); + if (Kind == -1) + return Error(Loc, "unknown region type in '.data_region' directive"); + Lex(); + + getStreamer().EmitDataRegion((MCDataRegionType)Kind); + return false; +} + +/// ParseDirectiveDataRegionEnd +/// ::= .end_data_region +bool DarwinAsmParser::ParseDirectiveDataRegionEnd(StringRef, SMLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.end_data_region' directive"); + + Lex(); + getStreamer().EmitDataRegion(MCDR_DataRegionEnd); + return false; +} + namespace llvm { MCAsmParserExtension *createDarwinAsmParser() { diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 43e62ff..e363f28 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -20,12 +20,9 @@ #include using namespace llvm; -MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), EmitEHFrame(true), - EmitDebugFrame(false), - CurrentW64UnwindInfo(0), - LastSymbol(0), - UniqueCodeBeginSuffix(0), - UniqueDataBeginSuffix(0) { +MCStreamer::MCStreamer(MCContext &Ctx) + : Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false), + CurrentW64UnwindInfo(0), LastSymbol(0) { const MCSection *section = NULL; SectionStack.push_back(std::make_pair(section, section)); } @@ -183,85 +180,6 @@ void MCStreamer::EmitLabel(MCSymbol *Symbol) { LastSymbol = Symbol; } -void MCStreamer::EmitDataRegion() { - if (RegionIndicator == Data) return; - - MCContext &Context = getContext(); - const MCAsmInfo &MAI = Context.getAsmInfo(); - if (!MAI.getSupportsDataRegions()) return; - - // Generate a unique symbol name. - MCSymbol *NewSym = Context.GetOrCreateSymbol(MAI.getDataBeginLabelName() + - Twine(UniqueDataBeginSuffix++)); - EmitLabel(NewSym); - - RegionIndicator = Data; -} - -void MCStreamer::EmitCodeRegion() { - if (RegionIndicator == Code) return; - - MCContext &Context = getContext(); - const MCAsmInfo &MAI = Context.getAsmInfo(); - if (!MAI.getSupportsDataRegions()) return; - - // Generate a unique symbol name. - MCSymbol *NewSym = Context.GetOrCreateSymbol(MAI.getCodeBeginLabelName() + - Twine(UniqueCodeBeginSuffix++)); - EmitLabel(NewSym); - - RegionIndicator = Code; -} - -void MCStreamer::EmitJumpTable8Region() { - if (RegionIndicator == JumpTable8) return; - - MCContext &Context = getContext(); - const MCAsmInfo &MAI = Context.getAsmInfo(); - if (!MAI.getSupportsDataRegions()) return; - - // Generate a unique symbol name. - MCSymbol *NewSym = - Context.GetOrCreateSymbol(MAI.getJumpTable8BeginLabelName() + - Twine(UniqueDataBeginSuffix++)); - EmitLabel(NewSym); - - RegionIndicator = JumpTable8; -} - -void MCStreamer::EmitJumpTable16Region() { - if (RegionIndicator == JumpTable16) return; - - MCContext &Context = getContext(); - const MCAsmInfo &MAI = Context.getAsmInfo(); - if (!MAI.getSupportsDataRegions()) return; - - // Generate a unique symbol name. - MCSymbol *NewSym = - Context.GetOrCreateSymbol(MAI.getJumpTable16BeginLabelName() + - Twine(UniqueDataBeginSuffix++)); - EmitLabel(NewSym); - - RegionIndicator = JumpTable16; -} - - -void MCStreamer::EmitJumpTable32Region() { - if (RegionIndicator == JumpTable32) return; - - MCContext &Context = getContext(); - const MCAsmInfo &MAI = Context.getAsmInfo(); - if (!MAI.getSupportsDataRegions()) return; - - // Generate a unique symbol name. - MCSymbol *NewSym = - Context.GetOrCreateSymbol(MAI.getJumpTable32BeginLabelName() + - Twine(UniqueDataBeginSuffix++)); - EmitLabel(NewSym); - - RegionIndicator = JumpTable32; -} - void MCStreamer::EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); @@ -283,7 +201,6 @@ void MCStreamer::EmitCFIStartProc() { EmitCFIStartProcImpl(Frame); FrameInfos.push_back(Frame); - RegionIndicator = Code; } void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp index 8e4066c..5820a22 100644 --- a/llvm/lib/MC/MachObjectWriter.cpp +++ b/llvm/lib/MC/MachObjectWriter.cpp @@ -21,6 +21,7 @@ #include "llvm/MC/MCMachOSymbolFlags.h" #include "llvm/MC/MCValue.h" #include "llvm/Object/MachOFormat.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include @@ -351,6 +352,21 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, Write32(Address); } +void MachObjectWriter::WriteLinkeditLoadCommand(uint32_t Type, + uint32_t DataOffset, + uint32_t DataSize) { + uint64_t Start = OS.tell(); + (void) Start; + + Write32(Type); + Write32(macho::LinkeditLoadCommandSize); + Write32(DataOffset); + Write32(DataSize); + + assert(OS.tell() - Start == macho::LinkeditLoadCommandSize); +} + + void MachObjectWriter::RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, @@ -654,6 +670,13 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, macho::DysymtabLoadCommandSize); } + // Add the data-in-code load command size, if used. + unsigned NumDataRegions = Asm.getDataRegions().size(); + if (NumDataRegions) { + ++NumLoadCommands; + LoadCommandsSize += macho::LinkeditLoadCommandSize; + } + // Compute the total size of the section data, as well as its file size and vm // size. uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size : @@ -701,6 +724,15 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, RelocTableEnd += NumRelocs * macho::RelocationInfoSize; } + // Write the data-in-code load command, if used. + uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8; + if (NumDataRegions) { + uint64_t DataRegionsOffset = RelocTableEnd; + uint64_t DataRegionsSize = NumDataRegions * 8; + WriteLinkeditLoadCommand(macho::LCT_DataInCode, DataRegionsOffset, + DataRegionsSize); + } + // Write the symbol table load command, if used. if (NumSymbols) { unsigned FirstLocalSymbol = 0; @@ -717,10 +749,10 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, // If used, the indirect symbols are written after the section data. if (NumIndirectSymbols) - IndirectSymbolOffset = RelocTableEnd; + IndirectSymbolOffset = DataInCodeTableEnd; // The symbol table is written after the indirect symbol data. - uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize; + uint64_t SymbolTableOffset = DataInCodeTableEnd + IndirectSymbolSize; // The string table is written after symbol table. uint64_t StringTableOffset = @@ -760,6 +792,23 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, } } + // Write out the data-in-code region payload, if there is one. + for (MCAssembler::const_data_region_iterator + it = Asm.data_region_begin(), ie = Asm.data_region_end(); + it != ie; ++it) { + const DataRegionData *Data = &(*it); + uint64_t Start = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->Start), Layout); + uint64_t End = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->End), Layout); + DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind + << " start: " << Start << "(" << Data->Start->getName() << ")" + << " end: " << End << "(" << Data->End->getName() << ")" + << " size: " << End - Start + << "\n"); + Write32(Start); + Write16(End - Start); + Write16(Data->Kind); + } + // Write the symbol table data, if used. if (NumSymbols) { // Write the indirect symbol entries. diff --git a/llvm/lib/Object/MachOObject.cpp b/llvm/lib/Object/MachOObject.cpp index b7e5cdc..00dea3f 100644 --- a/llvm/lib/Object/MachOObject.cpp +++ b/llvm/lib/Object/MachOObject.cpp @@ -357,6 +357,19 @@ void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset, ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); } +template<> +void SwapStruct(macho::DataInCodeTableEntry &Value) { + SwapValue(Value.Offset); + SwapValue(Value.Length); + SwapValue(Value.Kind); +} +void MachOObject::ReadDataInCodeTableEntry(uint64_t TableOffset, + unsigned Index, + InMemoryStruct &Res) const { + uint64_t Offset = (TableOffset + + Index * sizeof(macho::DataInCodeTableEntry)); + ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); +} void MachOObject::ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const { diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index 410790a..e781498 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -283,9 +283,16 @@ void ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const { } } -void ARMAsmPrinter::EmitFunctionEntryLabel() { - OutStreamer.ForceCodeRegion(); +void ARMAsmPrinter::EmitFunctionBodyEnd() { + // Make sure to terminate any constant pools that were at the end + // of the function. + if (!InConstantPool) + return; + InConstantPool = false; + OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); +} +void ARMAsmPrinter::EmitFunctionEntryLabel() { if (AFI->isThumbFunction()) { OutStreamer.EmitAssemblerFlag(MCAF_Code16); OutStreamer.EmitThumbFunc(CurrentFnSym); @@ -934,13 +941,13 @@ void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) { const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id unsigned JTI = MO1.getIndex(); - // Tag the jump table appropriately for precise disassembly. - OutStreamer.EmitJumpTable32Region(); - // Emit a label for the jump table. MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); OutStreamer.EmitLabel(JTISymbol); + // Mark the jump table as data-in-code. + OutStreamer.EmitDataRegion(MCDR_DataRegionJT32); + // Emit each entry of the table. const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); const std::vector &JT = MJTI->getJumpTables(); @@ -969,6 +976,8 @@ void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) { OutContext); OutStreamer.EmitValue(Expr, 4); } + // Mark the end of jump table data-in-code region. + OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); } void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) { @@ -978,15 +987,6 @@ void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) { const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id unsigned JTI = MO1.getIndex(); - // Emit a label for the jump table. - if (MI->getOpcode() == ARM::t2TBB_JT) { - OutStreamer.EmitJumpTable8Region(); - } else if (MI->getOpcode() == ARM::t2TBH_JT) { - OutStreamer.EmitJumpTable16Region(); - } else { - OutStreamer.EmitJumpTable32Region(); - } - MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); OutStreamer.EmitLabel(JTISymbol); @@ -995,10 +995,15 @@ void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) { const std::vector &JT = MJTI->getJumpTables(); const std::vector &JTBBs = JT[JTI].MBBs; unsigned OffsetWidth = 4; - if (MI->getOpcode() == ARM::t2TBB_JT) + if (MI->getOpcode() == ARM::t2TBB_JT) { OffsetWidth = 1; - else if (MI->getOpcode() == ARM::t2TBH_JT) + // Mark the jump table as data-in-code. + OutStreamer.EmitDataRegion(MCDR_DataRegionJT8); + } else if (MI->getOpcode() == ARM::t2TBH_JT) { OffsetWidth = 2; + // Mark the jump table as data-in-code. + OutStreamer.EmitDataRegion(MCDR_DataRegionJT16); + } for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { MachineBasicBlock *MBB = JTBBs[i]; @@ -1031,6 +1036,8 @@ void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) { OutContext); OutStreamer.EmitValue(Expr, OffsetWidth); } + // Mark the end of jump table data-in-code region. + OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); } void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, @@ -1208,8 +1215,11 @@ extern cl::opt EnableARMEHABI; #include "ARMGenMCPseudoLowering.inc" void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { - if (MI->getOpcode() != ARM::CONSTPOOL_ENTRY) - OutStreamer.EmitCodeRegion(); + // If we just ended a constant pool, mark it as such. + if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) { + OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); + InConstantPool = false; + } // Emit unwinding stuff for frame-related instructions if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup)) @@ -1565,9 +1575,12 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); - // Mark the constant pool entry as data if we're not already in a data - // region. - OutStreamer.EmitDataRegion(); + // If this is the first entry of the pool, mark it. + if (!InConstantPool) { + OutStreamer.EmitDataRegion(MCDR_DataRegion); + InConstantPool = true; + } + OutStreamer.EmitLabel(GetCPISymbol(LabelId)); const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.h b/llvm/lib/Target/ARM/ARMAsmPrinter.h index af3f75a..3555e8f 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.h +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.h @@ -44,9 +44,12 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter { /// MachineFunction. const MachineConstantPool *MCP; + /// InConstantPool - Maintain state when emitting a sequence of constant + /// pool entries so we can properly mark them as data regions. + bool InConstantPool; public: explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) - : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) { + : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL), InConstantPool(false) { Subtarget = &TM.getSubtarget(); } @@ -70,6 +73,7 @@ public: bool runOnMachineFunction(MachineFunction &F); virtual void EmitConstantPool() {} // we emit constant pools customly! + virtual void EmitFunctionBodyEnd(); virtual void EmitFunctionEntryLabel(); void EmitStartOfAsmFile(Module &M); void EmitEndOfAsmFile(Module &M); diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp index 4ac7741..d32805e 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp @@ -29,6 +29,7 @@ ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() { CommentString = "@"; Code16Directive = ".code\t16"; Code32Directive = ".code\t32"; + UseDataRegionDirectives = true; SupportsDebugInformation = true; diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp index 54bfce1..2f368b6 100644 --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -610,8 +610,6 @@ static void LowerTlsAddr(MCStreamer &OutStreamer, } void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { - OutStreamer.EmitCodeRegion(); - X86MCInstLower MCInstLowering(Mang, *MF, *this); switch (MI->getOpcode()) { case TargetOpcode::DBG_VALUE: diff --git a/llvm/test/CodeGen/ARM/data-in-code-annotations.ll b/llvm/test/CodeGen/ARM/data-in-code-annotations.ll new file mode 100644 index 0000000..a66a9d1 --- /dev/null +++ b/llvm/test/CodeGen/ARM/data-in-code-annotations.ll @@ -0,0 +1,42 @@ +; RUN: llc < %s -mtriple=armv7-apple-darwin | FileCheck %s + +define double @f1() nounwind { +; CHECK: f1: +; CHECK: .data_region +; CHECK: .long 1413754129 +; CHECK: .long 1074340347 +; CHECK: .end_data_region + ret double 0x400921FB54442D11 +} + + +define i32 @f2() { +; CHECK: f2: +; CHECK: .data_region jt32 +; CHECK: .end_data_region + +entry: + switch i32 undef, label %return [ + i32 1, label %sw.bb + i32 2, label %sw.bb6 + i32 3, label %sw.bb13 + i32 4, label %sw.bb20 + ] + +sw.bb: ; preds = %entry + br label %return + +sw.bb6: ; preds = %entry + br label %return + +sw.bb13: ; preds = %entry + br label %return + +sw.bb20: ; preds = %entry + %div = sdiv i32 undef, undef + br label %return + +return: ; preds = %sw.bb20, %sw.bb13, %sw.bb6, %sw.bb, %entry + %retval.0 = phi i32 [ %div, %sw.bb20 ], [ undef, %sw.bb13 ], [ undef, %sw.bb6 ], [ undef, %sw.bb ], [ 0, %entry ] + ret i32 %retval.0 +} diff --git a/llvm/test/CodeGen/Thumb2/thumb2-tbb.ll b/llvm/test/CodeGen/Thumb2/thumb2-tbb.ll index 5dc3cc3..a9d71d6 100644 --- a/llvm/test/CodeGen/Thumb2/thumb2-tbb.ll +++ b/llvm/test/CodeGen/Thumb2/thumb2-tbb.ll @@ -5,7 +5,9 @@ define void @bar(i32 %n.u) { entry: ; CHECK: bar: ; CHECK: tbb -; CHECK: .align 1 +; CHECK: .data_region jt8 +; CHECK: .end_data_region +; CHECK-NEXT: .align 1 switch i32 %n.u, label %bb12 [i32 1, label %bb i32 2, label %bb6 i32 4, label %bb7 i32 5, label %bb8 i32 6, label %bb10 i32 7, label %bb1 i32 8, label %bb3 i32 9, label %bb4 i32 10, label %bb9 i32 11, label %bb2 i32 12, label %bb5 i32 13, label %bb11 ] bb: diff --git a/llvm/test/MC/ARM/elf-reloc-01.ll b/llvm/test/MC/ARM/elf-reloc-01.ll index 6899d92b..c98026b 100644 --- a/llvm/test/MC/ARM/elf-reloc-01.ll +++ b/llvm/test/MC/ARM/elf-reloc-01.ll @@ -61,7 +61,7 @@ bb3: ; preds = %bb, %entry declare void @exit(i32) noreturn nounwind ;; OBJ: Relocation 1 -;; OBJ-NEXT: 'r_offset', +;; OBJ-NEXT: 'r_offset', ;; OBJ-NEXT: 'r_sym', 0x000002 ;; OBJ-NEXT: 'r_type', 0x2b diff --git a/llvm/test/MC/MachO/ARM/data-in-code.s b/llvm/test/MC/MachO/ARM/data-in-code.s new file mode 100644 index 0000000..bbcb9aa --- /dev/null +++ b/llvm/test/MC/MachO/ARM/data-in-code.s @@ -0,0 +1,33 @@ +@ RUN: llvm-mc -triple armv7-apple-darwin10 -filetype=obj -o - < %s | macho-dump | FileCheck %s + .text +_foo: +@ CHECK: # DICE 0 +@ CHECK: ('offset', 0) +@ CHECK: ('length', 4) +@ CHECK: ('kind', 1) +@ CHECK: # DICE 1 +@ CHECK: ('offset', 4) +@ CHECK: ('length', 4) +@ CHECK: ('kind', 4) +@ CHECK: # DICE 2 +@ CHECK: ('offset', 8) +@ CHECK: ('length', 2) +@ CHECK: ('kind', 3) +@ CHECK: # DICE 3 +@ CHECK: ('offset', 10) +@ CHECK: ('length', 1) +@ CHECK: ('kind', 2) + +.data_region + .long 10 +.end_data_region +.data_region jt32 + .long 1 +.end_data_region +.data_region jt16 + .short 2 +.end_data_region +.data_region jt8 + .byte 3 +.end_data_region + diff --git a/llvm/tools/macho-dump/macho-dump.cpp b/llvm/tools/macho-dump/macho-dump.cpp index f65c795..20deda9 100644 --- a/llvm/tools/macho-dump/macho-dump.cpp +++ b/llvm/tools/macho-dump/macho-dump.cpp @@ -332,6 +332,35 @@ static int DumpLinkeditDataCommand(MachOObject &Obj, return 0; } +static int DumpDataInCodeDataCommand(MachOObject &Obj, + const MachOObject::LoadCommandInfo &LCI) { + InMemoryStruct LLC; + Obj.ReadLinkeditDataLoadCommand(LCI, LLC); + if (!LLC) + return Error("unable to read segment load command"); + + outs() << " ('dataoff', " << LLC->DataOffset << ")\n" + << " ('datasize', " << LLC->DataSize << ")\n" + << " ('_data_regions', [\n"; + + + unsigned NumRegions = LLC->DataSize / 8; + for (unsigned i = 0; i < NumRegions; ++i) { + InMemoryStruct DICE; + Obj.ReadDataInCodeTableEntry(LLC->DataOffset, i, DICE); + if (!DICE) + return Error("unable to read DataInCodeTableEntry"); + outs() << " # DICE " << i << "\n" + << " ('offset', " << DICE->Offset << ")\n" + << " ('length', " << DICE->Length << ")\n" + << " ('kind', " << DICE->Kind << ")\n"; + } + + outs() <<" ])\n"; + + return 0; +} + static int DumpLoadCommand(MachOObject &Obj, unsigned Index) { const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index); @@ -358,6 +387,9 @@ static int DumpLoadCommand(MachOObject &Obj, unsigned Index) { case macho::LCT_FunctionStarts: Res = DumpLinkeditDataCommand(Obj, LCI); break; + case macho::LCT_DataInCode: + Res = DumpDataInCodeDataCommand(Obj, LCI); + break; default: Warning("unknown load command: " + Twine(LCI.Command.Type)); break; -- 2.7.4