diff options
Diffstat (limited to 'lib/MC')
41 files changed, 2098 insertions, 635 deletions
diff --git a/lib/MC/Android.mk b/lib/MC/Android.mk index a0b77ba..6c69ca2 100644 --- a/lib/MC/Android.mk +++ b/lib/MC/Android.mk @@ -18,6 +18,7 @@ mc_SRC_FILES := \ MCELFObjectTargetWriter.cpp \ MCELFStreamer.cpp \ MCExpr.cpp \ + MCExternalSymbolizer.cpp \ MCInst.cpp \ MCInstPrinter.cpp \ MCInstrAnalysis.cpp \ @@ -29,6 +30,7 @@ mc_SRC_FILES := \ MCObjectStreamer.cpp \ MCObjectWriter.cpp \ MCRegisterInfo.cpp \ + MCRelocationInfo.cpp \ MCSection.cpp \ MCSectionCOFF.cpp \ MCSectionELF.cpp \ @@ -36,6 +38,7 @@ mc_SRC_FILES := \ MCStreamer.cpp \ MCSubtargetInfo.cpp \ MCSymbol.cpp \ + MCSymbolizer.cpp \ MCValue.cpp \ MCWin64EH.cpp \ WinCOFFObjectWriter.cpp \ diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index db882c0..89e2aaf 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -15,7 +15,9 @@ add_llvm_library(LLVMMC MCELF.cpp MCELFObjectTargetWriter.cpp MCELFStreamer.cpp + MCFunction.cpp MCExpr.cpp + MCExternalSymbolizer.cpp MCInst.cpp MCInstPrinter.cpp MCInstrAnalysis.cpp @@ -25,10 +27,13 @@ add_llvm_library(LLVMMC MCModule.cpp MCNullStreamer.cpp MCObjectFileInfo.cpp + MCObjectDisassembler.cpp MCObjectStreamer.cpp + MCObjectSymbolizer.cpp MCObjectWriter.cpp MCPureStreamer.cpp MCRegisterInfo.cpp + MCRelocationInfo.cpp MCSection.cpp MCSectionCOFF.cpp MCSectionELF.cpp @@ -36,6 +41,7 @@ add_llvm_library(LLVMMC MCStreamer.cpp MCSubtargetInfo.cpp MCSymbol.cpp + MCSymbolizer.cpp MCValue.cpp MCWin64EH.cpp MachObjectWriter.cpp diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 3d99548..2db59ac 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -759,9 +759,6 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, uint64_t RelocOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - // FIXME: no tests cover this. Is adjustFixupOffset dead code? - TargetObjectWriter->adjustFixupOffset(Fixup, RelocOffset); - if (!hasRelocationAddend()) Addend = 0; @@ -1005,11 +1002,18 @@ void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm, else EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); + unsigned Flags = 0; + StringRef Group = ""; + if (Section.getFlags() & ELF::SHF_GROUP) { + Flags = ELF::SHF_GROUP; + Group = Section.getGroup()->getName(); + } + const MCSectionELF *RelaSection = Ctx.getELFSection(RelaSectionName, hasRelocationAddend() ? - ELF::SHT_RELA : ELF::SHT_REL, 0, + ELF::SHT_RELA : ELF::SHT_REL, Flags, SectionKind::getReadOnly(), - EntrySize, ""); + EntrySize, Group); RelMap[&Section] = RelaSection; Asm.getOrCreateSectionData(*RelaSection); } diff --git a/lib/MC/MCAsmBackend.cpp b/lib/MC/MCAsmBackend.cpp index 53960e7..c4c98cc 100644 --- a/lib/MC/MCAsmBackend.cpp +++ b/lib/MC/MCAsmBackend.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCAsmBackend.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCFixupKindInfo.h" using namespace llvm; @@ -37,7 +38,6 @@ MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { { "FK_SecRel_8", 0, 64, 0 } }; - assert((size_t)Kind <= sizeof(Builtins) / sizeof(Builtins[0]) && - "Unknown fixup kind"); + assert((size_t)Kind <= array_lengthof(Builtins) && "Unknown fixup kind"); return Builtins[Kind]; } diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index 51bb435..84e4075 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -34,6 +34,7 @@ MCAsmInfo::MCAsmInfo() { HasStaticCtorDtorReferenceInStaticMode = false; LinkerRequiresNonEmptyDwarfLines = false; MaxInstLength = 4; + MinInstAlignment = 1; PCSymbol = "$"; SeparatorString = ";"; CommentColumn = 40; @@ -87,17 +88,17 @@ MCAsmInfo::MCAsmInfo() { SupportsDebugInformation = false; ExceptionsType = ExceptionHandling::None; DwarfUsesInlineInfoSection = false; - DwarfSectionOffsetDirective = 0; DwarfUsesRelocationsAcrossSections = true; DwarfRegNumForCFI = false; HasMicrosoftFastStdCallMangling = false; + NeedsDwarfSectionOffsetDirective = false; } MCAsmInfo::~MCAsmInfo() { } -unsigned MCAsmInfo::getULEB128Size(unsigned Value) { +unsigned MCAsmInfo::getULEB128Size(uint64_t Value) { unsigned Size = 0; do { Value >>= 7; @@ -106,7 +107,7 @@ unsigned MCAsmInfo::getULEB128Size(unsigned Value) { return Size; } -unsigned MCAsmInfo::getSLEB128Size(int Value) { +unsigned MCAsmInfo::getSLEB128Size(int64_t Value) { unsigned Size = 0; int Sign = Value >> (8 * sizeof(Value) - 1); bool IsMore; diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp index fd79193..33350d9 100644 --- a/lib/MC/MCAsmInfoCOFF.cpp +++ b/lib/MC/MCAsmInfoCOFF.cpp @@ -36,8 +36,8 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() { // Set up DWARF directives HasLEB128 = true; // Target asm supports leb128 directives (little-endian) SupportsDebugInformation = true; - DwarfSectionOffsetDirective = "\t.secrel32\t"; HasMicrosoftFastStdCallMangling = true; + NeedsDwarfSectionOffsetDirective = true; } void MCAsmInfoMicrosoft::anchor() { } diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 35613b4..781e400 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -29,7 +29,7 @@ #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/PathV2.h" +#include "llvm/Support/Path.h" #include <cctype> using namespace llvm; @@ -38,7 +38,7 @@ namespace { class MCAsmStreamer : public MCStreamer { protected: formatted_raw_ostream &OS; - const MCAsmInfo &MAI; + const MCAsmInfo *MAI; private: OwningPtr<MCInstPrinter> InstPrinter; OwningPtr<MCCodeEmitter> Emitter; @@ -124,19 +124,15 @@ public: /// @name MCStreamer Interface /// @{ - virtual void ChangeSection(const MCSection *Section); + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection); virtual void InitSections() { InitToTextSection(); } virtual void InitToTextSection() { - // FIXME, this is MachO specific, but the testsuite - // expects this. - SwitchSection(getContext().getMachOSection( - "__TEXT", "__text", - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - 0, SectionKind::getText())); + SwitchSection(getContext().getObjectFileInfo()->getTextSection()); } virtual void EmitLabel(MCSymbol *Symbol); @@ -184,12 +180,10 @@ public: virtual void EmitTBSSSymbol (const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0); - virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + virtual void EmitBytes(StringRef Data); - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace); - virtual void EmitIntValue(uint64_t Value, unsigned Size, - unsigned AddrSpace = 0); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); + virtual void EmitIntValue(uint64_t Value, unsigned Size); virtual void EmitULEB128Value(const MCExpr *Value); @@ -200,8 +194,7 @@ public: virtual void EmitGPRel32Value(const MCExpr *Value); - virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace); + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, @@ -316,9 +309,9 @@ void MCAsmStreamer::EmitCommentsAndEOL() { "Comment array not newline terminated"); do { // Emit a line of comments. - OS.PadToColumn(MAI.getCommentColumn()); + OS.PadToColumn(MAI->getCommentColumn()); size_t Position = Comments.find('\n'); - OS << MAI.getCommentString() << ' ' << Comments.substr(0, Position) << '\n'; + OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n'; Comments = Comments.substr(Position+1); } while (!Comments.empty()); @@ -333,9 +326,10 @@ static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); } -void MCAsmStreamer::ChangeSection(const MCSection *Section) { +void MCAsmStreamer::ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); - Section->PrintSwitchToSection(MAI, OS); + Section->PrintSwitchToSection(*MAI, OS, Subsection); } void MCAsmStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, @@ -357,7 +351,7 @@ void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); MCStreamer::EmitLabel(Symbol); - OS << *Symbol << MAI.getLabelSuffix(); + OS << *Symbol << MAI->getLabelSuffix(); EmitEOL(); } @@ -365,7 +359,7 @@ void MCAsmStreamer::EmitDebugLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); MCStreamer::EmitDebugLabel(Symbol); - OS << *Symbol << MAI.getDebugLabelSuffix(); + OS << *Symbol << MAI->getDebugLabelSuffix(); EmitEOL(); } @@ -373,9 +367,9 @@ void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { switch (Flag) { case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break; case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; - case MCAF_Code16: OS << '\t'<< MAI.getCode16Directive(); break; - case MCAF_Code32: OS << '\t'<< MAI.getCode32Directive(); break; - case MCAF_Code64: OS << '\t'<< MAI.getCode64Directive(); break; + case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break; + case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break; + case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break; } EmitEOL(); } @@ -391,9 +385,7 @@ void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) { } void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { - MCContext &Ctx = getContext(); - const MCAsmInfo &MAI = Ctx.getAsmInfo(); - if (!MAI.doesSupportDataRegionDirectives()) + if (!MAI->doesSupportDataRegionDirectives()) return; switch (Kind) { case MCDR_DataRegion: OS << "\t.data_region"; break; @@ -410,7 +402,7 @@ void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) { // MCSymbols when they have spaces in them. OS << "\t.thumb_func"; // Only Mach-O hasSubsectionsViaSymbols() - if (MAI.hasSubsectionsViaSymbols()) + if (MAI->hasSubsectionsViaSymbols()) OS << '\t' << *Func; EmitEOL(); } @@ -455,9 +447,9 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object - assert(MAI.hasDotTypeDotSizeDirective() && "Symbol Attr not supported"); + assert(MAI->hasDotTypeDotSizeDirective() && "Symbol Attr not supported"); OS << "\t.type\t" << *Symbol << ',' - << ((MAI.getCommentString()[0] != '@') ? '@' : '%'); + << ((MAI->getCommentString()[0] != '@') ? '@' : '%'); switch (Attribute) { default: llvm_unreachable("Unknown ELF .type"); case MCSA_ELF_TypeFunction: OS << "function"; break; @@ -471,7 +463,7 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, EmitEOL(); return; case MCSA_Global: // .globl/.global - OS << MAI.getGlobalDirective(); + OS << MAI->getGlobalDirective(); FlagMap[Symbol] |= EHGlobal; break; case MCSA_Hidden: OS << "\t.hidden\t"; break; @@ -493,7 +485,7 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, FlagMap[Symbol] |= EHWeakDefinition; break; // .weak_reference - case MCSA_WeakReference: OS << MAI.getWeakRefDirective(); break; + case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break; case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break; } @@ -532,7 +524,7 @@ void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { } void MCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { - assert(MAI.hasDotTypeDotSizeDirective()); + assert(MAI->hasDotTypeDotSizeDirective()); OS << "\t.size\t" << *Symbol << ", " << *Value << '\n'; } @@ -540,7 +532,7 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { OS << "\t.comm\t" << *Symbol << ',' << Size; if (ByteAlignment != 0) { - if (MAI.getCOMMDirectiveAlignmentIsInBytes()) + if (MAI->getCOMMDirectiveAlignmentIsInBytes()) OS << ',' << ByteAlignment; else OS << ',' << Log2_32(ByteAlignment); @@ -556,7 +548,7 @@ void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlign) { OS << "\t.lcomm\t" << *Symbol << ',' << Size; if (ByteAlign > 1) { - switch (MAI.getLCOMMDirectiveAlignmentType()) { + switch (MAI->getLCOMMDirectiveAlignmentType()) { case LCOMM::NoAlignment: llvm_unreachable("alignment not supported on .lcomm!"); case LCOMM::ByteAlignment: @@ -641,12 +633,13 @@ static void PrintQuotedString(StringRef Data, raw_ostream &OS) { } -void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { - assert(getCurrentSection() && "Cannot emit contents before setting section!"); +void MCAsmStreamer::EmitBytes(StringRef Data) { + assert(getCurrentSection().first && + "Cannot emit contents before setting section!"); if (Data.empty()) return; if (Data.size() == 1) { - OS << MAI.getData8bitsDirective(AddrSpace); + OS << MAI->getData8bitsDirective(); OS << (unsigned)(unsigned char)Data[0]; EmitEOL(); return; @@ -654,11 +647,11 @@ void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { // If the data ends with 0 and the target supports .asciz, use it, otherwise // use .ascii - if (MAI.getAscizDirective() && Data.back() == 0) { - OS << MAI.getAscizDirective(); + if (MAI->getAscizDirective() && Data.back() == 0) { + OS << MAI->getAscizDirective(); Data = Data.substr(0, Data.size()-1); } else { - OS << MAI.getAsciiDirective(); + OS << MAI->getAsciiDirective(); } OS << ' '; @@ -666,33 +659,32 @@ void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { EmitEOL(); } -void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, - unsigned AddrSpace) { - EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace); +void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) { + EmitValue(MCConstantExpr::Create(Value, getContext()), Size); } -void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) { - assert(getCurrentSection() && "Cannot emit contents before setting section!"); +void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size) { + assert(getCurrentSection().first && + "Cannot emit contents before setting section!"); const char *Directive = 0; switch (Size) { default: break; - case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break; - case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break; - case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break; + case 1: Directive = MAI->getData8bitsDirective(); break; + case 2: Directive = MAI->getData16bitsDirective(); break; + case 4: Directive = MAI->getData32bitsDirective(); break; case 8: - Directive = MAI.getData64bitsDirective(AddrSpace); + Directive = MAI->getData64bitsDirective(); // If the target doesn't support 64-bit data, emit as two 32-bit halves. if (Directive) break; int64_t IntValue; if (!Value->EvaluateAsAbsolute(IntValue)) report_fatal_error("Don't know how to emit this value."); - if (getContext().getAsmInfo().isLittleEndian()) { - EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace); - EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace); + if (MAI->isLittleEndian()) { + EmitIntValue((uint32_t)(IntValue >> 0 ), 4); + EmitIntValue((uint32_t)(IntValue >> 32), 4); } else { - EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace); - EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace); + EmitIntValue((uint32_t)(IntValue >> 32), 4); + EmitIntValue((uint32_t)(IntValue >> 0 ), 4); } return; } @@ -708,7 +700,7 @@ void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) { EmitULEB128IntValue(IntValue); return; } - assert(MAI.hasLEB128() && "Cannot print a .uleb"); + assert(MAI->hasLEB128() && "Cannot print a .uleb"); OS << ".uleb128 " << *Value; EmitEOL(); } @@ -719,41 +711,39 @@ void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) { EmitSLEB128IntValue(IntValue); return; } - assert(MAI.hasLEB128() && "Cannot print a .sleb"); + assert(MAI->hasLEB128() && "Cannot print a .sleb"); OS << ".sleb128 " << *Value; EmitEOL(); } void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) { - assert(MAI.getGPRel64Directive() != 0); - OS << MAI.getGPRel64Directive() << *Value; + assert(MAI->getGPRel64Directive() != 0); + OS << MAI->getGPRel64Directive() << *Value; EmitEOL(); } void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { - assert(MAI.getGPRel32Directive() != 0); - OS << MAI.getGPRel32Directive() << *Value; + assert(MAI->getGPRel32Directive() != 0); + OS << MAI->getGPRel32Directive() << *Value; EmitEOL(); } /// EmitFill - Emit NumBytes bytes worth of the value specified by /// FillValue. This implements directives such as '.space'. -void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace) { +void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) { if (NumBytes == 0) return; - if (AddrSpace == 0) - if (const char *ZeroDirective = MAI.getZeroDirective()) { - OS << ZeroDirective << NumBytes; - if (FillValue != 0) - OS << ',' << (int)FillValue; - EmitEOL(); - return; - } + if (const char *ZeroDirective = MAI->getZeroDirective()) { + OS << ZeroDirective << NumBytes; + if (FillValue != 0) + OS << ',' << (int)FillValue; + EmitEOL(); + return; + } // Emit a byte at a time. - MCStreamer::EmitFill(NumBytes, FillValue, AddrSpace); + MCStreamer::EmitFill(NumBytes, FillValue); } void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, @@ -764,14 +754,14 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, if (isPowerOf2_32(ByteAlignment)) { switch (ValueSize) { default: llvm_unreachable("Invalid size for machine code value!"); - case 1: OS << MAI.getAlignDirective(); break; + case 1: OS << MAI->getAlignDirective(); break; // FIXME: use MAI for this! case 2: OS << ".p2alignw "; break; case 4: OS << ".p2alignl "; break; case 8: llvm_unreachable("Unsupported alignment size!"); } - if (MAI.getAlignmentIsInBytes()) + if (MAI->getAlignmentIsInBytes()) OS << ByteAlignment; else OS << Log2_32(ByteAlignment); @@ -807,7 +797,7 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit) { // Emit with a text fill value. - EmitValueToAlignment(ByteAlignment, MAI.getTextAlignFillValue(), + EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(), 1, MaxBytesToEmit); } @@ -821,7 +811,7 @@ bool MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset, void MCAsmStreamer::EmitFileDirective(StringRef Filename) { - assert(MAI.hasSingleParameterDotFile()); + assert(MAI->hasSingleParameterDotFile()); OS << "\t.file\t"; PrintQuotedString(Filename, OS); EmitEOL(); @@ -887,8 +877,8 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, OS << "discriminator " << Discriminator; if (IsVerboseAsm) { - OS.PadToColumn(MAI.getCommentColumn()); - OS << MAI.getCommentString() << ' ' << FileName << ':' + OS.PadToColumn(MAI->getCommentColumn()); + OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':' << Column; } EmitEOL(); @@ -937,9 +927,9 @@ void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { } void MCAsmStreamer::EmitRegisterName(int64_t Register) { - if (InstPrinter && !MAI.useDwarfRegNumForCFI()) { - const MCRegisterInfo &MRI = getContext().getRegisterInfo(); - unsigned LLVMRegister = MRI.getLLVMRegNum(Register, true); + if (InstPrinter && !MAI->useDwarfRegNumForCFI()) { + const MCRegisterInfo *MRI = getContext().getRegisterInfo(); + unsigned LLVMRegister = MRI->getLLVMRegNum(Register, true); InstPrinter->printRegName(OS, LLVMRegister); } else { OS << Register; @@ -1277,7 +1267,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { unsigned Bit = (Code[i] >> j) & 1; unsigned FixupBit; - if (getContext().getAsmInfo().isLittleEndian()) + if (MAI->isLittleEndian()) FixupBit = i * 8 + j; else FixupBit = i * 8 + (7-j); @@ -1368,7 +1358,8 @@ void MCAsmStreamer::EmitTCEntry(const MCSymbol &S) { } void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { - assert(getCurrentSection() && "Cannot emit contents before setting section!"); + assert(getCurrentSection().first && + "Cannot emit contents before setting section!"); // Show the encoding in a comment if we have a code emitter. if (Emitter) @@ -1376,7 +1367,7 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { // Show the MCInst if enabled. if (ShowInst) { - Inst.dump_pretty(GetCommentOS(), &MAI, InstPrinter.get(), "\n "); + Inst.dump_pretty(GetCommentOS(), MAI, InstPrinter.get(), "\n "); GetCommentOS() << "\n"; } @@ -1384,7 +1375,7 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { if (InstPrinter) InstPrinter->printInst(&Inst, OS, ""); else - Inst.print(OS, &MAI); + Inst.print(OS, MAI); EmitEOL(); } diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 208a4d5..21dcdd7 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -244,6 +244,36 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) A->getSectionList().push_back(this); } +MCSectionData::iterator +MCSectionData::getSubsectionInsertionPoint(unsigned Subsection) { + if (Subsection == 0 && SubsectionFragmentMap.empty()) + return end(); + + SmallVectorImpl<std::pair<unsigned, MCFragment *> >::iterator MI = + std::lower_bound(SubsectionFragmentMap.begin(), SubsectionFragmentMap.end(), + std::make_pair(Subsection, (MCFragment *)0)); + bool ExactMatch = false; + if (MI != SubsectionFragmentMap.end()) { + ExactMatch = MI->first == Subsection; + if (ExactMatch) + ++MI; + } + iterator IP; + if (MI == SubsectionFragmentMap.end()) + IP = end(); + else + IP = MI->second; + if (!ExactMatch && Subsection != 0) { + // The GNU as documentation claims that subsections have an alignment of 4, + // although this appears not to be the case. + MCFragment *F = new MCDataFragment(); + SubsectionFragmentMap.insert(MI, std::make_pair(Subsection, F)); + getFragmentList().insert(IP, F); + F->setParent(this); + } + return IP; +} + /* *** */ MCSymbolData::MCSymbolData() : Symbol(0) {} @@ -556,10 +586,10 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, case MCFragment::FT_Align: { ++stats::EmittedAlignFragments; const MCAlignFragment &AF = cast<MCAlignFragment>(F); - uint64_t Count = FragmentSize / AF.getValueSize(); - assert(AF.getValueSize() && "Invalid virtual align in concrete fragment!"); + uint64_t Count = FragmentSize / AF.getValueSize(); + // FIXME: This error shouldn't actually occur (the front end should emit // multiple .align directives to enforce the semantics it wants), but is // severe enough that we want to report it. How to handle this? @@ -684,12 +714,13 @@ void MCAssembler::writeSectionData(const MCSectionData *SD, case MCFragment::FT_Align: // Check that we aren't trying to write a non-zero value into a virtual // section. - assert((!cast<MCAlignFragment>(it)->getValueSize() || - !cast<MCAlignFragment>(it)->getValue()) && + assert((cast<MCAlignFragment>(it)->getValueSize() == 0 || + cast<MCAlignFragment>(it)->getValue() == 0) && "Invalid align in virtual section!"); break; case MCFragment::FT_Fill: - assert(!cast<MCFillFragment>(it)->getValueSize() && + assert((cast<MCFillFragment>(it)->getValueSize() == 0 || + cast<MCFillFragment>(it)->getValue() == 0) && "Invalid fill in virtual section!"); break; } @@ -880,6 +911,7 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF) { + MCContext &Context = Layout.getAssembler().getContext(); int64_t AddrDelta = 0; uint64_t OldSize = DF.getContents().size(); bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout); @@ -890,13 +922,14 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, SmallString<8> &Data = DF.getContents(); Data.clear(); raw_svector_ostream OSE(Data); - MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OSE); + MCDwarfLineAddr::Encode(Context, LineDelta, AddrDelta, OSE); OSE.flush(); return OldSize != Data.size(); } bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout, MCDwarfCallFrameFragment &DF) { + MCContext &Context = Layout.getAssembler().getContext(); int64_t AddrDelta = 0; uint64_t OldSize = DF.getContents().size(); bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout); @@ -905,7 +938,7 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout, SmallString<8> &Data = DF.getContents(); Data.clear(); raw_svector_ostream OSE(Data); - MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OSE); + MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE); OSE.flush(); return OldSize != Data.size(); } diff --git a/lib/MC/MCAtom.cpp b/lib/MC/MCAtom.cpp index d714443..2626b39 100644 --- a/lib/MC/MCAtom.cpp +++ b/lib/MC/MCAtom.cpp @@ -10,88 +10,101 @@ #include "llvm/MC/MCAtom.h" #include "llvm/MC/MCModule.h" #include "llvm/Support/ErrorHandling.h" +#include <iterator> using namespace llvm; -void MCAtom::addInst(const MCInst &I, uint64_t Address, unsigned Size) { - assert(Type == TextAtom && "Trying to add MCInst to a non-text atom!"); - - assert(Address < End+Size && - "Instruction not contiguous with end of atom!"); - if (Address > End) - Parent->remap(this, Begin, End+Size); - - Text.push_back(std::make_pair(Address, I)); +void MCAtom::remap(uint64_t NewBegin, uint64_t NewEnd) { + Parent->remap(this, NewBegin, NewEnd); } -void MCAtom::addData(const MCData &D) { - assert(Type == DataAtom && "Trying to add MCData to a non-data atom!"); - Parent->remap(this, Begin, End+1); - - Data.push_back(D); +void MCAtom::remapForTruncate(uint64_t TruncPt) { + assert((TruncPt >= Begin && TruncPt < End) && + "Truncation point not contained in atom!"); + remap(Begin, TruncPt); } -MCAtom *MCAtom::split(uint64_t SplitPt) { +void MCAtom::remapForSplit(uint64_t SplitPt, + uint64_t &LBegin, uint64_t &LEnd, + uint64_t &RBegin, uint64_t &REnd) { assert((SplitPt > Begin && SplitPt <= End) && "Splitting at point not contained in atom!"); // Compute the new begin/end points. - uint64_t LeftBegin = Begin; - uint64_t LeftEnd = SplitPt - 1; - uint64_t RightBegin = SplitPt; - uint64_t RightEnd = End; + LBegin = Begin; + LEnd = SplitPt - 1; + RBegin = SplitPt; + REnd = End; // Remap this atom to become the lower of the two new ones. - Parent->remap(this, LeftBegin, LeftEnd); + remap(LBegin, LEnd); +} - // Create a new atom for the higher atom. - MCAtom *RightAtom = Parent->createAtom(Type, RightBegin, RightEnd); +// MCDataAtom - // Split the contents of the original atom between it and the new one. The - // precise method depends on whether this is a data or a text atom. - if (isDataAtom()) { - std::vector<MCData>::iterator I = Data.begin() + (RightBegin - LeftBegin); +void MCDataAtom::addData(const MCData &D) { + Data.push_back(D); + if (Data.size() > Begin - End) + remap(Begin, End + 1); +} - assert(I != Data.end() && "Split point not found in range!"); +void MCDataAtom::truncate(uint64_t TruncPt) { + remapForTruncate(TruncPt); - std::copy(I, Data.end(), RightAtom->Data.end()); - Data.erase(I, Data.end()); - } else if (isTextAtom()) { - std::vector<std::pair<uint64_t, MCInst> >::iterator I = Text.begin(); + Data.resize(TruncPt - Begin + 1); +} - while (I != Text.end() && I->first < SplitPt) ++I; +MCDataAtom *MCDataAtom::split(uint64_t SplitPt) { + uint64_t LBegin, LEnd, RBegin, REnd; + remapForSplit(SplitPt, LBegin, LEnd, RBegin, REnd); - assert(I != Text.end() && "Split point not found in disassembly!"); - assert(I->first == SplitPt && - "Split point does not fall on instruction boundary!"); + MCDataAtom *RightAtom = Parent->createDataAtom(RBegin, REnd); + RightAtom->setName(getName()); - std::copy(I, Text.end(), RightAtom->Text.end()); - Text.erase(I, Text.end()); - } else - llvm_unreachable("Unknown atom type!"); + std::vector<MCData>::iterator I = Data.begin() + (RBegin - LBegin); + assert(I != Data.end() && "Split point not found in range!"); + std::copy(I, Data.end(), std::back_inserter(RightAtom->Data)); + Data.erase(I, Data.end()); return RightAtom; } -void MCAtom::truncate(uint64_t TruncPt) { - assert((TruncPt >= Begin && TruncPt < End) && - "Truncation point not contained in atom!"); +// MCTextAtom - Parent->remap(this, Begin, TruncPt); +void MCTextAtom::addInst(const MCInst &I, uint64_t Size) { + if (NextInstAddress > End) + remap(Begin, NextInstAddress); + Insts.push_back(MCDecodedInst(I, NextInstAddress, Size)); + NextInstAddress += Size; +} - if (isDataAtom()) { - Data.resize(TruncPt - Begin + 1); - } else if (isTextAtom()) { - std::vector<std::pair<uint64_t, MCInst> >::iterator I = Text.begin(); +void MCTextAtom::truncate(uint64_t TruncPt) { + remapForTruncate(TruncPt); - while (I != Text.end() && I->first <= TruncPt) ++I; + InstListTy::iterator I = Insts.begin(); + while (I != Insts.end() && I->Address <= TruncPt) ++I; - assert(I != Text.end() && "Truncation point not found in disassembly!"); - assert(I->first == TruncPt+1 && - "Truncation point does not fall on instruction boundary"); + assert(I != Insts.end() && "Truncation point not found in disassembly!"); + assert(I->Address == TruncPt + 1 && + "Truncation point does not fall on instruction boundary"); - Text.erase(I, Text.end()); - } else - llvm_unreachable("Unknown atom type!"); + Insts.erase(I, Insts.end()); } +MCTextAtom *MCTextAtom::split(uint64_t SplitPt) { + uint64_t LBegin, LEnd, RBegin, REnd; + remapForSplit(SplitPt, LBegin, LEnd, RBegin, REnd); + + MCTextAtom *RightAtom = Parent->createTextAtom(RBegin, REnd); + RightAtom->setName(getName()); + + InstListTy::iterator I = Insts.begin(); + while (I != Insts.end() && I->Address < SplitPt) ++I; + assert(I != Insts.end() && "Split point not found in disassembly!"); + assert(I->Address == SplitPt && + "Split point does not fall on instruction boundary!"); + + std::copy(I, Insts.end(), std::back_inserter(RightAtom->Insts)); + Insts.erase(I, Insts.end()); + return RightAtom; +} diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index 9adcc02..6e4d82b 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -21,6 +21,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" @@ -31,17 +32,20 @@ typedef StringMap<const MCSectionELF*> ELFUniqueMapTy; typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy; -MCContext::MCContext(const MCAsmInfo &mai, const MCRegisterInfo &mri, +MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri, const MCObjectFileInfo *mofi, const SourceMgr *mgr, bool DoAutoReset) : SrcMgr(mgr), MAI(mai), MRI(mri), MOFI(mofi), Allocator(), Symbols(Allocator), UsedNames(Allocator), NextUniqueID(0), - CompilationDir(llvm::sys::Path::GetCurrentDirectory().str()), CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0), DwarfLocSeen(false), GenDwarfForAssembly(false), GenDwarfFileNumber(0), AllowTemporaryLabels(true), DwarfCompileUnitID(0), AutoReset(DoAutoReset) { + error_code EC = llvm::sys::fs::current_path(CompilationDir); + assert(!EC && "Could not determine the current directory"); + (void)EC; + MachOUniquingMap = 0; ELFUniquingMap = 0; COFFUniquingMap = 0; @@ -126,7 +130,7 @@ MCSymbol *MCContext::CreateSymbol(StringRef Name) { // Determine whether this is an assembler temporary or normal label, if used. bool isTemporary = false; if (AllowTemporaryLabels) - isTemporary = Name.startswith(MAI.getPrivateGlobalPrefix()); + isTemporary = Name.startswith(MAI->getPrivateGlobalPrefix()); StringMapEntry<bool> *NameEntry = &UsedNames.GetOrCreateValue(Name); if (NameEntry->getValue()) { @@ -156,7 +160,7 @@ MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { MCSymbol *MCContext::CreateTempSymbol() { SmallString<128> NameSV; raw_svector_ostream(NameSV) - << MAI.getPrivateGlobalPrefix() << "tmp" << NextUniqueID++; + << MAI->getPrivateGlobalPrefix() << "tmp" << NextUniqueID++; return CreateSymbol(NameSV); } @@ -175,14 +179,14 @@ unsigned MCContext::GetInstance(int64_t LocalLabelVal) { } MCSymbol *MCContext::CreateDirectionalLocalSymbol(int64_t LocalLabelVal) { - return GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix()) + + return GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + Twine(LocalLabelVal) + "\2" + Twine(NextInstance(LocalLabelVal))); } MCSymbol *MCContext::GetDirectionalLocalSymbol(int64_t LocalLabelVal, int bORf) { - return GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix()) + + return GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + Twine(LocalLabelVal) + "\2" + Twine(GetInstance(LocalLabelVal) + bORf)); @@ -270,10 +274,10 @@ const MCSectionELF *MCContext::CreateELFGroupSection() { return Result; } -const MCSection *MCContext::getCOFFSection(StringRef Section, - unsigned Characteristics, - int Selection, - SectionKind Kind) { +const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind, int Selection, + const MCSectionCOFF *Assoc) { if (COFFUniquingMap == 0) COFFUniquingMap = new COFFUniqueMapTy(); COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap; @@ -284,12 +288,20 @@ const MCSection *MCContext::getCOFFSection(StringRef Section, MCSectionCOFF *Result = new (*this) MCSectionCOFF(Entry.getKey(), Characteristics, - Selection, Kind); + Selection, Assoc, Kind); Entry.setValue(Result); return Result; } +const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) { + if (COFFUniquingMap == 0) + COFFUniquingMap = new COFFUniqueMapTy(); + COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap; + + return Map.lookup(Section); +} + //===----------------------------------------------------------------------===// // Dwarf Management //===----------------------------------------------------------------------===// diff --git a/lib/MC/MCDisassembler.cpp b/lib/MC/MCDisassembler.cpp index 0809690..bfd51ab 100644 --- a/lib/MC/MCDisassembler.cpp +++ b/lib/MC/MCDisassembler.cpp @@ -8,7 +8,49 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCExternalSymbolizer.h" +#include "llvm/Support/raw_ostream.h" + using namespace llvm; MCDisassembler::~MCDisassembler() { } + +void +MCDisassembler::setupForSymbolicDisassembly( + LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, + void *DisInfo, + MCContext *Ctx, + OwningPtr<MCRelocationInfo> &RelInfo) { + this->GetOpInfo = GetOpInfo; + this->SymbolLookUp = SymbolLookUp; + this->DisInfo = DisInfo; + this->Ctx = Ctx; + assert(Ctx != 0 && "No MCContext given for symbolic disassembly"); + if (!Symbolizer) + Symbolizer.reset(new MCExternalSymbolizer(*Ctx, RelInfo, GetOpInfo, + SymbolLookUp, DisInfo)); +} + +bool MCDisassembler::tryAddingSymbolicOperand(MCInst &Inst, int64_t Value, + uint64_t Address, bool IsBranch, + uint64_t Offset, + uint64_t InstSize) const { + raw_ostream &cStream = CommentStream ? *CommentStream : nulls(); + if (Symbolizer) + return Symbolizer->tryAddingSymbolicOperand(Inst, cStream, Value, Address, + IsBranch, Offset, InstSize); + return false; +} + +void MCDisassembler::tryAddingPcLoadReferenceComment(int64_t Value, + uint64_t Address) const { + raw_ostream &cStream = CommentStream ? *CommentStream : nulls(); + if (Symbolizer) + Symbolizer->tryAddingPcLoadReferenceComment(cStream, Value, Address); +} + +void MCDisassembler::setSymbolizer(OwningPtr<MCSymbolizer> &Symzer) { + Symbolizer.reset(Symzer.take()); +} diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp index 4766b37..ecc7aff 100644 --- a/lib/MC/MCDisassembler/Disassembler.cpp +++ b/lib/MC/MCDisassembler/Disassembler.cpp @@ -16,7 +16,9 @@ #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbolizer.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/TargetRegistry.h" @@ -40,10 +42,15 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, // Get the target. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); - assert(TheTarget && "Unable to create target!"); + if (!TheTarget) + return 0; + + const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(Triple); + if (!MRI) + return 0; // Get the assembler info needed to setup the MCContext. - const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(Triple); + const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(*MRI, Triple); if (!MAI) return 0; @@ -51,10 +58,6 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, if (!MII) return 0; - const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(Triple); - if (!MRI) - return 0; - // Package up features to be passed to target/subtarget std::string FeaturesStr; @@ -64,7 +67,7 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, return 0; // Set up the MCContext for creating symbols and MCExpr's. - MCContext *Ctx = new MCContext(*MAI, *MRI, 0); + MCContext *Ctx = new MCContext(MAI, MRI, 0); if (!Ctx) return 0; @@ -72,8 +75,18 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI); if (!DisAsm) return 0; - DisAsm->setupForSymbolicDisassembly(GetOpInfo, SymbolLookUp, DisInfo, Ctx); + OwningPtr<MCRelocationInfo> RelInfo( + TheTarget->createMCRelocationInfo(Triple, *Ctx)); + if (!RelInfo) + return 0; + + OwningPtr<MCSymbolizer> Symbolizer( + TheTarget->createMCSymbolizer(Triple, GetOpInfo, SymbolLookUp, DisInfo, + Ctx, RelInfo.take())); + DisAsm->setSymbolizer(Symbolizer); + DisAsm->setupForSymbolicDisassembly(GetOpInfo, SymbolLookUp, DisInfo, + Ctx, RelInfo); // Set up the instruction printer. int AsmPrinterVariant = MAI->getAssemblerDialect(); MCInstPrinter *IP = TheTarget->createMCInstPrinter(AsmPrinterVariant, diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 0f8f074..195bbfe 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -16,7 +16,6 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" @@ -47,20 +46,15 @@ using namespace llvm; // Range of line offsets in a special line info. opcode. #define DWARF2_LINE_RANGE 14 -// Define the architecture-dependent minimum instruction length (in bytes). -// This value should be rather too small than too big. -#define DWARF2_LINE_MIN_INSN_LENGTH 1 - -// Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting, -// this routine is a nop and will be optimized away. -static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) { - if (DWARF2_LINE_MIN_INSN_LENGTH == 1) +static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) { + unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment(); + if (MinInsnLength == 1) return AddrDelta; - if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) { + if (AddrDelta % MinInsnLength != 0) { // TODO: report this error, but really only once. ; } - return AddrDelta / DWARF2_LINE_MIN_INSN_LENGTH; + return AddrDelta / MinInsnLength; } // @@ -182,9 +176,9 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, // 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(); + const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo(); MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, - asmInfo.getPointerSize()); + asmInfo->getPointerSize()); LastLine = it->getLine(); LastLabel = Label; @@ -197,6 +191,8 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, // actually a DW_LNE_end_sequence. // Switch to the section to be able to create a symbol at its end. + // TODO: keep track of the last subsection so that this symbol appears in the + // correct place. MCOS->SwitchSection(Section); MCContext &context = MCOS->getContext(); @@ -208,9 +204,9 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, // Switch back the dwarf line section. MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); - const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo(); + const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo(); MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, - asmInfo.getPointerSize()); + asmInfo->getPointerSize()); } // @@ -272,10 +268,10 @@ const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { // total length, the 2 bytes for the version, and these 4 bytes for the // length of the prologue. MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, - (4 + 2 + 4)), 4, 0); + (4 + 2 + 4)), 4); // Parameters of the state machine, are next. - MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1); + MCOS->EmitIntValue(context.getAsmInfo()->getMinInstAlignment(), 1); MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1); MCOS->EmitIntValue(DWARF2_LINE_BASE, 1); MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1); @@ -336,7 +332,7 @@ const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { EmitDwarfLineTable(MCOS, Sec, Line, CUID); } - if (MCOS->getContext().getAsmInfo().getLinkerRequiresNonEmptyDwarfLines() + if (MCOS->getContext().getAsmInfo()->getLinkerRequiresNonEmptyDwarfLines() && MCLineSectionOrder.begin() == MCLineSectionOrder.end()) { // The darwin9 linker has a bug (see PR8715). For for 32-bit architectures // it requires: @@ -355,32 +351,24 @@ const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { return LineStartSym; } -/// Utility function to write the encoding to an object writer. -void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta, - uint64_t AddrDelta) { - SmallString<256> Tmp; - raw_svector_ostream OS(Tmp); - MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); - OW->WriteBytes(OS.str()); -} - /// Utility function to emit the encoding to a streamer. void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta, uint64_t AddrDelta) { + MCContext &Context = MCOS->getContext(); SmallString<256> Tmp; raw_svector_ostream OS(Tmp); - MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); + MCDwarfLineAddr::Encode(Context, LineDelta, AddrDelta, OS); MCOS->EmitBytes(OS.str()); } /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. -void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta, - raw_ostream &OS) { +void MCDwarfLineAddr::Encode(MCContext &Context, int64_t LineDelta, + uint64_t AddrDelta, raw_ostream &OS) { uint64_t Temp, Opcode; bool NeedCopy = false; // Scale the address delta by the minimum instruction length. - AddrDelta = ScaleAddrDelta(AddrDelta); + AddrDelta = ScaleAddrDelta(Context, AddrDelta); // A LineDelta of INT64_MAX is a signal that this is actually a // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the @@ -532,8 +520,8 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, // Figure the padding after the header before the table of address and size // pairs who's values are PointerSize'ed. - const MCAsmInfo &asmInfo = context.getAsmInfo(); - int AddrSize = asmInfo.getPointerSize(); + const MCAsmInfo *asmInfo = context.getAsmInfo(); + int AddrSize = asmInfo->getPointerSize(); int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1)); if (Pad == 2 * AddrSize) Pad = 0; @@ -613,8 +601,8 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, MCOS->EmitIntValue(0, 4); } - const MCAsmInfo &asmInfo = context.getAsmInfo(); - int AddrSize = asmInfo.getPointerSize(); + const MCAsmInfo *asmInfo = context.getAsmInfo(); + int AddrSize = asmInfo->getPointerSize(); // The 1 byte size of an address. MCOS->EmitIntValue(AddrSize, 1); @@ -741,9 +729,9 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, void MCGenDwarfInfo::Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol) { // Create the dwarf sections in this order (.debug_line already created). MCContext &context = MCOS->getContext(); - const MCAsmInfo &AsmInfo = context.getAsmInfo(); + const MCAsmInfo *AsmInfo = context.getAsmInfo(); bool CreateDwarfSectionSymbols = - AsmInfo.doesDwarfUseRelocationsAcrossSections(); + AsmInfo->doesDwarfUseRelocationsAcrossSections(); if (!CreateDwarfSectionSymbols) LineSectionSymbol = NULL; MCSymbol *AbbrevSectionSymbol = NULL; @@ -787,7 +775,7 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, if (Symbol->isTemporary()) return; MCContext &context = MCOS->getContext(); - if (context.getGenDwarfSection() != MCOS->getCurrentSection()) + if (context.getGenDwarfSection() != MCOS->getCurrentSection().first) return; // The dwarf label's name does not have the symbol name's leading @@ -819,9 +807,9 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, static int getDataAlignmentFactor(MCStreamer &streamer) { MCContext &context = streamer.getContext(); - const MCAsmInfo &asmInfo = context.getAsmInfo(); - int size = asmInfo.getCalleeSaveStackSlotSize(); - if (asmInfo.isStackGrowthDirectionUp()) + const MCAsmInfo *asmInfo = context.getAsmInfo(); + int size = asmInfo->getCalleeSaveStackSlotSize(); + if (asmInfo->isStackGrowthDirectionUp()) return size; else return -size; @@ -835,7 +823,7 @@ static unsigned getSizeForEncoding(MCStreamer &streamer, default: llvm_unreachable("Unknown Encoding"); case dwarf::DW_EH_PE_absptr: case dwarf::DW_EH_PE_signed: - return context.getAsmInfo().getPointerSize(); + return context.getAsmInfo()->getPointerSize(); case dwarf::DW_EH_PE_udata2: case dwarf::DW_EH_PE_sdata2: return 2; @@ -851,10 +839,10 @@ static unsigned getSizeForEncoding(MCStreamer &streamer, static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, unsigned symbolEncoding, const char *comment = 0) { MCContext &context = streamer.getContext(); - const MCAsmInfo &asmInfo = context.getAsmInfo(); - const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol, - symbolEncoding, - streamer); + const MCAsmInfo *asmInfo = context.getAsmInfo(); + const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol, + symbolEncoding, + streamer); unsigned size = getSizeForEncoding(streamer, symbolEncoding); if (streamer.isVerboseAsm() && comment) streamer.AddComment(comment); streamer.EmitAbsValue(v, size); @@ -863,25 +851,14 @@ static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, unsigned symbolEncoding) { MCContext &context = streamer.getContext(); - const MCAsmInfo &asmInfo = context.getAsmInfo(); - const MCExpr *v = asmInfo.getExprForPersonalitySymbol(&symbol, - symbolEncoding, - streamer); + const MCAsmInfo *asmInfo = context.getAsmInfo(); + const MCExpr *v = asmInfo->getExprForPersonalitySymbol(&symbol, + symbolEncoding, + streamer); unsigned size = getSizeForEncoding(streamer, symbolEncoding); streamer.EmitValue(v, size); } -static const MachineLocation TranslateMachineLocation( - const MCRegisterInfo &MRI, - const MachineLocation &Loc) { - unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? - MachineLocation::VirtualFP : - unsigned(MRI.getDwarfRegNum(Loc.getReg(), true)); - const MachineLocation &NewLoc = Loc.isReg() ? - MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); - return NewLoc; -} - namespace { class FrameEmitterImpl { int CFAOffset; @@ -899,7 +876,7 @@ namespace { /// EmitCompactUnwind - Emit the unwind information in a compact way. If /// we're successful, return 'true'. Otherwise, return 'false' and it will /// emit the normal CIE and FDE. - bool EmitCompactUnwind(MCStreamer &streamer, + void EmitCompactUnwind(MCStreamer &streamer, const MCDwarfFrameInfo &frame); const MCSymbol &EmitCIE(MCStreamer &streamer, @@ -1139,7 +1116,7 @@ void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, /// EmitCompactUnwind - Emit the unwind information in a compact way. If we're /// successful, return 'true'. Otherwise, return 'false' and it will emit the /// normal CIE and FDE. -bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, +void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, const MCDwarfFrameInfo &Frame) { MCContext &Context = Streamer.getContext(); const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); @@ -1168,14 +1145,13 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, // .quad except_tab1 uint32_t Encoding = Frame.CompactUnwindEncoding; - if (!Encoding) return false; + if (!Encoding) return; + bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly()); // The encoding needs to know we have an LSDA. - if (Frame.Lsda) + if (!DwarfEHFrameOnly && Frame.Lsda) Encoding |= 0x40000000; - Streamer.SwitchSection(MOFI->getCompactUnwindSection()); - // Range Start unsigned FDEEncoding = MOFI->getFDEEncoding(UsingCFI); unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); @@ -1194,11 +1170,10 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, Twine::utohexstr(Encoding)); Streamer.EmitIntValue(Encoding, Size); - // Personality Function Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr); if (VerboseAsm) Streamer.AddComment("Personality Function"); - if (Frame.Personality) + if (!DwarfEHFrameOnly && Frame.Personality) Streamer.EmitSymbolValue(Frame.Personality, Size); else Streamer.EmitIntValue(0, Size); // No personality fn @@ -1206,12 +1181,10 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, // LSDA Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding); if (VerboseAsm) Streamer.AddComment("LSDA"); - if (Frame.Lsda) + if (!DwarfEHFrameOnly && Frame.Lsda) Streamer.EmitSymbolValue(Frame.Lsda, Size); else Streamer.EmitIntValue(0, Size); // No LSDA - - return true; } const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, @@ -1221,7 +1194,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, bool IsSignalFrame, unsigned lsdaEncoding) { MCContext &context = streamer.getContext(); - const MCRegisterInfo &MRI = context.getRegisterInfo(); + const MCRegisterInfo *MRI = context.getRegisterInfo(); const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); bool verboseAsm = streamer.isVerboseAsm(); @@ -1269,7 +1242,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, // Code Alignment Factor if (verboseAsm) streamer.AddComment("CIE Code Alignment Factor"); - streamer.EmitULEB128IntValue(1); + streamer.EmitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment()); // Data Alignment Factor if (verboseAsm) streamer.AddComment("CIE Data Alignment Factor"); @@ -1277,7 +1250,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, // Return Address Register if (verboseAsm) streamer.AddComment("CIE Return Address Column"); - streamer.EmitULEB128IntValue(MRI.getDwarfRegNum(MRI.getRARegister(), true)); + streamer.EmitULEB128IntValue(MRI->getDwarfRegNum(MRI->getRARegister(), true)); // Augmentation Data Length (optional) @@ -1317,38 +1290,13 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, // Initial Instructions - const MCAsmInfo &MAI = context.getAsmInfo(); - const std::vector<MachineMove> &Moves = MAI.getInitialFrameState(); - std::vector<MCCFIInstruction> Instructions; - - for (int i = 0, n = Moves.size(); i != n; ++i) { - MCSymbol *Label = Moves[i].getLabel(); - const MachineLocation &Dst = - TranslateMachineLocation(MRI, Moves[i].getDestination()); - const MachineLocation &Src = - TranslateMachineLocation(MRI, Moves[i].getSource()); - - if (Dst.isReg()) { - assert(Dst.getReg() == MachineLocation::VirtualFP); - assert(!Src.isReg()); - MCCFIInstruction Inst = - MCCFIInstruction::createDefCfa(Label, Src.getReg(), -Src.getOffset()); - Instructions.push_back(Inst); - } else { - assert(Src.isReg()); - unsigned Reg = Src.getReg(); - int Offset = Dst.getOffset(); - MCCFIInstruction Inst = - MCCFIInstruction::createOffset(Label, Reg, Offset); - Instructions.push_back(Inst); - } - } - + const MCAsmInfo *MAI = context.getAsmInfo(); + const std::vector<MCCFIInstruction> &Instructions = + MAI->getInitialFrameState(); EmitCFIInstructions(streamer, Instructions, NULL); // Padding - streamer.EmitValueToAlignment(IsEH - ? 4 : context.getAsmInfo().getPointerSize()); + streamer.EmitValueToAlignment(IsEH ? 4 : MAI->getPointerSize()); streamer.EmitLabel(sectionEnd); return *sectionStart; @@ -1378,13 +1326,13 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, streamer.EmitLabel(fdeStart); // CIE Pointer - const MCAsmInfo &asmInfo = context.getAsmInfo(); + const MCAsmInfo *asmInfo = context.getAsmInfo(); if (IsEH) { const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, 0); if (verboseAsm) streamer.AddComment("FDE CIE Offset"); streamer.EmitAbsValue(offset, 4); - } else if (!asmInfo.doesDwarfUseRelocationsAcrossSections()) { + } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) { const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart, cieStart, 0); streamer.EmitAbsValue(offset, 4); @@ -1421,7 +1369,6 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, } // Call Frame Instructions - EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); // Padding @@ -1476,21 +1423,28 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, bool UsingCFI, bool IsEH) { MCContext &Context = Streamer.getContext(); - MCObjectFileInfo *MOFI = - const_cast<MCObjectFileInfo*>(Context.getObjectFileInfo()); + const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); FrameEmitterImpl Emitter(UsingCFI, IsEH); ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getFrameInfos(); // Emit the compact unwind info if available. - if (IsEH && MOFI->getCompactUnwindSection()) - for (unsigned i = 0, n = Streamer.getNumFrameInfos(); i < n; ++i) { - const MCDwarfFrameInfo &Frame = Streamer.getFrameInfo(i); - if (Frame.CompactUnwindEncoding) - Emitter.EmitCompactUnwind(Streamer, Frame); + if (IsEH && MOFI->getCompactUnwindSection()) { + bool SectionEmitted = false; + for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { + const MCDwarfFrameInfo &Frame = FrameArray[i]; + if (Frame.CompactUnwindEncoding == 0) continue; + if (!SectionEmitted) { + Streamer.SwitchSection(MOFI->getCompactUnwindSection()); + Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize()); + SectionEmitted = true; + } + Emitter.EmitCompactUnwind(Streamer, Frame); } + } - const MCSection &Section = IsEH ? *MOFI->getEHFrameSection() : - *MOFI->getDwarfFrameSection(); + const MCSection &Section = + IsEH ? *const_cast<MCObjectFileInfo*>(MOFI)->getEHFrameSection() : + *MOFI->getDwarfFrameSection(); Streamer.SwitchSection(&Section); MCSymbol *SectionStart = Context.CreateTempSymbol(); Streamer.EmitLabel(SectionStart); @@ -1517,22 +1471,26 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, Streamer.EmitLabel(FDEEnd); } - Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize()); + Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize()); if (FDEEnd) Streamer.EmitLabel(FDEEnd); } void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta) { + MCContext &Context = Streamer.getContext(); SmallString<256> Tmp; raw_svector_ostream OS(Tmp); - MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS); + MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OS); Streamer.EmitBytes(OS.str()); } -void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta, +void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context, + uint64_t AddrDelta, raw_ostream &OS) { - // FIXME: Assumes the code alignment factor is 1. + // Scale the address delta by the minimum instruction length. + AddrDelta = ScaleAddrDelta(Context, AddrDelta); + if (AddrDelta == 0) { } else if (isUIntN(6, AddrDelta)) { uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta; diff --git a/lib/MC/MCELFObjectTargetWriter.cpp b/lib/MC/MCELFObjectTargetWriter.cpp index 4cac84d..ec7397d 100644 --- a/lib/MC/MCELFObjectTargetWriter.cpp +++ b/lib/MC/MCELFObjectTargetWriter.cpp @@ -39,13 +39,23 @@ const MCSymbol *MCELFObjectTargetWriter::undefinedExplicitRelSym(const MCValue & return &Symbol.AliasedSymbol(); } -void MCELFObjectTargetWriter::adjustFixupOffset(const MCFixup &Fixup, - uint64_t &RelocOffset) { +// ELF doesn't require relocations to be in any order. We sort by the r_offset, +// just to match gnu as for easier comparison. The use type and index is an +// arbitrary way of making the sort deterministic. +static int cmpRel(const void *AP, const void *BP) { + const ELFRelocationEntry &A = *(const ELFRelocationEntry *)AP; + const ELFRelocationEntry &B = *(const ELFRelocationEntry *)BP; + if (A.r_offset != B.r_offset) + return B.r_offset - A.r_offset; + if (B.Type != A.Type) + return A.Type - B.Type; + if (B.Index != A.Index) + return B.Index - A.Index; + llvm_unreachable("ELFRelocs might be unstable!"); } void MCELFObjectTargetWriter::sortRelocs(const MCAssembler &Asm, std::vector<ELFRelocationEntry> &Relocs) { - // Sort by the r_offset, just like gnu as does. - array_pod_sort(Relocs.begin(), Relocs.end()); + array_pod_sort(Relocs.begin(), Relocs.end(), cmpRel); } diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 7f5f1b6..6e5ff50 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -13,6 +13,7 @@ #include "llvm/MC/MCELFStreamer.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" @@ -108,14 +109,15 @@ void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { llvm_unreachable("invalid assembler flag!"); } -void MCELFStreamer::ChangeSection(const MCSection *Section) { +void MCELFStreamer::ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { MCSectionData *CurSection = getCurrentSectionData(); if (CurSection && CurSection->isBundleLocked()) report_fatal_error("Unterminated .bundle_lock when changing a section"); const MCSymbol *Grp = static_cast<const MCSectionELF *>(Section)->getGroup(); if (Grp) getAssembler().getOrCreateSymbolData(*Grp); - this->MCObjectStreamer::ChangeSection(Section); + this->MCObjectStreamer::ChangeSection(Section, Subsection); } void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { @@ -126,6 +128,26 @@ void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { Alias->setVariableValue(Value); } +// When GNU as encounters more than one .type declaration for an object it seems +// to use a mechanism similar to the one below to decide which type is actually +// used in the object file. The greater of T1 and T2 is selected based on the +// following ordering: +// STT_NOTYPE < STT_OBJECT < STT_FUNC < STT_GNU_IFUNC < STT_TLS < anything else +// If neither T1 < T2 nor T2 < T1 according to this ordering, use T2 (the user +// provided type). +static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) { + unsigned TypeOrdering[] = {ELF::STT_NOTYPE, ELF::STT_OBJECT, ELF::STT_FUNC, + ELF::STT_GNU_IFUNC, ELF::STT_TLS}; + for (unsigned i = 0; i != array_lengthof(TypeOrdering); ++i) { + if (T1 == TypeOrdering[i]) + return T2; + if (T2 == TypeOrdering[i]) + return T1; + } + + return T2; +} + void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { // Indirect symbols are handled differently, to match how 'as' handles @@ -187,27 +209,34 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, break; case MCSA_ELF_TypeFunction: - MCELF::SetType(SD, ELF::STT_FUNC); + MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), + ELF::STT_FUNC)); break; case MCSA_ELF_TypeIndFunction: - MCELF::SetType(SD, ELF::STT_GNU_IFUNC); + MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), + ELF::STT_GNU_IFUNC)); break; case MCSA_ELF_TypeObject: - MCELF::SetType(SD, ELF::STT_OBJECT); + MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), + ELF::STT_OBJECT)); break; case MCSA_ELF_TypeTLS: - MCELF::SetType(SD, ELF::STT_TLS); + MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), + ELF::STT_TLS)); break; case MCSA_ELF_TypeCommon: - MCELF::SetType(SD, ELF::STT_COMMON); + // TODO: Emit these as a common symbol. + MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), + ELF::STT_OBJECT)); break; case MCSA_ELF_TypeNoType: - MCELF::SetType(SD, ELF::STT_NOTYPE); + MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), + ELF::STT_NOTYPE)); break; case MCSA_Protected: @@ -267,12 +296,11 @@ void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, EmitCommonSymbol(Symbol, Size, ByteAlignment); } -void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) { +void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size) { if (getCurrentSectionData()->isBundleLocked()) report_fatal_error("Emitting values inside a locked bundle is forbidden"); fixSymbolsInTLSFixups(Value); - MCObjectStreamer::EmitValueImpl(Value, Size, AddrSpace); + MCObjectStreamer::EmitValueImpl(Value, Size); } void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, @@ -290,7 +318,7 @@ void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, // entry in the module's symbol table (the first being the null symbol). void MCELFStreamer::EmitFileDirective(StringRef Filename) { MCSymbol *Symbol = getAssembler().getContext().GetOrCreateSymbol(Filename); - Symbol->setSection(*getCurrentSection()); + Symbol->setSection(*getCurrentSection().first); Symbol->setAbsolute(); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); @@ -334,18 +362,41 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { case MCSymbolRefExpr::VK_Mips_GOTTPREL: case MCSymbolRefExpr::VK_Mips_TPREL_HI: case MCSymbolRefExpr::VK_Mips_TPREL_LO: - case MCSymbolRefExpr::VK_PPC_TPREL16_HA: - case MCSymbolRefExpr::VK_PPC_TPREL16_LO: - case MCSymbolRefExpr::VK_PPC_DTPREL16_HA: - case MCSymbolRefExpr::VK_PPC_DTPREL16_LO: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_HA: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_LO: + case MCSymbolRefExpr::VK_PPC_DTPMOD: + case MCSymbolRefExpr::VK_PPC_TPREL: + case MCSymbolRefExpr::VK_PPC_TPREL_LO: + case MCSymbolRefExpr::VK_PPC_TPREL_HI: + case MCSymbolRefExpr::VK_PPC_TPREL_HA: + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: + case MCSymbolRefExpr::VK_PPC_DTPREL: + case MCSymbolRefExpr::VK_PPC_DTPREL_LO: + case MCSymbolRefExpr::VK_PPC_DTPREL_HI: + case MCSymbolRefExpr::VK_PPC_DTPREL_HA: + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: + case MCSymbolRefExpr::VK_PPC_GOT_TPREL: + case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: + case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: + case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: case MCSymbolRefExpr::VK_PPC_TLS: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_HA: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_LO: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: case MCSymbolRefExpr::VK_PPC_TLSGD: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_HA: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO: + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: case MCSymbolRefExpr::VK_PPC_TLSLD: break; } @@ -406,11 +457,13 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) { // Optimize memory usage by emitting the instruction to a // MCCompactEncodedInstFragment when not in a bundle-locked group and // there are no fixups registered. - MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(SD); + MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(); + insert(CEIF); CEIF->getContents().append(Code.begin(), Code.end()); return; } else { - DF = new MCDataFragment(SD); + DF = new MCDataFragment(); + insert(DF); if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) { // If this is a new fragment created for a bundle-locked group, and the // group was marked as "align_to_end", set a flag in the fragment. diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 1a53934..c777e64 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -42,13 +42,6 @@ void MCExpr::print(raw_ostream &OS) const { // Parenthesize names that start with $ so that they don't look like // absolute names. bool UseParens = Sym.getName()[0] == '$'; - - if (SRE.getKind() == MCSymbolRefExpr::VK_PPC_DARWIN_HA16 || - SRE.getKind() == MCSymbolRefExpr::VK_PPC_DARWIN_LO16) { - OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); - UseParens = true; - } - if (UseParens) OS << '(' << Sym << ')'; else @@ -65,9 +58,7 @@ void MCExpr::print(raw_ostream &OS) const { SRE.getKind() == MCSymbolRefExpr::VK_ARM_TARGET2 || SRE.getKind() == MCSymbolRefExpr::VK_ARM_PREL31) OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); - else if (SRE.getKind() != MCSymbolRefExpr::VK_None && - SRE.getKind() != MCSymbolRefExpr::VK_PPC_DARWIN_HA16 && - SRE.getKind() != MCSymbolRefExpr::VK_PPC_DARWIN_LO16) + else if (SRE.getKind() != MCSymbolRefExpr::VK_None) OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); return; @@ -194,7 +185,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_TPOFF: return "TPOFF"; case VK_DTPOFF: return "DTPOFF"; case VK_TLVP: return "TLVP"; - case VK_SECREL: return "SECREL"; + case VK_SECREL: return "SECREL32"; case VK_ARM_NONE: return "(NONE)"; case VK_ARM_PLT: return "(PLT)"; case VK_ARM_GOT: return "(GOT)"; @@ -205,26 +196,56 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_ARM_TARGET1: return "(target1)"; case VK_ARM_TARGET2: return "(target2)"; case VK_ARM_PREL31: return "(prel31)"; - case VK_PPC_TOC: return "tocbase"; - case VK_PPC_TOC_ENTRY: return "toc"; - case VK_PPC_DARWIN_HA16: return "ha16"; - case VK_PPC_DARWIN_LO16: return "lo16"; - case VK_PPC_GAS_HA16: return "ha"; - case VK_PPC_GAS_LO16: return "l"; - case VK_PPC_TPREL16_HA: return "tprel@ha"; - case VK_PPC_TPREL16_LO: return "tprel@l"; - case VK_PPC_DTPREL16_HA: return "dtprel@ha"; - case VK_PPC_DTPREL16_LO: return "dtprel@l"; - case VK_PPC_TOC16_HA: return "toc@ha"; - case VK_PPC_TOC16_LO: return "toc@l"; - case VK_PPC_GOT_TPREL16_HA: return "got@tprel@ha"; - case VK_PPC_GOT_TPREL16_LO: return "got@tprel@l"; + case VK_PPC_LO: return "l"; + case VK_PPC_HI: return "h"; + case VK_PPC_HA: return "ha"; + case VK_PPC_HIGHER: return "higher"; + case VK_PPC_HIGHERA: return "highera"; + case VK_PPC_HIGHEST: return "highest"; + case VK_PPC_HIGHESTA: return "highesta"; + case VK_PPC_GOT_LO: return "got@l"; + case VK_PPC_GOT_HI: return "got@h"; + case VK_PPC_GOT_HA: return "got@ha"; + case VK_PPC_TOCBASE: return "tocbase"; + case VK_PPC_TOC: return "toc"; + case VK_PPC_TOC_LO: return "toc@l"; + case VK_PPC_TOC_HI: return "toc@h"; + case VK_PPC_TOC_HA: return "toc@ha"; + case VK_PPC_DTPMOD: return "dtpmod"; + case VK_PPC_TPREL: return "tprel"; + case VK_PPC_TPREL_LO: return "tprel@l"; + case VK_PPC_TPREL_HI: return "tprel@h"; + case VK_PPC_TPREL_HA: return "tprel@ha"; + case VK_PPC_TPREL_HIGHER: return "tprel@higher"; + case VK_PPC_TPREL_HIGHERA: return "tprel@highera"; + case VK_PPC_TPREL_HIGHEST: return "tprel@highest"; + case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta"; + case VK_PPC_DTPREL: return "dtprel"; + case VK_PPC_DTPREL_LO: return "dtprel@l"; + case VK_PPC_DTPREL_HI: return "dtprel@h"; + case VK_PPC_DTPREL_HA: return "dtprel@ha"; + case VK_PPC_DTPREL_HIGHER: return "dtprel@higher"; + case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera"; + case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest"; + case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta"; + case VK_PPC_GOT_TPREL: return "got@tprel"; + case VK_PPC_GOT_TPREL_LO: return "got@tprel@l"; + case VK_PPC_GOT_TPREL_HI: return "got@tprel@h"; + case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha"; + case VK_PPC_GOT_DTPREL: return "got@dtprel"; + case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l"; + case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h"; + case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha"; case VK_PPC_TLS: return "tls"; - case VK_PPC_GOT_TLSGD16_HA: return "got@tlsgd@ha"; - case VK_PPC_GOT_TLSGD16_LO: return "got@tlsgd@l"; - case VK_PPC_GOT_TLSLD16_HA: return "got@tlsld@ha"; - case VK_PPC_GOT_TLSLD16_LO: return "got@tlsld@l"; + case VK_PPC_GOT_TLSGD: return "got@tlsgd"; + case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l"; + case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h"; + case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha"; case VK_PPC_TLSGD: return "tlsgd"; + case VK_PPC_GOT_TLSLD: return "got@tlsld"; + case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l"; + case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; + case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; case VK_PPC_TLSLD: return "tlsld"; case VK_Mips_GPREL: return "GPREL"; case VK_Mips_GOT_CALL: return "GOT_CALL"; @@ -250,6 +271,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_Mips_GOT_LO16: return "GOT_LO16"; case VK_Mips_CALL_HI16: return "CALL_HI16"; case VK_Mips_CALL_LO16: return "CALL_LO16"; + case VK_COFF_IMGREL32: return "IMGREL32"; } llvm_unreachable("Invalid variant kind"); } @@ -285,6 +307,108 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .Case("dtpoff", VK_DTPOFF) .Case("TLVP", VK_TLVP) .Case("tlvp", VK_TLVP) + .Case("IMGREL", VK_COFF_IMGREL32) + .Case("imgrel", VK_COFF_IMGREL32) + .Case("SECREL32", VK_SECREL) + .Case("secrel32", VK_SECREL) + .Case("L", VK_PPC_LO) + .Case("l", VK_PPC_LO) + .Case("H", VK_PPC_HI) + .Case("h", VK_PPC_HI) + .Case("HA", VK_PPC_HA) + .Case("ha", VK_PPC_HA) + .Case("HIGHER", VK_PPC_HIGHER) + .Case("higher", VK_PPC_HIGHER) + .Case("HIGHERA", VK_PPC_HIGHERA) + .Case("highera", VK_PPC_HIGHERA) + .Case("HIGHEST", VK_PPC_HIGHEST) + .Case("highest", VK_PPC_HIGHEST) + .Case("HIGHESTA", VK_PPC_HIGHESTA) + .Case("highesta", VK_PPC_HIGHESTA) + .Case("GOT@L", VK_PPC_GOT_LO) + .Case("got@l", VK_PPC_GOT_LO) + .Case("GOT@H", VK_PPC_GOT_HI) + .Case("got@h", VK_PPC_GOT_HI) + .Case("GOT@HA", VK_PPC_GOT_HA) + .Case("got@ha", VK_PPC_GOT_HA) + .Case("TOCBASE", VK_PPC_TOCBASE) + .Case("tocbase", VK_PPC_TOCBASE) + .Case("TOC", VK_PPC_TOC) + .Case("toc", VK_PPC_TOC) + .Case("TOC@L", VK_PPC_TOC_LO) + .Case("toc@l", VK_PPC_TOC_LO) + .Case("TOC@H", VK_PPC_TOC_HI) + .Case("toc@h", VK_PPC_TOC_HI) + .Case("TOC@HA", VK_PPC_TOC_HA) + .Case("toc@ha", VK_PPC_TOC_HA) + .Case("TLS", VK_PPC_TLS) + .Case("tls", VK_PPC_TLS) + .Case("DTPMOD", VK_PPC_DTPMOD) + .Case("dtpmod", VK_PPC_DTPMOD) + .Case("TPREL", VK_PPC_TPREL) + .Case("tprel", VK_PPC_TPREL) + .Case("TPREL@L", VK_PPC_TPREL_LO) + .Case("tprel@l", VK_PPC_TPREL_LO) + .Case("TPREL@H", VK_PPC_TPREL_HI) + .Case("tprel@h", VK_PPC_TPREL_HI) + .Case("TPREL@HA", VK_PPC_TPREL_HA) + .Case("tprel@ha", VK_PPC_TPREL_HA) + .Case("TPREL@HIGHER", VK_PPC_TPREL_HIGHER) + .Case("tprel@higher", VK_PPC_TPREL_HIGHER) + .Case("TPREL@HIGHERA", VK_PPC_TPREL_HIGHERA) + .Case("tprel@highera", VK_PPC_TPREL_HIGHERA) + .Case("TPREL@HIGHEST", VK_PPC_TPREL_HIGHEST) + .Case("tprel@highest", VK_PPC_TPREL_HIGHEST) + .Case("TPREL@HIGHESTA", VK_PPC_TPREL_HIGHESTA) + .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA) + .Case("DTPREL", VK_PPC_DTPREL) + .Case("dtprel", VK_PPC_DTPREL) + .Case("DTPREL@L", VK_PPC_DTPREL_LO) + .Case("dtprel@l", VK_PPC_DTPREL_LO) + .Case("DTPREL@H", VK_PPC_DTPREL_HI) + .Case("dtprel@h", VK_PPC_DTPREL_HI) + .Case("DTPREL@HA", VK_PPC_DTPREL_HA) + .Case("dtprel@ha", VK_PPC_DTPREL_HA) + .Case("DTPREL@HIGHER", VK_PPC_DTPREL_HIGHER) + .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER) + .Case("DTPREL@HIGHERA", VK_PPC_DTPREL_HIGHERA) + .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA) + .Case("DTPREL@HIGHEST", VK_PPC_DTPREL_HIGHEST) + .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST) + .Case("DTPREL@HIGHESTA", VK_PPC_DTPREL_HIGHESTA) + .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA) + .Case("GOT@TPREL", VK_PPC_GOT_TPREL) + .Case("got@tprel", VK_PPC_GOT_TPREL) + .Case("GOT@TPREL@L", VK_PPC_GOT_TPREL_LO) + .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO) + .Case("GOT@TPREL@H", VK_PPC_GOT_TPREL_HI) + .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI) + .Case("GOT@TPREL@HA", VK_PPC_GOT_TPREL_HA) + .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA) + .Case("GOT@DTPREL", VK_PPC_GOT_DTPREL) + .Case("got@dtprel", VK_PPC_GOT_DTPREL) + .Case("GOT@DTPREL@L", VK_PPC_GOT_DTPREL_LO) + .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO) + .Case("GOT@DTPREL@H", VK_PPC_GOT_DTPREL_HI) + .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI) + .Case("GOT@DTPREL@HA", VK_PPC_GOT_DTPREL_HA) + .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA) + .Case("GOT@TLSGD", VK_PPC_GOT_TLSGD) + .Case("got@tlsgd", VK_PPC_GOT_TLSGD) + .Case("GOT@TLSGD@L", VK_PPC_GOT_TLSGD_LO) + .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO) + .Case("GOT@TLSGD@H", VK_PPC_GOT_TLSGD_HI) + .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI) + .Case("GOT@TLSGD@HA", VK_PPC_GOT_TLSGD_HA) + .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA) + .Case("GOT@TLSLD", VK_PPC_GOT_TLSLD) + .Case("got@tlsld", VK_PPC_GOT_TLSLD) + .Case("GOT@TLSLD@L", VK_PPC_GOT_TLSLD_LO) + .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO) + .Case("GOT@TLSLD@H", VK_PPC_GOT_TLSLD_HI) + .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) + .Case("GOT@TLSLD@HA", VK_PPC_GOT_TLSLD_HA) + .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) .Default(VK_Invalid); } diff --git a/lib/MC/MCExternalSymbolizer.cpp b/lib/MC/MCExternalSymbolizer.cpp new file mode 100644 index 0000000..47ef6c4 --- /dev/null +++ b/lib/MC/MCExternalSymbolizer.cpp @@ -0,0 +1,160 @@ +//===-- lib/MC/MCExternalSymbolizer.cpp - External symbolizer ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCExternalSymbolizer.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/raw_ostream.h" +#include <cstring> + +using namespace llvm; + +// This function tries to add a symbolic operand in place of the immediate +// Value in the MCInst. The immediate Value has had any PC adjustment made by +// the caller. If the instruction is a branch instruction then IsBranch is true, +// else false. If the getOpInfo() function was set as part of the +// setupForSymbolicDisassembly() call then that function is called to get any +// symbolic information at the Address for this instruction. If that returns +// non-zero then the symbolic information it returns is used to create an MCExpr +// and that is added as an operand to the MCInst. If getOpInfo() returns zero +// and IsBranch is true then a symbol look up for Value is done and if a symbol +// is found an MCExpr is created with that, else an MCExpr with Value is +// created. This function returns true if it adds an operand to the MCInst and +// false otherwise. +bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, + raw_ostream &cStream, + int64_t Value, + uint64_t Address, + bool IsBranch, + uint64_t Offset, + uint64_t InstSize) { + struct LLVMOpInfo1 SymbolicOp; + std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); + SymbolicOp.Value = Value; + + if (!GetOpInfo || + !GetOpInfo(DisInfo, Address, Offset, InstSize, 1, &SymbolicOp)) { + // Clear SymbolicOp.Value from above and also all other fields. + std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); + if (!SymbolLookUp) + return false; + uint64_t ReferenceType; + if (IsBranch) + ReferenceType = LLVMDisassembler_ReferenceType_In_Branch; + else + ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; + const char *ReferenceName; + const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address, + &ReferenceName); + if (Name) { + SymbolicOp.AddSymbol.Name = Name; + SymbolicOp.AddSymbol.Present = true; + } + // For branches always create an MCExpr so it gets printed as hex address. + else if (IsBranch) { + SymbolicOp.Value = Value; + } + if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub) + cStream << "symbol stub for: " << ReferenceName; + if (!Name && !IsBranch) + return false; + } + + const MCExpr *Add = NULL; + if (SymbolicOp.AddSymbol.Present) { + if (SymbolicOp.AddSymbol.Name) { + StringRef Name(SymbolicOp.AddSymbol.Name); + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name); + Add = MCSymbolRefExpr::Create(Sym, Ctx); + } else { + Add = MCConstantExpr::Create((int)SymbolicOp.AddSymbol.Value, Ctx); + } + } + + const MCExpr *Sub = NULL; + if (SymbolicOp.SubtractSymbol.Present) { + if (SymbolicOp.SubtractSymbol.Name) { + StringRef Name(SymbolicOp.SubtractSymbol.Name); + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name); + Sub = MCSymbolRefExpr::Create(Sym, Ctx); + } else { + Sub = MCConstantExpr::Create((int)SymbolicOp.SubtractSymbol.Value, Ctx); + } + } + + const MCExpr *Off = NULL; + if (SymbolicOp.Value != 0) + Off = MCConstantExpr::Create(SymbolicOp.Value, Ctx); + + const MCExpr *Expr; + if (Sub) { + const MCExpr *LHS; + if (Add) + LHS = MCBinaryExpr::CreateSub(Add, Sub, Ctx); + else + LHS = MCUnaryExpr::CreateMinus(Sub, Ctx); + if (Off != 0) + Expr = MCBinaryExpr::CreateAdd(LHS, Off, Ctx); + else + Expr = LHS; + } else if (Add) { + if (Off != 0) + Expr = MCBinaryExpr::CreateAdd(Add, Off, Ctx); + else + Expr = Add; + } else { + if (Off != 0) + Expr = Off; + else + Expr = MCConstantExpr::Create(0, Ctx); + } + + Expr = RelInfo->createExprForCAPIVariantKind(Expr, SymbolicOp.VariantKind); + if (!Expr) + return false; + + MI.addOperand(MCOperand::CreateExpr(Expr)); + return true; +} + +// This function tries to add a comment as to what is being referenced by a load +// instruction with the base register that is the Pc. These can often be values +// in a literal pool near the Address of the instruction. The Address of the +// instruction and its immediate Value are used as a possible literal pool entry. +// The SymbolLookUp call back will return the name of a symbol referenced by the +// literal pool's entry if the referenced address is that of a symbol. Or it +// will return a pointer to a literal 'C' string if the referenced address of +// the literal pool's entry is an address into a section with C string literals. +void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream, + int64_t Value, + uint64_t Address) { + if (SymbolLookUp) { + uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load; + const char *ReferenceName; + (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName); + if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr || + ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) + cStream << "literal pool for: " << ReferenceName; + } +} + +namespace llvm { +MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, + void *DisInfo, + MCContext *Ctx, + MCRelocationInfo *RelInfo) { + assert(Ctx != 0 && "No MCContext given for symbolic disassembly"); + + OwningPtr<MCRelocationInfo> RelInfoOwingPtr(RelInfo); + return new MCExternalSymbolizer(*Ctx, RelInfoOwingPtr, GetOpInfo, + SymbolLookUp, DisInfo); +} +} diff --git a/lib/MC/MCFunction.cpp b/lib/MC/MCFunction.cpp new file mode 100644 index 0000000..2665d3e --- /dev/null +++ b/lib/MC/MCFunction.cpp @@ -0,0 +1,55 @@ +//===-- lib/MC/MCFunction.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCFunction.h" +#include "llvm/MC/MCAtom.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> + +using namespace llvm; + +// MCFunction + +MCFunction::MCFunction(StringRef Name) + : Name(Name) +{} + +MCFunction::~MCFunction() { + for (iterator I = begin(), E = end(); I != E; ++I) + delete *I; +} + +MCBasicBlock &MCFunction::createBlock(const MCTextAtom &TA) { + Blocks.push_back(new MCBasicBlock(TA, this)); + return *Blocks.back(); +} + +// MCBasicBlock + +MCBasicBlock::MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent) + : Insts(&Insts), Parent(Parent) +{} + +void MCBasicBlock::addSuccessor(const MCBasicBlock *MCBB) { + Successors.push_back(MCBB); +} + +bool MCBasicBlock::isSuccessor(const MCBasicBlock *MCBB) const { + return std::find(Successors.begin(), Successors.end(), + MCBB) != Successors.end(); +} + +void MCBasicBlock::addPredecessor(const MCBasicBlock *MCBB) { + Predecessors.push_back(MCBB); +} + +bool MCBasicBlock::isPredecessor(const MCBasicBlock *MCBB) const { + return std::find(Predecessors.begin(), Predecessors.end(), + MCBB) != Predecessors.end(); +} diff --git a/lib/MC/MCInstPrinter.cpp b/lib/MC/MCInstPrinter.cpp index 73f30ff..6a452c8 100644 --- a/lib/MC/MCInstPrinter.cpp +++ b/lib/MC/MCInstPrinter.cpp @@ -52,10 +52,55 @@ StringRef MCInstPrinter::markup(StringRef a, StringRef b) const { return b; } -/// Utility function to print immediates in decimal or hex. -format_object1<int64_t> MCInstPrinter::formatImm(const int64_t Value) const { - if (getPrintImmHex()) - return format("0x%" PRIx64, Value); - else - return format("%" PRId64, Value); +// For asm-style hex (e.g. 0ffh) the first digit always has to be a number. +static bool needsLeadingZero(uint64_t Value) +{ + while(Value) + { + uint64_t digit = (Value >> 60) & 0xf; + if (digit != 0) + return (digit >= 0xa); + Value <<= 4; + } + return false; +} + +format_object1<int64_t> MCInstPrinter::formatDec(const int64_t Value) const { + return format("%" PRId64, Value); +} + +format_object1<int64_t> MCInstPrinter::formatHex(const int64_t Value) const { + switch(PrintHexStyle) { + case HexStyle::C: + if (Value < 0) + return format("-0x%" PRIx64, -Value); + else + return format("0x%" PRIx64, Value); + case HexStyle::Asm: + if (Value < 0) { + if (needsLeadingZero((uint64_t)(-Value))) + return format("-0%" PRIx64 "h", -Value); + else + return format("-%" PRIx64 "h", -Value); + } else { + if (needsLeadingZero((uint64_t)(Value))) + return format("0%" PRIx64 "h", Value); + else + return format("%" PRIx64 "h", Value); + } + } + llvm_unreachable("unsupported print style"); +} + +format_object1<uint64_t> MCInstPrinter::formatHex(const uint64_t Value) const { + switch(PrintHexStyle) { + case HexStyle::C: + return format("0x%" PRIx64, Value); + case HexStyle::Asm: + if (needsLeadingZero(Value)) + return format("0%" PRIx64 "h", Value); + else + return format("%" PRIx64 "h", Value); + } + llvm_unreachable("unsupported print style"); } diff --git a/lib/MC/MCInstrAnalysis.cpp b/lib/MC/MCInstrAnalysis.cpp index 7736702..2d8336d 100644 --- a/lib/MC/MCInstrAnalysis.cpp +++ b/lib/MC/MCInstrAnalysis.cpp @@ -10,12 +10,13 @@ #include "llvm/MC/MCInstrAnalysis.h" using namespace llvm; -uint64_t MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr, - uint64_t Size) const { +bool MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr, + uint64_t Size, uint64_t &Target) const { if (Inst.getNumOperands() == 0 || Info->get(Inst.getOpcode()).OpInfo[0].OperandType != MCOI::OPERAND_PCREL) - return -1ULL; + return false; int64_t Imm = Inst.getOperand(0).getImm(); - return Addr+Size+Imm; + Target = Addr+Size+Imm; + return true; } diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 7d08d0e..0729b7a 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -122,11 +122,11 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); // isSymbolLinkerVisible uses the section. - Symbol->setSection(*getCurrentSection()); + Symbol->setSection(*getCurrentSection().first); // We have to create a new fragment if this is an atom defining symbol, // fragments cannot span atoms. if (getAssembler().isSymbolLinkerVisible(*Symbol)) - new MCDataFragment(getCurrentSectionData()); + insert(new MCDataFragment()); MCObjectStreamer::EmitLabel(Symbol); @@ -346,7 +346,8 @@ void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, if (!Symbol) return; - // FIXME: Assert that this section has the zerofill type. + // On darwin all virtual sections have zerofill type. + assert(Section->isVirtualSection() && "Section does not have zerofill type!"); assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); diff --git a/lib/MC/MCModule.cpp b/lib/MC/MCModule.cpp index f563160..5890b4b 100644 --- a/lib/MC/MCModule.cpp +++ b/lib/MC/MCModule.cpp @@ -7,39 +7,91 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCAtom.h" #include "llvm/MC/MCModule.h" +#include "llvm/MC/MCAtom.h" +#include "llvm/MC/MCFunction.h" +#include <algorithm> using namespace llvm; -MCAtom *MCModule::createAtom(MCAtom::AtomType Type, - uint64_t Begin, uint64_t End) { - assert(Begin < End && "Creating MCAtom with endpoints reversed?"); +static bool AtomComp(const MCAtom *L, uint64_t Addr) { + return L->getEndAddr() < Addr; +} + +void MCModule::map(MCAtom *NewAtom) { + uint64_t Begin = NewAtom->Begin; + + assert(Begin <= NewAtom->End && "Creating MCAtom with endpoints reversed?"); // Check for atoms already covering this range. - IntervalMap<uint64_t, MCAtom*>::iterator I = OffsetMap.find(Begin); - assert((!I.valid() || I.start() < End) && "Offset range already occupied!"); + AtomListTy::iterator I = std::lower_bound(atom_begin(), atom_end(), + Begin, AtomComp); + assert((I == atom_end() || (*I)->getBeginAddr() > NewAtom->End) + && "Offset range already occupied!"); - // Create the new atom and add it to our maps. - MCAtom *NewAtom = new MCAtom(Type, this, Begin, End); - AtomAllocationTracker.insert(NewAtom); - OffsetMap.insert(Begin, End, NewAtom); + // Insert the new atom to the list. + Atoms.insert(I, NewAtom); +} + +MCTextAtom *MCModule::createTextAtom(uint64_t Begin, uint64_t End) { + MCTextAtom *NewAtom = new MCTextAtom(this, Begin, End); + map(NewAtom); + return NewAtom; +} + +MCDataAtom *MCModule::createDataAtom(uint64_t Begin, uint64_t End) { + MCDataAtom *NewAtom = new MCDataAtom(this, Begin, End); + map(NewAtom); return NewAtom; } // remap - Update the interval mapping for an atom. void MCModule::remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd) { // Find and erase the old mapping. - IntervalMap<uint64_t, MCAtom*>::iterator I = OffsetMap.find(Atom->Begin); - assert(I.valid() && "Atom offset not found in module!"); + AtomListTy::iterator I = std::lower_bound(atom_begin(), atom_end(), + Atom->Begin, AtomComp); + assert(I != atom_end() && "Atom offset not found in module!"); assert(*I == Atom && "Previous atom mapping was invalid!"); - I.erase(); + Atoms.erase(I); // Insert the new mapping. - OffsetMap.insert(NewBegin, NewEnd, Atom); + AtomListTy::iterator NewI = std::lower_bound(atom_begin(), atom_end(), + NewBegin, AtomComp); + Atoms.insert(NewI, Atom); // Update the atom internal bounds. Atom->Begin = NewBegin; Atom->End = NewEnd; } +const MCAtom *MCModule::findAtomContaining(uint64_t Addr) const { + AtomListTy::const_iterator I = std::lower_bound(atom_begin(), atom_end(), + Addr, AtomComp); + if (I != atom_end() && (*I)->getBeginAddr() <= Addr) + return *I; + return 0; +} + +MCAtom *MCModule::findAtomContaining(uint64_t Addr) { + AtomListTy::iterator I = std::lower_bound(atom_begin(), atom_end(), + Addr, AtomComp); + if (I != atom_end() && (*I)->getBeginAddr() <= Addr) + return *I; + return 0; +} + +MCFunction *MCModule::createFunction(const StringRef &Name) { + Functions.push_back(new MCFunction(Name)); + return Functions.back(); +} + +MCModule::~MCModule() { + for (AtomListTy::iterator AI = atom_begin(), + AE = atom_end(); + AI != AE; ++AI) + delete *AI; + for (FunctionListTy::iterator FI = func_begin(), + FE = func_end(); + FI != FE; ++FI) + delete *FI; +} diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index c872b22..530c646 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -30,13 +30,14 @@ namespace { virtual void InitSections() { } - virtual void ChangeSection(const MCSection *Section) { + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { } virtual void EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - assert(getCurrentSection() && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection()); + assert(getCurrentSection().first &&"Cannot emit before setting section!"); + Symbol->setSection(*getCurrentSection().first); } virtual void EmitDebugLabel(MCSymbol *Symbol) { EmitLabel(Symbol); @@ -70,10 +71,9 @@ namespace { uint64_t Size = 0, unsigned ByteAlignment = 0) {} virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) {} - virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {} + virtual void EmitBytes(StringRef Data) {} - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) {} + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) {} virtual void EmitULEB128Value(const MCExpr *Value) {} virtual void EmitSLEB128Value(const MCExpr *Value) {} virtual void EmitGPRel32Value(const MCExpr *Value) {} diff --git a/lib/MC/MCObjectDisassembler.cpp b/lib/MC/MCObjectDisassembler.cpp new file mode 100644 index 0000000..1ea6eed --- /dev/null +++ b/lib/MC/MCObjectDisassembler.cpp @@ -0,0 +1,216 @@ +//===- lib/MC/MCObjectDisassembler.cpp ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCObjectDisassembler.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAtom.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCFunction.h" +#include "llvm/MC/MCInstrAnalysis.h" +#include "llvm/MC/MCModule.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/StringRefMemoryObject.h" +#include "llvm/Support/raw_ostream.h" +#include <map> +#include <set> + +using namespace llvm; +using namespace object; + +MCObjectDisassembler::MCObjectDisassembler(const ObjectFile &Obj, + const MCDisassembler &Dis, + const MCInstrAnalysis &MIA) + : Obj(Obj), Dis(Dis), MIA(MIA) {} + +MCModule *MCObjectDisassembler::buildModule(bool withCFG) { + MCModule *Module = new MCModule; + buildSectionAtoms(Module); + if (withCFG) + buildCFG(Module); + return Module; +} + +void MCObjectDisassembler::buildSectionAtoms(MCModule *Module) { + error_code ec; + for (section_iterator SI = Obj.begin_sections(), + SE = Obj.end_sections(); + SI != SE; + SI.increment(ec)) { + if (ec) break; + + bool isText; SI->isText(isText); + bool isData; SI->isData(isData); + if (!isData && !isText) + continue; + + uint64_t StartAddr; SI->getAddress(StartAddr); + uint64_t SecSize; SI->getSize(SecSize); + if (StartAddr == UnknownAddressOrSize || SecSize == UnknownAddressOrSize) + continue; + + StringRef Contents; SI->getContents(Contents); + StringRefMemoryObject memoryObject(Contents); + + // We don't care about things like non-file-backed sections yet. + if (Contents.size() != SecSize || !SecSize) + continue; + uint64_t EndAddr = StartAddr + SecSize - 1; + + StringRef SecName; SI->getName(SecName); + + if (isText) { + MCTextAtom *Text = Module->createTextAtom(StartAddr, EndAddr); + Text->setName(SecName); + uint64_t InstSize; + for (uint64_t Index = 0; Index < SecSize; Index += InstSize) { + MCInst Inst; + if (Dis.getInstruction(Inst, InstSize, memoryObject, Index, + nulls(), nulls())) + Text->addInst(Inst, InstSize); + else + // We don't care about splitting mixed atoms either. + llvm_unreachable("Couldn't disassemble instruction in atom."); + } + + } else { + MCDataAtom *Data = Module->createDataAtom(StartAddr, EndAddr); + Data->setName(SecName); + for (uint64_t Index = 0; Index < SecSize; ++Index) + Data->addData(Contents[Index]); + } + } +} + +namespace { + struct BBInfo; + typedef std::set<BBInfo*> BBInfoSetTy; + + struct BBInfo { + MCTextAtom *Atom; + MCBasicBlock *BB; + BBInfoSetTy Succs; + BBInfoSetTy Preds; + + void addSucc(BBInfo &Succ) { + Succs.insert(&Succ); + Succ.Preds.insert(this); + } + }; +} + +void MCObjectDisassembler::buildCFG(MCModule *Module) { + typedef std::map<uint64_t, BBInfo> BBInfoByAddrTy; + BBInfoByAddrTy BBInfos; + typedef std::set<uint64_t> AddressSetTy; + AddressSetTy Splits; + AddressSetTy Calls; + + assert(Module->func_begin() == Module->func_end() + && "Module already has a CFG!"); + + // First, determine the basic block boundaries and call targets. + for (MCModule::atom_iterator AI = Module->atom_begin(), + AE = Module->atom_end(); + AI != AE; ++AI) { + MCTextAtom *TA = dyn_cast<MCTextAtom>(*AI); + if (!TA) continue; + Calls.insert(TA->getBeginAddr()); + BBInfos[TA->getBeginAddr()].Atom = TA; + for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end(); + II != IE; ++II) { + if (MIA.isTerminator(II->Inst)) + Splits.insert(II->Address + II->Size); + uint64_t Target; + if (MIA.evaluateBranch(II->Inst, II->Address, II->Size, Target)) { + if (MIA.isCall(II->Inst)) + Calls.insert(Target); + Splits.insert(Target); + } + } + } + + // Split text atoms into basic block atoms. + for (AddressSetTy::const_iterator SI = Splits.begin(), SE = Splits.end(); + SI != SE; ++SI) { + MCAtom *A = Module->findAtomContaining(*SI); + if (!A) continue; + MCTextAtom *TA = cast<MCTextAtom>(A); + if (TA->getBeginAddr() == *SI) + continue; + MCTextAtom *NewAtom = TA->split(*SI); + BBInfos[NewAtom->getBeginAddr()].Atom = NewAtom; + StringRef BBName = TA->getName(); + BBName = BBName.substr(0, BBName.find_last_of(':')); + NewAtom->setName((BBName + ":" + utohexstr(*SI)).str()); + } + + // Compute succs/preds. + for (MCModule::atom_iterator AI = Module->atom_begin(), + AE = Module->atom_end(); + AI != AE; ++AI) { + MCTextAtom *TA = dyn_cast<MCTextAtom>(*AI); + if (!TA) continue; + BBInfo &CurBB = BBInfos[TA->getBeginAddr()]; + const MCDecodedInst &LI = TA->back(); + if (MIA.isBranch(LI.Inst)) { + uint64_t Target; + if (MIA.evaluateBranch(LI.Inst, LI.Address, LI.Size, Target)) + CurBB.addSucc(BBInfos[Target]); + if (MIA.isConditionalBranch(LI.Inst)) + CurBB.addSucc(BBInfos[LI.Address + LI.Size]); + } else if (!MIA.isTerminator(LI.Inst)) + CurBB.addSucc(BBInfos[LI.Address + LI.Size]); + } + + + // Create functions and basic blocks. + for (AddressSetTy::const_iterator CI = Calls.begin(), CE = Calls.end(); + CI != CE; ++CI) { + BBInfo &BBI = BBInfos[*CI]; + if (!BBI.Atom) continue; + + MCFunction &MCFN = *Module->createFunction(BBI.Atom->getName()); + + // Create MCBBs. + SmallSetVector<BBInfo*, 16> Worklist; + Worklist.insert(&BBI); + for (size_t WI = 0; WI < Worklist.size(); ++WI) { + BBInfo *BBI = Worklist[WI]; + if (!BBI->Atom) + continue; + BBI->BB = &MCFN.createBlock(*BBI->Atom); + // Add all predecessors and successors to the worklist. + for (BBInfoSetTy::iterator SI = BBI->Succs.begin(), SE = BBI->Succs.end(); + SI != SE; ++SI) + Worklist.insert(*SI); + for (BBInfoSetTy::iterator PI = BBI->Preds.begin(), PE = BBI->Preds.end(); + PI != PE; ++PI) + Worklist.insert(*PI); + } + + // Set preds/succs. + for (size_t WI = 0; WI < Worklist.size(); ++WI) { + BBInfo *BBI = Worklist[WI]; + MCBasicBlock *MCBB = BBI->BB; + if (!MCBB) + continue; + for (BBInfoSetTy::iterator SI = BBI->Succs.begin(), SE = BBI->Succs.end(); + SI != SE; ++SI) + MCBB->addSuccessor((*SI)->BB); + for (BBInfoSetTy::iterator PI = BBI->Preds.begin(), PE = BBI->Preds.end(); + PI != PE; ++PI) + MCBB->addPredecessor((*PI)->BB); + } + } +} diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index bafa002..bcf52d2 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -79,7 +79,8 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { // to using it in -static mode. SixteenByteConstantSection = 0; if (RelocM != Reloc::Static && - T.getArch() != Triple::x86_64 && T.getArch() != Triple::ppc64) + T.getArch() != Triple::x86_64 && T.getArch() != Triple::ppc64 && + T.getArch() != Triple::ppc64le) SixteenByteConstantSection = // .literal16 Ctx->getMachOSection("__TEXT", "__literal16", MCSectionMachO::S_16BYTE_LITERALS, @@ -145,12 +146,16 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { LSDASection = Ctx->getMachOSection("__TEXT", "__gcc_except_tab", 0, SectionKind::getReadOnlyWithRel()); - if (T.isMacOSX() && !T.isMacOSXVersionLT(10, 6)) + if (T.isMacOSX() && !T.isMacOSXVersionLT(10, 6)) { CompactUnwindSection = Ctx->getMachOSection("__LD", "__compact_unwind", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getReadOnly()); + if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86) + CompactUnwindDwarfEHFrameOnly = 0x04000000; + } + // Debug Information. DwarfAccelNamesSection = Ctx->getMachOSection("__DWARF", "__apple_names", @@ -223,9 +228,13 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { } void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { - // FIXME: Check this. Mips64el is using the base values, which is most likely - // incorrect. - if (T.getArch() != Triple::mips64el) + if (T.getArch() == Triple::mips || + T.getArch() == Triple::mipsel) + FDECFIEncoding = dwarf::DW_EH_PE_sdata4; + else if (T.getArch() == Triple::mips64 || + T.getArch() == Triple::mips64el) + FDECFIEncoding = dwarf::DW_EH_PE_sdata8; + else FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; if (T.getArch() == Triple::x86) { @@ -280,13 +289,29 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { FDEEncoding = dwarf::DW_EH_PE_udata4; TTypeEncoding = dwarf::DW_EH_PE_absptr; } - } else if (T.getArch() == Triple::ppc64) { + } else if (T.getArch() == Triple::ppc64 || T.getArch() == Triple::ppc64le) { PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; + } else if (T.getArch() == Triple::systemz) { + // All currently-defined code models guarantee that 4-byte PC-relative + // values will be in range. + if (RelocM == Reloc::PIC_) { + PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + dwarf::DW_EH_PE_sdata4; + LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + dwarf::DW_EH_PE_sdata4; + } else { + PersonalityEncoding = dwarf::DW_EH_PE_absptr; + LSDAEncoding = dwarf::DW_EH_PE_absptr; + FDEEncoding = dwarf::DW_EH_PE_absptr; + TTypeEncoding = dwarf::DW_EH_PE_absptr; + } } // Solaris requires different flags for .eh_frame to seemingly every other @@ -625,6 +650,8 @@ void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm, PersonalityEncoding = LSDAEncoding = FDEEncoding = FDECFIEncoding = TTypeEncoding = dwarf::DW_EH_PE_absptr; + CompactUnwindDwarfEHFrameOnly = 0; + EHFrameSection = 0; // Created on demand. CompactUnwindSection = 0; // Used only by selected targets. DwarfAccelNamesSection = 0; // Used only by selected targets. diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 0d2ce83..36a923a 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCObjectStreamer.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAssembler.h" @@ -17,6 +18,7 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSection.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -45,14 +47,15 @@ void MCObjectStreamer::reset() { if (Assembler) Assembler->reset(); CurSectionData = 0; + CurInsertionPoint = MCSectionData::iterator(); MCStreamer::reset(); } MCFragment *MCObjectStreamer::getCurrentFragment() const { assert(getCurrentSectionData() && "No current section!"); - if (!getCurrentSectionData()->empty()) - return &getCurrentSectionData()->getFragmentList().back(); + if (CurInsertionPoint != getCurrentSectionData()->getFragmentList().begin()) + return prior(CurInsertionPoint); return 0; } @@ -61,8 +64,10 @@ MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const { MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); // When bundling is enabled, we don't want to add data to a fragment that // already has instructions (see MCELFStreamer::EmitInstToData for details) - if (!F || (Assembler->isBundlingEnabled() && F->hasInstructions())) - F = new MCDataFragment(getCurrentSectionData()); + if (!F || (Assembler->isBundlingEnabled() && F->hasInstructions())) { + F = new MCDataFragment(); + insert(F); + } return F; } @@ -94,15 +99,15 @@ const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) { return Value; } -void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) { - assert(AddrSpace == 0 && "Address space must be 0!"); +void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size) { MCDataFragment *DF = getOrCreateDataFragment(); + MCLineEntry::Make(this, getCurrentSection().first); + // Avoid fixups when possible. int64_t AbsValue; if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue, getAssembler())) { - EmitIntValue(AbsValue, Size, AddrSpace); + EmitIntValue(AbsValue, Size); return; } DF->getFixups().push_back( @@ -145,7 +150,7 @@ void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { return; } Value = ForceExpAbs(Value); - new MCLEBFragment(*Value, false, getCurrentSectionData()); + insert(new MCLEBFragment(*Value, false)); } void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) { @@ -155,7 +160,7 @@ void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) { return; } Value = ForceExpAbs(Value); - new MCLEBFragment(*Value, true, getCurrentSectionData()); + insert(new MCLEBFragment(*Value, true)); } void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias, @@ -163,10 +168,20 @@ void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias, report_fatal_error("This file format doesn't support weak aliases."); } -void MCObjectStreamer::ChangeSection(const MCSection *Section) { +void MCObjectStreamer::ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); CurSectionData = &getAssembler().getOrCreateSectionData(*Section); + + int64_t IntSubsection = 0; + if (Subsection && + !Subsection->EvaluateAsAbsolute(IntSubsection, getAssembler())) + report_fatal_error("Cannot evaluate subsection number"); + if (IntSubsection < 0 || IntSubsection > 8192) + report_fatal_error("Subsection number out of range"); + CurInsertionPoint = + CurSectionData->getSubsectionInsertionPoint(unsigned(IntSubsection)); } void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { @@ -185,7 +200,7 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst) { // Now that a machine instruction has been assembled into this section, make // a line entry for any .loc directive that has been seen. - MCLineEntry::Make(this, getCurrentSection()); + MCLineEntry::Make(this, getCurrentSection().first); // If this instruction doesn't need relaxation, just emit it as data. MCAssembler &Assembler = getAssembler(); @@ -216,8 +231,8 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst) { void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) { // Always create a new, separate fragment here, because its size can change // during relaxation. - MCRelaxableFragment *IF = - new MCRelaxableFragment(Inst, getCurrentSectionData()); + MCRelaxableFragment *IF = new MCRelaxableFragment(Inst); + insert(IF); SmallString<128> Code; raw_svector_ostream VecOS(Code); @@ -227,7 +242,7 @@ void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) { } #ifndef NDEBUG -static const char *BundlingNotImplementedMsg = +static const char *const BundlingNotImplementedMsg = "Aligned bundling is not implemented for this object format"; #endif @@ -243,6 +258,19 @@ void MCObjectStreamer::EmitBundleUnlock() { llvm_unreachable(BundlingNotImplementedMsg); } +void MCObjectStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, + unsigned Discriminator, + StringRef FileName) { + // In case we see two .loc directives in a row, make sure the + // first one gets a line entry. + MCLineEntry::Make(this, getCurrentSection().first); + + this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, + Isa, Discriminator, FileName); +} + void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label, @@ -258,7 +286,7 @@ void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, return; } AddrDelta = ForceExpAbs(AddrDelta); - new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, getCurrentSectionData()); + insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta)); } void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, @@ -270,11 +298,10 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, return; } AddrDelta = ForceExpAbs(AddrDelta); - new MCDwarfCallFrameFragment(*AddrDelta, getCurrentSectionData()); + insert(new MCDwarfCallFrameFragment(*AddrDelta)); } -void MCObjectStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { - assert(AddrSpace == 0 && "Address space must be 0!"); +void MCObjectStreamer::EmitBytes(StringRef Data) { getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); } @@ -284,8 +311,7 @@ void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit) { if (MaxBytesToEmit == 0) MaxBytesToEmit = ByteAlignment; - new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, - getCurrentSectionData()); + insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit)); // Update the maximum alignment on the current section if necessary. if (ByteAlignment > getCurrentSectionData()->getAlignment()) @@ -302,7 +328,7 @@ bool MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset, unsigned char Value) { int64_t Res; if (Offset->EvaluateAsAbsolute(Res, getAssembler())) { - new MCOrgFragment(*Offset, Value, getCurrentSectionData()); + insert(new MCOrgFragment(*Offset, Value)); return false; } @@ -338,14 +364,17 @@ void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) { DF->getContents().resize(DF->getContents().size() + 8, 0); } -void MCObjectStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace) { - assert(AddrSpace == 0 && "Address space must be 0!"); +void MCObjectStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) { // FIXME: A MCFillFragment would be more memory efficient but MCExpr has // problems evaluating expressions across multiple fragments. getOrCreateDataFragment()->getContents().append(NumBytes, FillValue); } +void MCObjectStreamer::EmitZeros(uint64_t NumBytes) { + unsigned ItemSize = getCurrentSection().first->isVirtualSection() ? 0 : 1; + insert(new MCFillFragment(0, ItemSize, NumBytes)); +} + void MCObjectStreamer::FinishImpl() { // Dump out the dwarf file & directory tables and line tables. const MCSymbol *LineSectionSymbol = NULL; diff --git a/lib/MC/MCObjectSymbolizer.cpp b/lib/MC/MCObjectSymbolizer.cpp new file mode 100644 index 0000000..aa7648e --- /dev/null +++ b/lib/MC/MCObjectSymbolizer.cpp @@ -0,0 +1,214 @@ +//===-- lib/MC/MCObjectSymbolizer.cpp -------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCObjectSymbolizer.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCRelocationInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Object/MachO.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> + +using namespace llvm; +using namespace object; + +//===- MCMachObjectSymbolizer ---------------------------------------------===// + +namespace { +class MCMachObjectSymbolizer : public MCObjectSymbolizer { +public: + MCMachObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo, + const object::MachOObjectFile *MachOOF) + : MCObjectSymbolizer(Ctx, RelInfo, MachOOF) + {} + + void tryAddingPcLoadReferenceComment(raw_ostream &cStream, + int64_t Value, uint64_t Address) { + AddrToRelocMap::iterator RI = AddrToReloc.find(Address); + if (RI != AddrToReloc.end()) { + const MCExpr *RelExpr = RelInfo->createExprForRelocation(RI->second); + if (!RelExpr || RelExpr->EvaluateAsAbsolute(Value) == false) + return; + } + uint64_t Addr = Value; + SortedSectionList::const_iterator SI = findSectionContaining(Addr); + if (SI != SortedSections.end()) { + const SectionRef &S = *SI; + StringRef Name; S.getName(Name); + uint64_t SAddr; S.getAddress(SAddr); + if (Name == "__cstring") { + StringRef Contents; + S.getContents(Contents); + Contents = Contents.substr(Addr - SAddr); + cStream << " ## literal pool for: " + << Contents.substr(0, Contents.find_first_of(0)); + } + } + } +}; +} // End unnamed namespace + +//===- MCObjectSymbolizer -------------------------------------------------===// + +MCObjectSymbolizer::MCObjectSymbolizer(MCContext &Ctx, + OwningPtr<MCRelocationInfo> &RelInfo, + const ObjectFile *Obj) + : MCSymbolizer(Ctx, RelInfo), Obj(Obj), SortedSections(), AddrToReloc() { + error_code ec; + for (section_iterator SI = Obj->begin_sections(), + SE = Obj->end_sections(); + SI != SE; + SI.increment(ec)) { + if (ec) break; + + section_iterator RelSecI = SI->getRelocatedSection(); + if (RelSecI == Obj->end_sections()) + continue; + + uint64_t StartAddr; RelSecI->getAddress(StartAddr); + uint64_t Size; RelSecI->getSize(Size); + bool RequiredForExec; RelSecI->isRequiredForExecution(RequiredForExec); + if (RequiredForExec == false || Size == 0) + continue; + insertSection(*SI); + for (relocation_iterator RI = SI->begin_relocations(), + RE = SI->end_relocations(); + RI != RE; + RI.increment(ec)) { + if (ec) break; + // FIXME: libObject is inconsistent regarding error handling. The + // overwhelming majority of methods always return object_error::success, + // and assert for simple errors.. Here, ELFObjectFile::getRelocationOffset + // asserts when the file type isn't ET_REL. + // This workaround handles x86-64 elf, the only one that has a relocinfo. + uint64_t Offset; + if (Obj->isELF()) { + const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj); + if (ELFObj == 0) + break; + if (ELFObj->getElfHeader()->e_type == ELF::ET_REL) { + RI->getOffset(Offset); + Offset += StartAddr; + } else { + RI->getAddress(Offset); + } + } else { + RI->getOffset(Offset); + Offset += StartAddr; + } + // At a specific address, only keep the first relocation. + if (AddrToReloc.find(Offset) == AddrToReloc.end()) + AddrToReloc[Offset] = *RI; + } + } +} + +bool MCObjectSymbolizer:: +tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, + int64_t Value, uint64_t Address, bool IsBranch, + uint64_t Offset, uint64_t InstSize) { + AddrToRelocMap::iterator RI = AddrToReloc.find(Address + Offset); + if (RI != AddrToReloc.end()) { + if (const MCExpr *RelExpr = RelInfo->createExprForRelocation(RI->second)) { + MI.addOperand(MCOperand::CreateExpr(RelExpr)); + return true; + } + // Only try to create a symbol+offset expression if there is no relocation. + return false; + } + + // Interpret Value as a branch target. + if (IsBranch == false) + return false; + uint64_t UValue = Value; + // FIXME: map instead of looping each time? + error_code ec; + for (symbol_iterator SI = Obj->begin_symbols(), + SE = Obj->end_symbols(); + SI != SE; + SI.increment(ec)) { + if (ec) break; + uint64_t SymAddr; SI->getAddress(SymAddr); + uint64_t SymSize; SI->getSize(SymSize); + StringRef SymName; SI->getName(SymName); + SymbolRef::Type SymType; SI->getType(SymType); + if (SymAddr == UnknownAddressOrSize || SymSize == UnknownAddressOrSize + || SymName.empty() || SymType != SymbolRef::ST_Function) + continue; + + if ( SymAddr == UValue || + (SymAddr <= UValue && SymAddr + SymSize > UValue)) { + MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName); + const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx); + if (SymAddr != UValue) { + const MCExpr *Off = MCConstantExpr::Create(UValue - SymAddr, Ctx); + Expr = MCBinaryExpr::CreateAdd(Expr, Off, Ctx); + } + MI.addOperand(MCOperand::CreateExpr(Expr)); + return true; + } + } + return false; +} + +void MCObjectSymbolizer:: +tryAddingPcLoadReferenceComment(raw_ostream &cStream, + int64_t Value, uint64_t Address) { +} + +MCObjectSymbolizer * +MCObjectSymbolizer::createObjectSymbolizer(MCContext &Ctx, + OwningPtr<MCRelocationInfo> &RelInfo, + const ObjectFile *Obj) { + if (const MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(Obj)) { + return new MCMachObjectSymbolizer(Ctx, RelInfo, MachOOF); + } + return new MCObjectSymbolizer(Ctx, RelInfo, Obj); +} + +// SortedSections implementation. + +static bool SectionStartsBefore(const SectionRef &S, uint64_t Addr) { + uint64_t SAddr; S.getAddress(SAddr); + return SAddr < Addr; +} + +MCObjectSymbolizer::SortedSectionList::const_iterator +MCObjectSymbolizer::findSectionContaining(uint64_t Addr) const { + SortedSectionList::const_iterator + EndIt = SortedSections.end(), + It = std::lower_bound(SortedSections.begin(), EndIt, + Addr, SectionStartsBefore); + if (It == EndIt) + return It; + uint64_t SAddr; It->getAddress(SAddr); + uint64_t SSize; It->getSize(SSize); + if (Addr >= SAddr + SSize) + return EndIt; + return It; +} + +void MCObjectSymbolizer::insertSection(SectionRef Sec) { + uint64_t SAddr; Sec.getAddress(SAddr); + uint64_t SSize; Sec.getSize(SSize); + SortedSectionList::iterator It = std::lower_bound(SortedSections.begin(), + SortedSections.end(), + SAddr, + SectionStartsBefore); + if (It != SortedSections.end()) { + uint64_t FoundSAddr; It->getAddress(FoundSAddr); + if (FoundSAddr < SAddr + SSize) + llvm_unreachable("Inserting overlapping sections"); + } + SortedSections.insert(It, Sec); +} diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 9d52377..dd0d181 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -149,6 +149,9 @@ private: /// ActiveMacros - Stack of active macro instantiations. std::vector<MacroInstantiation*> ActiveMacros; + /// MacroLikeBodies - List of bodies of anonymous macros. + std::deque<MCAsmMacro> MacroLikeBodies; + /// Boolean tracking whether macro substitution is enabled. unsigned MacrosEnabledFlag : 1; @@ -160,6 +163,13 @@ private: int64_t CppHashLineNumber; SMLoc CppHashLoc; int CppHashBuf; + /// When generating dwarf for assembly source files we need to calculate the + /// logical line number based on the last parsed cpp hash file line comment + /// and current line. Since this is slow and messes up the SourceMgr's + /// cache we save the last info we queried with SrcMgr.FindLineNumber(). + SMLoc LastQueryIDLoc; + int LastQueryBuffer; + unsigned LastQueryLine; /// AssemblerDialect. ~OU means unset value and use value provided by MAI. unsigned AssemblerDialect; @@ -201,9 +211,9 @@ public: } virtual bool Warning(SMLoc L, const Twine &Msg, - ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()); + ArrayRef<SMRange> Ranges = None); virtual bool Error(SMLoc L, const Twine &Msg, - ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()); + ArrayRef<SMRange> Ranges = None); virtual const AsmToken &Lex(); @@ -221,6 +231,7 @@ public: bool parseExpression(const MCExpr *&Res); virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc); + virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc); virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc); virtual bool parseAbsoluteExpression(int64_t &Res); @@ -285,7 +296,7 @@ private: void PrintMacroInstantiations(); void PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, - ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) const { + ArrayRef<SMRange> Ranges = None) const { SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges); } static void DiagHandler(const SMDiagnostic &Diag, void *Context); @@ -544,7 +555,7 @@ bool AsmParser::EnterIncludeFile(const std::string &Filename) { return false; } -/// Process the specified .incbin file by seaching for it in the include paths +/// Process the specified .incbin file by searching for it in the include paths /// then just emitting the byte contents of the file to the streamer. This /// returns true on failure. bool AsmParser::ProcessIncbinFile(const std::string &Filename) { @@ -554,8 +565,7 @@ bool AsmParser::ProcessIncbinFile(const std::string &Filename) { return true; // Pick up the bytes from the file and emit them. - getStreamer().EmitBytes(SrcMgr.getMemoryBuffer(NewBuf)->getBuffer(), - DEFAULT_ADDRSPACE); + getStreamer().EmitBytes(SrcMgr.getMemoryBuffer(NewBuf)->getBuffer()); return false; } @@ -601,7 +611,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // If we are generating dwarf for assembly source files save the initial text // section and generate a .file directive. if (getContext().getGenDwarfForAssembly()) { - getContext().setGenDwarfSection(getStreamer().getCurrentSection()); + getContext().setGenDwarfSection(getStreamer().getCurrentSection().first); MCSymbol *SectionStartSym = getContext().CreateTempSymbol(); getStreamer().EmitLabel(SectionStartSym); getContext().setGenDwarfSectionStartSym(SectionStartSym); @@ -666,7 +676,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { } void AsmParser::checkForValidSection() { - if (!ParsingInlineAsm && !getStreamer().getCurrentSection()) { + if (!ParsingInlineAsm && !getStreamer().getCurrentSection().first) { TokError("expected section directive before assembly directive"); Out.InitToTextSection(); } @@ -804,11 +814,21 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { // Look for 'b' or 'f' following an Integer as a directional label if (Lexer.getKind() == AsmToken::Identifier) { StringRef IDVal = getTok().getString(); + // Lookup the symbol variant if used. + std::pair<StringRef, StringRef> Split = IDVal.split('@'); + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + if (Split.first.size() != IDVal.size()) { + Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); + if (Variant == MCSymbolRefExpr::VK_Invalid) { + Variant = MCSymbolRefExpr::VK_None; + return TokError("invalid variant '" + Split.second + "'"); + } + IDVal = Split.first; + } if (IDVal == "f" || IDVal == "b"){ MCSymbol *Sym = Ctx.GetDirectionalLocalSymbol(IntVal, IDVal == "f" ? 1 : 0); - Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, - getContext()); + Res = MCSymbolRefExpr::Create(Sym, Variant, getContext()); if (IDVal == "b" && Sym->isUndefined()) return Error(Loc, "invalid reference to undefined symbol"); EndLoc = Lexer.getTok().getEndLoc(); @@ -869,6 +889,10 @@ bool AsmParser::parseExpression(const MCExpr *&Res) { return parseExpression(Res, EndLoc); } +bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { + return ParsePrimaryExpr(Res, EndLoc); +} + const MCExpr * AsmParser::ApplyModifierToExpr(const MCExpr *E, MCSymbolRefExpr::VariantKind Variant) { @@ -1087,7 +1111,7 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, MCBinaryExpr::Opcode Dummy; unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); if (TokPrec < NextTokPrec) { - if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true; + if (ParseBinOpRHS(TokPrec+1, RHS, EndLoc)) return true; } // Merge LHS and RHS according to operator. @@ -1306,11 +1330,11 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { case DK_DOUBLE: return ParseDirectiveRealValue(APFloat::IEEEdouble); case DK_ALIGN: { - bool IsPow2 = !getContext().getAsmInfo().getAlignmentIsInBytes(); + bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes(); return ParseDirectiveAlign(IsPow2, /*ExprSize=*/1); } case DK_ALIGN32: { - bool IsPow2 = !getContext().getAsmInfo().getAlignmentIsInBytes(); + bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes(); return ParseDirectiveAlign(IsPow2, /*ExprSize=*/4); } case DK_BALIGN: @@ -1488,7 +1512,8 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { // section is the initial text section then generate a .loc directive for // the instruction. if (!HadError && getContext().getGenDwarfForAssembly() && - getContext().getGenDwarfSection() == getStreamer().getCurrentSection()) { + getContext().getGenDwarfSection() == + getStreamer().getCurrentSection().first) { unsigned Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); @@ -1503,7 +1528,18 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { getStreamer().EmitDwarfFileDirective( getContext().nextGenDwarfFileNumber(), StringRef(), CppHashFilename); - unsigned CppHashLocLineNo = SrcMgr.FindLineNumber(CppHashLoc,CppHashBuf); + // Since SrcMgr.FindLineNumber() is slow and messes up the SourceMgr's + // cache with the different Loc from the call above we save the last + // info we queried here with SrcMgr.FindLineNumber(). + unsigned CppHashLocLineNo; + if (LastQueryIDLoc == CppHashLoc && LastQueryBuffer == CppHashBuf) + CppHashLocLineNo = LastQueryLine; + else { + CppHashLocLineNo = SrcMgr.FindLineNumber(CppHashLoc, CppHashBuf); + LastQueryLine = CppHashLocLineNo; + LastQueryIDLoc = CppHashLoc; + LastQueryBuffer = CppHashBuf; + } Line = CppHashLineNumber - 1 + (Line - CppHashLocLineNo); } @@ -1978,7 +2014,6 @@ static bool IsUsedIn(const MCSymbol *Sym, const MCExpr *Value) { case MCExpr::Binary: { const MCBinaryExpr *BE = static_cast<const MCBinaryExpr*>(Value); return IsUsedIn(Sym, BE->getLHS()) || IsUsedIn(Sym, BE->getRHS()); - break; } case MCExpr::Target: case MCExpr::Constant: @@ -2187,9 +2222,9 @@ bool AsmParser::ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { if (parseEscapedString(Data)) return true; - getStreamer().EmitBytes(Data, DEFAULT_ADDRSPACE); + getStreamer().EmitBytes(Data); if (ZeroTerminated) - getStreamer().EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE); + getStreamer().EmitBytes(StringRef("\0", 1)); Lex(); @@ -2224,9 +2259,9 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) { uint64_t IntValue = MCE->getValue(); if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) return Error(ExprLoc, "literal value out of range for directive"); - getStreamer().EmitIntValue(IntValue, Size, DEFAULT_ADDRSPACE); + getStreamer().EmitIntValue(IntValue, Size); } else - getStreamer().EmitValue(Value, Size, DEFAULT_ADDRSPACE); + getStreamer().EmitValue(Value, Size); if (getLexer().is(AsmToken::EndOfStatement)) break; @@ -2285,7 +2320,7 @@ bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) { // Emit the value as an integer. APInt AsInt = Value.bitcastToAPInt(); getStreamer().EmitIntValue(AsInt.getLimitedValue(), - AsInt.getBitWidth() / 8, DEFAULT_ADDRSPACE); + AsInt.getBitWidth() / 8); if (getLexer().is(AsmToken::EndOfStatement)) break; @@ -2321,7 +2356,7 @@ bool AsmParser::ParseDirectiveZero() { Lex(); - getStreamer().EmitFill(NumBytes, Val, DEFAULT_ADDRSPACE); + getStreamer().EmitFill(NumBytes, Val); return false; } @@ -2360,7 +2395,7 @@ bool AsmParser::ParseDirectiveFill() { return TokError("invalid '.fill' size, expected 1, 2, 4, or 8"); for (uint64_t i = 0, e = NumValues; i != e; ++i) - getStreamer().EmitIntValue(FillExpr, FillSize, DEFAULT_ADDRSPACE); + getStreamer().EmitIntValue(FillExpr, FillSize); return false; } @@ -2479,7 +2514,7 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { // Check whether we should use optimal code alignment for this .align // directive. - bool UseCodeAlign = getStreamer().getCurrentSection()->UseCodeAlign(); + bool UseCodeAlign = getStreamer().getCurrentSection().first->UseCodeAlign(); if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) && ValueSize == 1 && UseCodeAlign) { getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill); @@ -2631,12 +2666,10 @@ bool AsmParser::ParseDirectiveLoc() { Flags |= DWARF2_FLAG_IS_STMT; else return Error(Loc, "is_stmt value not 0 or 1"); - } - else { + } else { return Error(Loc, "is_stmt value not the constant value of 0 or 1"); } - } - else if (Name == "isa") { + } else if (Name == "isa") { Loc = getTok().getLoc(); const MCExpr *Value; if (parseExpression(Value)) @@ -2647,16 +2680,13 @@ bool AsmParser::ParseDirectiveLoc() { if (Value < 0) return Error(Loc, "isa number less than zero"); Isa = Value; - } - else { + } else { return Error(Loc, "isa number not a constant value"); } - } - else if (Name == "discriminator") { + } else if (Name == "discriminator") { if (parseAbsoluteExpression(Discriminator)) return true; - } - else { + } else { return Error(Loc, "unknown sub-directive in '.loc' directive"); } @@ -2730,7 +2760,7 @@ bool AsmParser::ParseRegisterOrRegisterNumber(int64_t &Register, if (getLexer().isNot(AsmToken::Integer)) { if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc)) return true; - Register = getContext().getRegisterInfo().getDwarfRegNum(RegNo, true); + Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true); } else return parseAbsoluteExpression(Register); @@ -3303,7 +3333,7 @@ bool AsmParser::ParseDirectiveSpace(StringRef IDVal) { Twine(IDVal) + "' directive"); // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. - getStreamer().EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE); + getStreamer().EmitFill(NumBytes, FillExpr); return false; } @@ -3615,18 +3645,17 @@ bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { if (TheCondState.TheCond != AsmCond::IfCond && TheCondState.TheCond != AsmCond::ElseIfCond) - Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or " - " an .elseif"); + Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or " + " an .elseif"); TheCondState.TheCond = AsmCond::ElseIfCond; bool LastIgnoreState = false; if (!TheCondStack.empty()) - LastIgnoreState = TheCondStack.back().Ignore; + LastIgnoreState = TheCondStack.back().Ignore; if (LastIgnoreState || TheCondState.CondMet) { TheCondState.Ignore = true; eatToEndOfStatement(); - } - else { + } else { int64_t ExprValue; if (parseAbsoluteExpression(ExprValue)) return true; @@ -3652,8 +3681,8 @@ bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { if (TheCondState.TheCond != AsmCond::IfCond && TheCondState.TheCond != AsmCond::ElseIfCond) - Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an " - ".elseif"); + Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an " + ".elseif"); TheCondState.TheCond = AsmCond::ElseCond; bool LastIgnoreState = false; if (!TheCondStack.empty()) @@ -3832,7 +3861,8 @@ MCAsmMacro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) { // We Are Anonymous. StringRef Name; MCAsmMacroParameters Parameters; - return new MCAsmMacro(Name, Body, Parameters); + MacroLikeBodies.push_back(MCAsmMacro(Name, Body, Parameters)); + return &MacroLikeBodies.back(); } void AsmParser::InstantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, @@ -4046,19 +4076,17 @@ static int RewritesSort(const void *A, const void *B) { if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer()) return 1; - // It's possible to have a SizeDirective rewrite and an Input/Output rewrite - // to the same location. Make sure the SizeDirective rewrite is performed - // first. This also ensure the sort algorithm is stable. - if (AsmRewriteA->Kind == AOK_SizeDirective) { - assert ((AsmRewriteB->Kind == AOK_Input || AsmRewriteB->Kind == AOK_Output) && - "Expected an Input/Output rewrite!"); + // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output + // rewrite to the same location. Make sure the SizeDirective rewrite is + // performed first, then the Imm/ImmPrefix and finally the Input/Output. This + // ensures the sort algorithm is stable. + if (AsmRewritePrecedence [AsmRewriteA->Kind] > + AsmRewritePrecedence [AsmRewriteB->Kind]) return -1; - } - if (AsmRewriteB->Kind == AOK_SizeDirective) { - assert ((AsmRewriteA->Kind == AOK_Input || AsmRewriteA->Kind == AOK_Output) && - "Expected an Input/Output rewrite!"); + + if (AsmRewritePrecedence [AsmRewriteA->Kind] < + AsmRewritePrecedence [AsmRewriteB->Kind]) return 1; - } llvm_unreachable ("Unstable rewrite sort."); } @@ -4105,12 +4133,8 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString, MCParsedAsmOperand *Operand = Info.ParsedOperands[i]; // Immediate. - if (Operand->isImm()) { - if (Operand->needAsmRewrite()) - AsmStrRewrites.push_back(AsmRewrite(AOK_ImmPrefix, - Operand->getStartLoc())); + if (Operand->isImm()) continue; - } // Register operand. if (Operand->isReg() && !Operand->needAddressOf()) { @@ -4122,33 +4146,27 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString, } // Expr/Input or Output. - bool IsVarDecl; - unsigned Length, Size, Type; - void *OpDecl = SI.LookupInlineAsmIdentifier(Operand->getName(), AsmLoc, - Length, Size, Type, - IsVarDecl); + StringRef SymName = Operand->getSymName(); + if (SymName.empty()) + continue; + + void *OpDecl = Operand->getOpDecl(); if (!OpDecl) continue; bool isOutput = (i == 1) && Desc.mayStore(); - if (Operand->isMem() && Operand->needSizeDirective()) - AsmStrRewrites.push_back(AsmRewrite(AOK_SizeDirective, - Operand->getStartLoc(), /*Len*/0, - Operand->getMemSize())); - + SMLoc Start = SMLoc::getFromPointer(SymName.data()); if (isOutput) { ++InputIdx; OutputDecls.push_back(OpDecl); OutputDeclsAddressOf.push_back(Operand->needAddressOf()); OutputConstraints.push_back('=' + Operand->getConstraint().str()); - AsmStrRewrites.push_back(AsmRewrite(AOK_Output, Operand->getStartLoc(), - Operand->getNameLen())); + AsmStrRewrites.push_back(AsmRewrite(AOK_Output, Start, SymName.size())); } else { InputDecls.push_back(OpDecl); InputDeclsAddressOf.push_back(Operand->needAddressOf()); InputConstraints.push_back(Operand->getConstraint().str()); - AsmStrRewrites.push_back(AsmRewrite(AOK_Input, Operand->getStartLoc(), - Operand->getNameLen())); + AsmStrRewrites.push_back(AsmRewrite(AOK_Input, Start, SymName.size())); } } } @@ -4184,31 +4202,32 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString, // Build the IR assembly string. std::string AsmStringIR; - AsmRewriteKind PrevKind = AOK_Imm; raw_string_ostream OS(AsmStringIR); - const char *Start = SrcMgr.getMemoryBuffer(0)->getBufferStart(); + const char *AsmStart = SrcMgr.getMemoryBuffer(0)->getBufferStart(); + const char *AsmEnd = SrcMgr.getMemoryBuffer(0)->getBufferEnd(); array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), RewritesSort); for (SmallVectorImpl<AsmRewrite>::iterator I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) { - const char *Loc = (*I).Loc.getPointer(); - assert(Loc >= Start && "Expected Loc to be after Start!"); - - unsigned AdditionalSkip = 0; AsmRewriteKind Kind = (*I).Kind; + if (Kind == AOK_Delete) + continue; - // Emit everything up to the immediate/expression. If the previous rewrite - // was a size directive, then this has already been done. - if (PrevKind != AOK_SizeDirective) - OS << StringRef(Start, Loc - Start); - PrevKind = Kind; + const char *Loc = (*I).Loc.getPointer(); + assert(Loc >= AsmStart && "Expected Loc to be at or after Start!"); + + // Emit everything up to the immediate/expression. + unsigned Len = Loc - AsmStart; + if (Len) + OS << StringRef(AsmStart, Len); // Skip the original expression. if (Kind == AOK_Skip) { - Start = Loc + (*I).Len; + AsmStart = Loc + (*I).Len; continue; } + unsigned AdditionalSkip = 0; // Rewrite expressions in $N notation. switch (Kind) { default: break; @@ -4254,14 +4273,12 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString, } // Skip the original expression. - if (Kind != AOK_SizeDirective) - Start = Loc + (*I).Len + AdditionalSkip; + AsmStart = Loc + (*I).Len + AdditionalSkip; } // Emit the remainder of the asm string. - const char *AsmEnd = SrcMgr.getMemoryBuffer(0)->getBufferEnd(); - if (Start != AsmEnd) - OS << StringRef(Start, AsmEnd - Start); + if (AsmStart != AsmEnd) + OS << StringRef(AsmStart, AsmEnd - AsmStart); AsmString = OS.str(); return false; diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index a50eab2..df1794c 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -35,6 +35,9 @@ class COFFAsmParser : public MCAsmParserExtension { unsigned Characteristics, SectionKind Kind); + bool ParseSectionName(StringRef &SectionName); + bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags); + virtual void Initialize(MCAsmParser &Parser) { // Call the base implementation. MCAsmParserExtension::Initialize(Parser); @@ -42,11 +45,13 @@ class COFFAsmParser : public MCAsmParserExtension { addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text"); addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce"); // Win64 EH directives. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>( @@ -100,11 +105,13 @@ class COFFAsmParser : public MCAsmParserExtension { SectionKind::getBSS()); } + bool ParseDirectiveSection(StringRef, SMLoc); bool ParseDirectiveDef(StringRef, SMLoc); bool ParseDirectiveScl(StringRef, SMLoc); bool ParseDirectiveType(StringRef, SMLoc); bool ParseDirectiveEndef(StringRef, SMLoc); bool ParseDirectiveSecRel32(StringRef, SMLoc); + bool ParseDirectiveLinkOnce(StringRef, SMLoc); // Win64 EH directives. bool ParseSEHDirectiveStartProc(StringRef, SMLoc); @@ -130,6 +137,119 @@ public: } // end annonomous namespace. +static SectionKind computeSectionKind(unsigned Flags) { + if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) + return SectionKind::getText(); + if (Flags & COFF::IMAGE_SCN_MEM_READ && + (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) + return SectionKind::getReadOnly(); + return SectionKind::getDataRel(); +} + +bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) { + enum { + None = 0, + Alloc = 1 << 0, + Code = 1 << 1, + Load = 1 << 2, + InitData = 1 << 3, + Shared = 1 << 4, + NoLoad = 1 << 5, + NoRead = 1 << 6, + NoWrite = 1 << 7 + }; + + bool ReadOnlyRemoved = false; + unsigned SecFlags = None; + + for (unsigned i = 0; i < FlagsString.size(); ++i) { + switch (FlagsString[i]) { + case 'a': + // Ignored. + break; + + case 'b': // bss section + SecFlags |= Alloc; + if (SecFlags & InitData) + return TokError("conflicting section flags 'b' and 'd'."); + SecFlags &= ~Load; + break; + + case 'd': // data section + SecFlags |= InitData; + if (SecFlags & Alloc) + return TokError("conflicting section flags 'b' and 'd'."); + SecFlags &= ~NoWrite; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + break; + + case 'n': // section is not loaded + SecFlags |= NoLoad; + SecFlags &= ~Load; + break; + + case 'r': // read-only + ReadOnlyRemoved = false; + SecFlags |= NoWrite; + if ((SecFlags & Code) == 0) + SecFlags |= InitData; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + break; + + case 's': // shared section + SecFlags |= Shared | InitData; + SecFlags &= ~NoWrite; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + break; + + case 'w': // writable + SecFlags &= ~NoWrite; + ReadOnlyRemoved = true; + break; + + case 'x': // executable section + SecFlags |= Code; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + if (!ReadOnlyRemoved) + SecFlags |= NoWrite; + break; + + case 'y': // not readable + SecFlags |= NoRead | NoWrite; + break; + + default: + return TokError("unknown flag"); + } + } + + *Flags = 0; + + if (SecFlags == None) + SecFlags = InitData; + + if (SecFlags & Code) + *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE; + if (SecFlags & InitData) + *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; + if ((SecFlags & Alloc) && (SecFlags & Load) == 0) + *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; + if (SecFlags & NoLoad) + *Flags |= COFF::IMAGE_SCN_LNK_REMOVE; + if ((SecFlags & NoRead) == 0) + *Flags |= COFF::IMAGE_SCN_MEM_READ; + if ((SecFlags & NoWrite) == 0) + *Flags |= COFF::IMAGE_SCN_MEM_WRITE; + if (SecFlags & Shared) + *Flags |= COFF::IMAGE_SCN_MEM_SHARED; + + return false; +} + /// ParseDirectiveSymbolAttribute /// ::= { ".weak", ... } [ identifier ( , identifier )* ] bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { @@ -174,6 +294,60 @@ bool COFFAsmParser::ParseSectionSwitch(StringRef Section, return false; } +bool COFFAsmParser::ParseSectionName(StringRef &SectionName) { + if (!getLexer().is(AsmToken::Identifier)) + return true; + + SectionName = getTok().getIdentifier(); + Lex(); + return false; +} + +// .section name [, "flags"] +// +// Supported flags: +// a: Ignored. +// b: BSS section (uninitialized data) +// d: data section (initialized data) +// n: Discardable section +// r: Readable section +// s: Shared section +// w: Writable section +// x: Executable section +// y: Not-readable section (clears 'r') +// +// Subsections are not supported. +bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { + StringRef SectionName; + + if (ParseSectionName(SectionName)) + return TokError("expected identifier in directive"); + + unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE; + + if (getLexer().is(AsmToken::Comma)) { + Lex(); + + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in directive"); + + StringRef FlagsStr = getTok().getStringContents(); + Lex(); + + if (ParseSectionFlags(FlagsStr, &Flags)) + return true; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + SectionKind Kind = computeSectionKind(Flags); + ParseSectionSwitch(SectionName, Flags, Kind); + return false; +} + bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) { StringRef SymbolName; @@ -235,6 +409,64 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { return false; } +/// ParseDirectiveLinkOnce +/// ::= .linkonce [ identifier [ identifier ] ] +bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { + COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; + + if (getLexer().is(AsmToken::Identifier)) { + StringRef TypeId = getTok().getIdentifier(); + + Type = StringSwitch<COFF::COMDATType>(TypeId) + .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) + .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY) + .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE) + .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH) + .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) + .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST) + .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST) + .Default((COFF::COMDATType)0); + + if (Type == 0) + return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'")); + + Lex(); + } + + const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>( + getStreamer().getCurrentSection().first); + + const MCSectionCOFF *Assoc = 0; + if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { + StringRef AssocName; + SMLoc Loc = getTok().getLoc(); + if (ParseSectionName(AssocName)) + return TokError("expected associated section name"); + + Assoc = static_cast<const MCSectionCOFF*>( + getContext().getCOFFSection(AssocName)); + if (!Assoc) + return Error(Loc, "cannot associate unknown section '" + AssocName + "'"); + if (Assoc == Current) + return Error(Loc, "cannot associate a section with itself"); + if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)) + return Error(Loc, "associated section must be a COMDAT section"); + if (Assoc->getSelection() == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) + return Error(Loc, "associated section cannot be itself associative"); + } + + if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) + return Error(Loc, Twine("section '") + Current->getSectionName() + + "' is already linkonce"); + + Current->setSelection(Type, Assoc); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + return false; +} + bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { StringRef SymbolID; if (getParser().parseIdentifier(SymbolID)) @@ -453,7 +685,7 @@ bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) { SMLoc startLoc = getLexer().getLoc(); if (getLexer().is(AsmToken::Percent)) { - const MCRegisterInfo &MRI = getContext().getRegisterInfo(); + const MCRegisterInfo *MRI = getContext().getRegisterInfo(); SMLoc endLoc; unsigned LLVMRegNo; if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc)) @@ -473,7 +705,7 @@ bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) { return Error(startLoc, "expected non-volatile register"); #endif - int SEHRegNo = MRI.getSEHRegNum(LLVMRegNo); + int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo); if (SEHRegNo < 0) return Error(startLoc,"register can't be represented in SEH unwind info"); RegNo = SEHRegNo; diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp index 6d6409f..0aeeaf6 100644 --- a/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/lib/MC/MCParser/DarwinAsmParser.cpp @@ -566,10 +566,10 @@ bool DarwinAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { /// ParseDirectivePrevious: /// ::= .previous bool DarwinAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { - const MCSection *PreviousSection = getStreamer().getPreviousSection(); - if (PreviousSection == NULL) + MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); + if (PreviousSection.first == NULL) return TokError(".previous without corresponding .section"); - getStreamer().SwitchSection(PreviousSection); + getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); return false; } @@ -593,7 +593,7 @@ bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { raw_ostream *OS = getContext().getSecureLog(); if (OS == NULL) { std::string Err; - OS = new raw_fd_ostream(SecureLogFile, Err, raw_fd_ostream::F_Append); + OS = new raw_fd_ostream(SecureLogFile, Err, sys::fs::F_Append); if (!Err.empty()) { delete OS; return Error(IDLoc, Twine("can't open secure log file: ") + diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 4c45e08..3134fc3 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -76,6 +76,7 @@ public: &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal"); addDirectiveHandler< &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection"); } // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is @@ -147,9 +148,11 @@ public: bool ParseDirectiveVersion(StringRef, SMLoc); bool ParseDirectiveWeakref(StringRef, SMLoc); bool ParseDirectiveSymbolAttribute(StringRef, SMLoc); + bool ParseDirectiveSubsection(StringRef, SMLoc); private: bool ParseSectionName(StringRef &SectionName); + bool ParseSectionArguments(bool IsPush); }; } @@ -191,12 +194,15 @@ bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags, SectionKind Kind) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in section switching directive"); - Lex(); + const MCExpr *Subsection = 0; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getParser().parseExpression(Subsection)) + return true; + } getStreamer().SwitchSection(getContext().getELFSection( - Section, Type, Flags, Kind)); + Section, Type, Flags, Kind), + Subsection); return false; } @@ -316,7 +322,7 @@ static int parseSectionFlags(StringRef flagsStr) { bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { getStreamer().PushSection(); - if (ParseDirectiveSection(s, loc)) { + if (ParseSectionArguments(/*IsPush=*/true)) { getStreamer().PopSection(); return true; } @@ -332,6 +338,10 @@ bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { // FIXME: This is a work in progress. bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { + return ParseSectionArguments(/*IsPush=*/false); +} + +bool ELFAsmParser::ParseSectionArguments(bool IsPush) { StringRef SectionName; if (ParseSectionName(SectionName)) @@ -341,6 +351,7 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { int64_t Size = 0; StringRef GroupName; unsigned Flags = 0; + const MCExpr *Subsection = 0; // Set the defaults first. if (SectionName == ".fini" || SectionName == ".init" || @@ -352,6 +363,14 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { if (getLexer().is(AsmToken::Comma)) { Lex(); + if (IsPush && getLexer().isNot(AsmToken::String)) { + if (getParser().parseExpression(Subsection)) + return true; + if (getLexer().isNot(AsmToken::Comma)) + goto EndStmt; + Lex(); + } + if (getLexer().isNot(AsmToken::String)) return TokError("expected string in directive"); @@ -408,6 +427,7 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { } } +EndStmt: if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); @@ -444,15 +464,16 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { SectionKind Kind = computeSectionKind(Flags); getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, Flags, Kind, Size, - GroupName)); + GroupName), + Subsection); return false; } bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { - const MCSection *PreviousSection = getStreamer().getPreviousSection(); - if (PreviousSection == NULL) + MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); + if (PreviousSection.first == NULL) return TokError(".previous without corresponding .section"); - getStreamer().SwitchSection(PreviousSection); + getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); return false; } @@ -613,6 +634,20 @@ bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { return false; } +bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) { + const MCExpr *Subsection = 0; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getParser().parseExpression(Subsection)) + return true; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + getStreamer().SubSection(Subsection); + return false; +} + namespace llvm { MCAsmParserExtension *createELFAsmParser() { diff --git a/lib/MC/MCPureStreamer.cpp b/lib/MC/MCPureStreamer.cpp index 0e04c55..c5c3bb7 100644 --- a/lib/MC/MCPureStreamer.cpp +++ b/lib/MC/MCPureStreamer.cpp @@ -12,9 +12,8 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectStreamer.h" -// FIXME: Remove this. -#include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/ErrorHandling.h" @@ -41,7 +40,7 @@ public: virtual void EmitDebugLabel(MCSymbol *Symbol); virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, uint64_t Size = 0, unsigned ByteAlignment = 0); - virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + virtual void EmitBytes(StringRef Data); virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, unsigned MaxBytesToEmit = 0); @@ -113,25 +112,22 @@ void MCPureStreamer::InitSections() { } void MCPureStreamer::InitToTextSection() { - // FIMXE: To what!? - SwitchSection(getContext().getMachOSection("__TEXT", "__text", - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - 0, SectionKind::getText())); + SwitchSection(getContext().getObjectFileInfo()->getTextSection()); } void MCPureStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection() && "Cannot emit before setting section!"); + assert(getCurrentSection().first && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection()); + Symbol->setSection(*getCurrentSection().first); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); // We have to create a new fragment if this is an atom defining symbol, // fragments cannot span atoms. if (getAssembler().isSymbolLinkerVisible(SD.getSymbol())) - new MCDataFragment(getCurrentSectionData()); + insert(new MCDataFragment()); // FIXME: This is wasteful, we don't necessarily need to create a data // fragment. Instead, we should mark the symbol as pointing into the data @@ -153,7 +149,7 @@ void MCPureStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, report_fatal_error("not yet implemented in pure streamer"); } -void MCPureStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { +void MCPureStreamer::EmitBytes(StringRef Data) { // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into // MCObjectStreamer. getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); @@ -166,8 +162,7 @@ void MCPureStreamer::EmitValueToAlignment(unsigned ByteAlignment, // MCObjectStreamer. if (MaxBytesToEmit == 0) MaxBytesToEmit = ByteAlignment; - new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, - getCurrentSectionData()); + insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit)); // Update the maximum alignment on the current section if necessary. if (ByteAlignment > getCurrentSectionData()->getAlignment()) @@ -180,8 +175,8 @@ void MCPureStreamer::EmitCodeAlignment(unsigned ByteAlignment, // MCObjectStreamer. if (MaxBytesToEmit == 0) MaxBytesToEmit = ByteAlignment; - MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit, - getCurrentSectionData()); + MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit); + insert(F); F->setEmitNops(true); // Update the maximum alignment on the current section if necessary. @@ -191,13 +186,13 @@ void MCPureStreamer::EmitCodeAlignment(unsigned ByteAlignment, bool MCPureStreamer::EmitValueToOffset(const MCExpr *Offset, unsigned char Value) { - new MCOrgFragment(*Offset, Value, getCurrentSectionData()); + insert(new MCOrgFragment(*Offset, Value)); return false; } void MCPureStreamer::EmitInstToFragment(const MCInst &Inst) { - MCRelaxableFragment *IF = - new MCRelaxableFragment(Inst, getCurrentSectionData()); + MCRelaxableFragment *IF = new MCRelaxableFragment(Inst); + insert(IF); // Add the fixups and data. // diff --git a/lib/MC/MCRegisterInfo.cpp b/lib/MC/MCRegisterInfo.cpp index 5c71106..ce79cd5 100644 --- a/lib/MC/MCRegisterInfo.cpp +++ b/lib/MC/MCRegisterInfo.cpp @@ -46,6 +46,18 @@ unsigned MCRegisterInfo::getSubRegIndex(unsigned Reg, unsigned SubReg) const { return 0; } +unsigned MCRegisterInfo::getSubRegIdxSize(unsigned Idx) const { + assert(Idx && Idx < getNumSubRegIndices() && + "This is not a subregister index"); + return SubRegIdxRanges[Idx].Size; +} + +unsigned MCRegisterInfo::getSubRegIdxOffset(unsigned Idx) const { + assert(Idx && Idx < getNumSubRegIndices() && + "This is not a subregister index"); + return SubRegIdxRanges[Idx].Offset; +} + int MCRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs; unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize; diff --git a/lib/MC/MCRelocationInfo.cpp b/lib/MC/MCRelocationInfo.cpp new file mode 100644 index 0000000..53c48de --- /dev/null +++ b/lib/MC/MCRelocationInfo.cpp @@ -0,0 +1,39 @@ +//==-- lib/MC/MCRelocationInfo.cpp -------------------------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCRelocationInfo.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm-c/Disassembler.h" + +using namespace llvm; + +MCRelocationInfo::MCRelocationInfo(MCContext &Ctx) + : Ctx(Ctx) { +} + +MCRelocationInfo::~MCRelocationInfo() { +} + +const MCExpr * +MCRelocationInfo::createExprForRelocation(object::RelocationRef Rel) { + return 0; +} + +const MCExpr * +MCRelocationInfo::createExprForCAPIVariantKind(const MCExpr *SubExpr, + unsigned VariantKind) { + if (VariantKind != LLVMDisassembler_VariantKind_None) + return 0; + return SubExpr; +} + +MCRelocationInfo *llvm::createMCRelocationInfo(StringRef TT, MCContext &Ctx) { + return new MCRelocationInfo(Ctx); +} diff --git a/lib/MC/MCSectionCOFF.cpp b/lib/MC/MCSectionCOFF.cpp index aac9377..64aa2c5 100644 --- a/lib/MC/MCSectionCOFF.cpp +++ b/lib/MC/MCSectionCOFF.cpp @@ -28,8 +28,20 @@ bool MCSectionCOFF::ShouldOmitSectionDirective(StringRef Name, return false; } +void MCSectionCOFF::setSelection(int Selection, + const MCSectionCOFF *Assoc) const { + assert(Selection != 0 && "invalid COMDAT selection type"); + assert((Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) == + (Assoc != 0) && + "associative COMDAT section must have an associated section"); + this->Selection = Selection; + this->Assoc = Assoc; + Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; +} + void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const { + raw_ostream &OS, + const MCExpr *Subsection) const { // standard sections don't require the '.section' if (ShouldOmitSectionDirective(SectionName, MAI)) { @@ -62,12 +74,15 @@ void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, case COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH: OS << "\t.linkonce same_contents\n"; break; - //NOTE: as of binutils 2.20, there is no way to specifiy select largest - // with the .linkonce directive. For now, we treat it as an invalid - // comdat selection value. + case COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE: + OS << "\t.linkonce associative " << Assoc->getSectionName() << "\n"; + break; case COFF::IMAGE_COMDAT_SELECT_LARGEST: - // OS << "\t.linkonce largest\n"; - // break; + OS << "\t.linkonce largest\n"; + break; + case COFF::IMAGE_COMDAT_SELECT_NEWEST: + OS << "\t.linkonce newest\n"; + break; default: assert (0 && "unsupported COFF selection type"); break; diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp index 0775cfa..bf1a984 100644 --- a/lib/MC/MCSectionELF.cpp +++ b/lib/MC/MCSectionELF.cpp @@ -10,6 +10,7 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" @@ -32,10 +33,14 @@ bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name, } void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const { + raw_ostream &OS, + const MCExpr *Subsection) const { if (ShouldOmitSectionDirective(SectionName, MAI)) { - OS << '\t' << getSectionName() << '\n'; + OS << '\t' << getSectionName(); + if (Subsection) + OS << '\t' << *Subsection; + OS << '\n'; return; } @@ -129,6 +134,9 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, if (Flags & ELF::SHF_GROUP) OS << "," << Group->getName() << ",comdat"; OS << '\n'; + + if (Subsection) + OS << "\t.subsection\t" << *Subsection << '\n'; } bool MCSectionELF::UseCodeAlign() const { diff --git a/lib/MC/MCSectionMachO.cpp b/lib/MC/MCSectionMachO.cpp index fc32315..8704513 100644 --- a/lib/MC/MCSectionMachO.cpp +++ b/lib/MC/MCSectionMachO.cpp @@ -91,7 +91,8 @@ MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section, } void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const { + raw_ostream &OS, + const MCExpr *Subsection) const { OS << "\t.section\t" << getSegmentName() << ',' << getSectionName(); // Get the section type and attributes. diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index d02e553..6542f42 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -24,8 +24,7 @@ using namespace llvm; MCStreamer::MCStreamer(StreamerKind Kind, MCContext &Ctx) : Kind(Kind), Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false), CurrentW64UnwindInfo(0), LastSymbol(0), AutoInitSections(false) { - const MCSection *section = 0; - SectionStack.push_back(std::make_pair(section, section)); + SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>()); } MCStreamer::~MCStreamer() { @@ -36,13 +35,13 @@ MCStreamer::~MCStreamer() { void MCStreamer::reset() { for (unsigned i = 0; i < getNumW64UnwindInfos(); ++i) delete W64UnwindInfos[i]; + W64UnwindInfos.clear(); EmitEHFrame = true; EmitDebugFrame = false; CurrentW64UnwindInfo = 0; LastSymbol = 0; - const MCSection *section = 0; SectionStack.clear(); - SectionStack.push_back(std::make_pair(section, section)); + SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>()); } const MCExpr *MCStreamer::BuildSymbolDiff(MCContext &Context, @@ -59,7 +58,7 @@ const MCExpr *MCStreamer::BuildSymbolDiff(MCContext &Context, } const MCExpr *MCStreamer::ForceExpAbs(const MCExpr* Expr) { - if (Context.getAsmInfo().hasAggressiveSymbolFolding() || + if (Context.getAsmInfo()->hasAggressiveSymbolFolding() || isa<MCSymbolRefExpr>(Expr)) return Expr; @@ -87,55 +86,49 @@ void MCStreamer::EmitDwarfSetLineAddr(int64_t LineDelta, /// EmitIntValue - Special case of EmitValue that avoids the client having to /// pass in a MCExpr for constant integers. -void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size, - unsigned AddrSpace) { +void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size) { assert(Size <= 8 && "Invalid size"); assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) && "Invalid size"); char buf[8]; - const bool isLittleEndian = Context.getAsmInfo().isLittleEndian(); + const bool isLittleEndian = Context.getAsmInfo()->isLittleEndian(); for (unsigned i = 0; i != Size; ++i) { unsigned index = isLittleEndian ? i : (Size - i - 1); buf[i] = uint8_t(Value >> (index * 8)); } - EmitBytes(StringRef(buf, Size), AddrSpace); + EmitBytes(StringRef(buf, Size)); } /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. -void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned Padding, - unsigned AddrSpace) { +void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned Padding) { SmallString<128> Tmp; raw_svector_ostream OSE(Tmp); encodeULEB128(Value, OSE, Padding); - EmitBytes(OSE.str(), AddrSpace); + EmitBytes(OSE.str()); } /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. -void MCStreamer::EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace) { +void MCStreamer::EmitSLEB128IntValue(int64_t Value) { SmallString<128> Tmp; raw_svector_ostream OSE(Tmp); encodeSLEB128(Value, OSE); - EmitBytes(OSE.str(), AddrSpace); + EmitBytes(OSE.str()); } -void MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) { +void MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size) { const MCExpr *ABS = ForceExpAbs(Value); - EmitValue(ABS, Size, AddrSpace); + EmitValue(ABS, Size); } -void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) { - EmitValueImpl(Value, Size, AddrSpace); +void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size) { + EmitValueImpl(Value, Size); } -void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, - unsigned AddrSpace) { - EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size, - AddrSpace); +void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size) { + EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size); } void MCStreamer::EmitGPRel64Value(const MCExpr *Value) { @@ -148,11 +141,15 @@ void MCStreamer::EmitGPRel32Value(const MCExpr *Value) { /// EmitFill - Emit NumBytes bytes worth of the value specified by /// FillValue. This implements directives such as '.space'. -void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace) { +void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) { const MCExpr *E = MCConstantExpr::Create(FillValue, getContext()); for (uint64_t i = 0, e = NumBytes; i != e; ++i) - EmitValue(E, 1, AddrSpace); + EmitValue(E, 1); +} + +/// The implementation in this class just redirects to EmitFill. +void MCStreamer::EmitZeros(uint64_t NumBytes) { + EmitFill(NumBytes, 0); } bool MCStreamer::EmitDwarfFileDirective(unsigned FileNo, @@ -188,15 +185,15 @@ void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, void MCStreamer::EmitLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection() && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection()); + assert(getCurrentSection().first && "Cannot emit before setting section!"); + Symbol->setSection(*getCurrentSection().first); LastSymbol = Symbol; } void MCStreamer::EmitDebugLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection() && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection()); + assert(getCurrentSection().first && "Cannot emit before setting section!"); + Symbol->setSection(*getCurrentSection().first); LastSymbol = Symbol; } @@ -230,7 +227,7 @@ void MCStreamer::RecordProcStart(MCDwarfFrameInfo &Frame) { Frame.Function = LastSymbol; // If the function is externally visible, we need to create a local // symbol to avoid relocations. - StringRef Prefix = getContext().getAsmInfo().getPrivateGlobalPrefix(); + StringRef Prefix = getContext().getAsmInfo()->getPrivateGlobalPrefix(); if (LastSymbol && LastSymbol->getName().startswith(Prefix)) { Frame.Begin = LastSymbol; } else { diff --git a/lib/MC/MCSymbolizer.cpp b/lib/MC/MCSymbolizer.cpp new file mode 100644 index 0000000..1020b74 --- /dev/null +++ b/lib/MC/MCSymbolizer.cpp @@ -0,0 +1,20 @@ +//===-- llvm/MC/MCSymbolizer.cpp - MCSymbolizer class -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSymbolizer.h" +#include "llvm/MC/MCRelocationInfo.h" + +using namespace llvm; + +MCSymbolizer::MCSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo) + : Ctx(Ctx), RelInfo(RelInfo.take()) { +} + +MCSymbolizer::~MCSymbolizer() { +} diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index 6dffed7..4e26934 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" @@ -147,8 +148,7 @@ public: object_t *createCOFFEntity(StringRef Name, list_t &List); void DefineSection(MCSectionData const &SectionData); - void DefineSymbol(MCSymbol const &Symbol, - MCSymbolData const &SymbolData, + void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler); void MakeSymbolReal(COFFSymbol &S, size_t Index); @@ -410,25 +410,23 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) { /// This function takes a section data object from the assembler /// and creates the associated COFF symbol staging object. -void WinCOFFObjectWriter::DefineSymbol(MCSymbol const &Symbol, - MCSymbolData const &SymbolData, +void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler) { + MCSymbol const &Symbol = SymbolData.getSymbol(); COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol); - - coff_symbol->Data.Type = (SymbolData.getFlags() & 0x0000FFFF) >> 0; - coff_symbol->Data.StorageClass = (SymbolData.getFlags() & 0x00FF0000) >> 16; + SymbolMap[&Symbol] = coff_symbol; if (SymbolData.getFlags() & COFF::SF_WeakExternal) { coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; if (Symbol.isVariable()) { - coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; + const MCSymbolRefExpr *SymRef = + dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue()); - // FIXME: This assert message isn't very good. - assert(Symbol.getVariableValue()->getKind() == MCExpr::SymbolRef && - "Value must be a SymbolRef!"); + if (!SymRef) + report_fatal_error("Weak externals may only alias symbols"); - coff_symbol->Other = GetOrCreateCOFFSymbol(&Symbol); + coff_symbol->Other = GetOrCreateCOFFSymbol(&SymRef->getSymbol()); } else { std::string WeakName = std::string(".weak.") + Symbol.getName().str() @@ -448,41 +446,50 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbol const &Symbol, coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0; coff_symbol->Aux[0].Aux.WeakExternal.Characteristics = COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY; - } - // If no storage class was specified in the streamer, define it here. - if (coff_symbol->Data.StorageClass == 0) { - bool external = SymbolData.isExternal() || (SymbolData.Fragment == NULL); + coff_symbol->MCData = &SymbolData; + } else { + const MCSymbolData &ResSymData = + Assembler.getSymbolData(Symbol.AliasedSymbol()); + + coff_symbol->Data.Type = (ResSymData.getFlags() & 0x0000FFFF) >> 0; + coff_symbol->Data.StorageClass = (ResSymData.getFlags() & 0x00FF0000) >> 16; - coff_symbol->Data.StorageClass = - external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; - } + // If no storage class was specified in the streamer, define it here. + if (coff_symbol->Data.StorageClass == 0) { + bool external = ResSymData.isExternal() || (ResSymData.Fragment == NULL); - if (SymbolData.Fragment != NULL) - coff_symbol->Section = - SectionMap[&SymbolData.Fragment->getParent()->getSection()]; + coff_symbol->Data.StorageClass = + external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; + } - // Bind internal COFF symbol to MC symbol. - coff_symbol->MCData = &SymbolData; - SymbolMap[&Symbol] = coff_symbol; + if (ResSymData.Fragment != NULL) + coff_symbol->Section = + SectionMap[&ResSymData.Fragment->getParent()->getSection()]; + + coff_symbol->MCData = &ResSymData; + } } /// making a section real involves assigned it a number and putting /// name into the string table if needed void WinCOFFObjectWriter::MakeSectionReal(COFFSection &S, size_t Number) { if (S.Name.size() > COFF::NameSize) { - size_t StringTableEntry = Strings.insert(S.Name.c_str()); - - // FIXME: Why is this number 999999? This number is never mentioned in the - // spec. I'm assuming this is due to the printed value needing to fit into - // the S.Header.Name field. In which case why not 9999999 (7 9's instead of - // 6)? The spec does not state if this entry should be null terminated in - // this case, and thus this seems to be the best way to do it. I think I - // just solved my own FIXME... - if (StringTableEntry > 999999) - report_fatal_error("COFF string table is greater than 999999 bytes."); - - std::sprintf(S.Header.Name, "/%d", unsigned(StringTableEntry)); + const unsigned Max6DecimalSize = 999999; + const unsigned Max7DecimalSize = 9999999; + uint64_t StringTableEntry = Strings.insert(S.Name.c_str()); + + if (StringTableEntry <= Max6DecimalSize) { + std::sprintf(S.Header.Name, "/%d", unsigned(StringTableEntry)); + } else if (StringTableEntry <= Max7DecimalSize) { + // With seven digits, we have to skip the terminating null. Because + // sprintf always appends it, we use a larger temporary buffer. + char buffer[9] = { }; + std::sprintf(buffer, "/%d", unsigned(StringTableEntry)); + std::memcpy(S.Header.Name, buffer, 8); + } else { + report_fatal_error("COFF string table is greater than 9,999,999 bytes."); + } } else std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size()); @@ -620,9 +627,7 @@ void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, for (MCAssembler::const_symbol_iterator i = Asm.symbol_begin(), e = Asm.symbol_end(); i != e; i++) { if (ExportSymbol(*i, Asm)) { - const MCSymbol &Alias = i->getSymbol(); - const MCSymbol &Symbol = Alias.AliasedSymbol(); - DefineSymbol(Alias, Asm.getSymbolData(Symbol), Asm); + DefineSymbol(*i, Asm); } } } @@ -635,8 +640,9 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, uint64_t &FixedValue) { assert(Target.getSymA() != NULL && "Relocation must reference a symbol!"); - const MCSymbol *A = &Target.getSymA()->getSymbol(); - MCSymbolData &A_SD = Asm.getSymbolData(*A); + const MCSymbol &Symbol = Target.getSymA()->getSymbol(); + const MCSymbol &A = Symbol.AliasedSymbol(); + MCSymbolData &A_SD = Asm.getSymbolData(A); MCSectionData const *SectionData = Fragment->getParent(); @@ -689,13 +695,8 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, ++Reloc.Symb->Relocations; Reloc.Data.VirtualAddress += Fixup.getOffset(); - - unsigned FixupKind = Fixup.getKind(); - - if (CrossSection) - FixupKind = FK_PCRel_4; - - Reloc.Data.Type = TargetObjectWriter->getRelocType(FixupKind); + Reloc.Data.Type = TargetObjectWriter->getRelocType(Target, Fixup, + CrossSection); // FIXME: Can anyone explain what this does other than adjust for the size // of the offset? @@ -711,10 +712,13 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, // Assign symbol and section indexes and offsets. Header.NumberOfSections = 0; + DenseMap<COFFSection *, uint16_t> SectionIndices; for (sections::iterator i = Sections.begin(), e = Sections.end(); i != e; i++) { if (Layout.getSectionAddressSize((*i)->MCData) > 0) { - MakeSectionReal(**i, ++Header.NumberOfSections); + size_t Number = ++Header.NumberOfSections; + SectionIndices[*i] = Number; + MakeSectionReal(**i, Number); } else { (*i)->Number = -1; } @@ -758,6 +762,31 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, } } + // Fixup associative COMDAT sections. + for (sections::iterator i = Sections.begin(), + e = Sections.end(); i != e; i++) { + if ((*i)->Symbol->Aux[0].Aux.SectionDefinition.Selection != + COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) + continue; + + const MCSectionCOFF &MCSec = static_cast<const MCSectionCOFF &>( + (*i)->MCData->getSection()); + + COFFSection *Assoc = SectionMap.lookup(MCSec.getAssocSection()); + if (!Assoc) { + report_fatal_error(Twine("Missing associated COMDAT section ") + + MCSec.getAssocSection()->getSectionName() + + " for section " + MCSec.getSectionName()); + } + + // Skip this section if the associated section is unused. + if (Assoc->Number == -1) + continue; + + (*i)->Symbol->Aux[0].Aux.SectionDefinition.Number = SectionIndices[Assoc]; + } + + // Assign file offsets to COFF object file structures. unsigned offset = 0; diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index 75f343c..04bfeb4 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -155,7 +155,7 @@ void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, int Selection = COFF::IMAGE_COMDAT_SELECT_LARGEST; const MCSection *Section = MCStreamer::getContext().getCOFFSection( - SectionName, Characteristics, Selection, SectionKind::getBSS()); + SectionName, Characteristics, SectionKind::getBSS(), Selection); MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section); |
