diff options
Diffstat (limited to 'lib/MC')
-rw-r--r-- | lib/MC/CMakeLists.txt | 5 | ||||
-rw-r--r-- | lib/MC/ELFObjectWriter.cpp | 49 | ||||
-rw-r--r-- | lib/MC/ELFObjectWriter.h | 6 | ||||
-rw-r--r-- | lib/MC/LLVMBuild.txt | 4 | ||||
-rw-r--r-- | lib/MC/MCAsmInfo.cpp | 1 | ||||
-rw-r--r-- | lib/MC/MCAsmInfoCOFF.cpp | 8 | ||||
-rw-r--r-- | lib/MC/MCAsmInfoDarwin.cpp | 4 | ||||
-rw-r--r-- | lib/MC/MCAsmStreamer.cpp | 4 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 71 | ||||
-rw-r--r-- | lib/MC/MCDisassembler/CMakeLists.txt | 7 | ||||
-rw-r--r-- | lib/MC/MCDisassembler/EDMain.cpp | 280 | ||||
-rw-r--r-- | lib/MC/MCDwarf.cpp | 344 | ||||
-rw-r--r-- | lib/MC/MCELF.cpp | 4 | ||||
-rw-r--r-- | lib/MC/MCELFStreamer.cpp | 5 | ||||
-rw-r--r-- | lib/MC/MCMachOStreamer.cpp | 2 | ||||
-rw-r--r-- | lib/MC/MCObjectFileInfo.cpp | 6 | ||||
-rw-r--r-- | lib/MC/MCObjectStreamer.cpp | 4 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 55 | ||||
-rw-r--r-- | lib/MC/MCParser/CMakeLists.txt | 5 | ||||
-rw-r--r-- | lib/MC/MCParser/ELFAsmParser.cpp | 1 | ||||
-rw-r--r-- | lib/MC/MCParser/LLVMBuild.txt | 1 | ||||
-rw-r--r-- | lib/MC/MachObjectWriter.cpp | 11 | ||||
-rw-r--r-- | lib/MC/WinCOFFObjectWriter.cpp | 2 |
23 files changed, 797 insertions, 82 deletions
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index a4ac1bf..b2e62a5 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -45,10 +45,5 @@ add_llvm_library(LLVMMC WinCOFFStreamer.cpp ) -add_llvm_library_dependencies(LLVMMC - LLVMObject - LLVMSupport - ) - add_subdirectory(MCParser) add_subdirectory(MCDisassembler) diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index bd28069..92aad94 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -182,7 +182,7 @@ uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data, if (const MCExpr *Value = Symbol.getVariableValue()) { int64_t IntValue; if (Value->EvaluateAsAbsolute(IntValue, Layout)) - return (uint64_t)IntValue; + return (uint64_t)IntValue; } } @@ -1072,7 +1072,7 @@ void ELFObjectWriter::WriteDataSectionData(MCAssembler &Asm, WriteBytes(cast<MCDataFragment>(F).getContents().str()); } } else { - Asm.WriteSectionData(&SD, Layout); + Asm.writeSectionData(&SD, Layout); } } @@ -1742,14 +1742,26 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, } } else { if (IsPCRel) { - switch (Modifier) { - default: - llvm_unreachable("Unimplemented"); - case MCSymbolRefExpr::VK_None: - Type = ELF::R_386_PC32; + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + + case X86::reloc_global_offset_table: + Type = ELF::R_386_GOTPC; break; - case MCSymbolRefExpr::VK_PLT: - Type = ELF::R_386_PLT32; + + case X86::reloc_signed_4byte: + case FK_PCRel_4: + case FK_Data_4: + switch (Modifier) { + default: + llvm_unreachable("Unimplemented"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_386_PC32; + break; + case MCSymbolRefExpr::VK_PLT: + Type = ELF::R_386_PLT32; + break; + } break; } } else { @@ -1831,6 +1843,21 @@ void MipsELFObjectWriter::WriteEFlags() { ELF::EF_MIPS_ARCH_32R2); } +const MCSymbol *MipsELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + const MCFixup &Fixup, + bool IsPCRel) const { + assert(Target.getSymA() && "SymA cannot be 0."); + const MCSymbol &Sym = Target.getSymA()->getSymbol(); + + if (Sym.getSection().getKind().isMergeableCString() || + Sym.getSection().getKind().isMergeableConst()) + return &Sym; + + return NULL; +} + unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel, @@ -1858,7 +1885,8 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, case Mips::fixup_Mips_CALL16: Type = ELF::R_MIPS_CALL16; break; - case Mips::fixup_Mips_GOT16: + case Mips::fixup_Mips_GOT_Global: + case Mips::fixup_Mips_GOT_Local: Type = ELF::R_MIPS_GOT16; break; case Mips::fixup_Mips_HI16: @@ -1887,4 +1915,3 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, return Type; } - diff --git a/lib/MC/ELFObjectWriter.h b/lib/MC/ELFObjectWriter.h index 7838206..9adf0b1 100644 --- a/lib/MC/ELFObjectWriter.h +++ b/lib/MC/ELFObjectWriter.h @@ -445,6 +445,12 @@ class ELFObjectWriter : public MCObjectWriter { virtual void WriteEFlags(); protected: + virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + const MCFixup &Fixup, + bool IsPCRel) const; + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel, bool IsRelocWithSymbol, int64_t Addend); diff --git a/lib/MC/LLVMBuild.txt b/lib/MC/LLVMBuild.txt index 8ad66b6..f35dbe4 100644 --- a/lib/MC/LLVMBuild.txt +++ b/lib/MC/LLVMBuild.txt @@ -15,9 +15,11 @@ ; ;===------------------------------------------------------------------------===; +[common] +subdirectories = MCDisassembler MCParser + [component_0] type = Library name = MC parent = Libraries required_libraries = Object Support - diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index c330e74..b1e1bdf 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -29,7 +29,6 @@ MCAsmInfo::MCAsmInfo() { HasSubsectionsViaSymbols = false; HasMachoZeroFillDirective = false; HasMachoTBSSDirective = false; - StructorOutputOrder = Structors::ReversePriorityOrder; HasStaticCtorDtorReferenceInStaticMode = false; LinkerRequiresNonEmptyDwarfLines = false; MaxInstLength = 4; diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp index 434d910..6d34801 100644 --- a/lib/MC/MCAsmInfoCOFF.cpp +++ b/lib/MC/MCAsmInfoCOFF.cpp @@ -38,3 +38,11 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() { SupportsDataRegions = false; } + +MCAsmInfoMicrosoft::MCAsmInfoMicrosoft() { + AllowQuotesInName = true; +} + +MCAsmInfoGNUCOFF::MCAsmInfoGNUCOFF() { + +} diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp index 537d0a3..24f1243 100644 --- a/lib/MC/MCAsmInfoDarwin.cpp +++ b/lib/MC/MCAsmInfoDarwin.cpp @@ -39,7 +39,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. HasMachoZeroFillDirective = true; // Uses .zerofill HasMachoTBSSDirective = true; // Uses .tbss - StructorOutputOrder = Structors::PriorityOrder; HasStaticCtorDtorReferenceInStaticMode = true; CodeBegin = "L$start$code$"; @@ -57,8 +56,9 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { HiddenVisibilityAttr = MCSA_PrivateExtern; HiddenDeclarationVisibilityAttr = MCSA_Invalid; + // Doesn't support protected visibility. - ProtectedVisibilityAttr = MCSA_Global; + ProtectedVisibilityAttr = MCSA_Invalid; HasDotTypeDotSizeDirective = false; HasNoDeadStrip = true; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index d90f7b2..c785c03 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -1284,6 +1284,10 @@ void MCAsmStreamer::Finish() { if (getContext().hasDwarfFiles() && !UseLoc) MCDwarfFileTable::Emit(this); + // If we are generating dwarf for assembly source files dump out the sections. + if (getContext().getGenDwarfForAssembly()) + MCGenDwarfInfo::Emit(this); + if (!UseCFI) EmitFrames(false); } diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 29adbcb..c5bf6b9 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -33,7 +33,7 @@ using namespace llvm; namespace { namespace stats { STATISTIC(EmittedFragments, "Number of emitted assembler fragments"); -STATISTIC(EvaluateFixup, "Number of evaluated fixups"); +STATISTIC(evaluateFixup, "Number of evaluated fixups"); STATISTIC(FragmentLayouts, "Number of fragment layouts"); STATISTIC(ObjectBytes, "Number of emitted object file bytes"); STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps"); @@ -136,7 +136,7 @@ uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const { uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const { // The size is the last fragment's end offset. const MCFragment &F = SD->getFragmentList().back(); - return getFragmentOffset(&F) + getAssembler().ComputeFragmentSize(*this, F); + return getFragmentOffset(&F) + getAssembler().computeFragmentSize(*this, F); } uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const { @@ -237,10 +237,10 @@ const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const { return SD->getFragment()->getAtom(); } -bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, +bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const { - ++stats::EvaluateFixup; + ++stats::evaluateFixup; if (!Fixup.getValue()->EvaluateAsRelocatable(Target, Layout)) report_fatal_error("expected relocatable expression"); @@ -312,7 +312,7 @@ bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, return IsResolved; } -uint64_t MCAssembler::ComputeFragmentSize(const MCAsmLayout &Layout, +uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, const MCFragment &F) const { switch (F.getKind()) { case MCFragment::FT_Data: @@ -374,7 +374,7 @@ void MCAsmLayout::LayoutFragment(MCFragment *F) { // Compute fragment offset and size. uint64_t Offset = 0; if (Prev) - Offset += Prev->Offset + getAssembler().ComputeFragmentSize(*this, *Prev); + Offset += Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev); F->Offset = Offset; LastValidFragment[F->getParent()] = F; @@ -390,7 +390,7 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout, ++stats::EmittedFragments; // FIXME: Embed in fragments instead? - uint64_t FragmentSize = Asm.ComputeFragmentSize(Layout, F); + uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F); switch (F.getKind()) { case MCFragment::FT_Align: { MCAlignFragment &AF = cast<MCAlignFragment>(F); @@ -493,7 +493,7 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout, assert(OW->getStream().tell() - Start == FragmentSize); } -void MCAssembler::WriteSectionData(const MCSectionData *SD, +void MCAssembler::writeSectionData(const MCSectionData *SD, const MCAsmLayout &Layout) const { // Ignore virtual sections. if (SD->getSection().isVirtualSection()) { @@ -546,13 +546,13 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD, } -uint64_t MCAssembler::HandleFixup(const MCAsmLayout &Layout, +uint64_t MCAssembler::handleFixup(const MCAsmLayout &Layout, MCFragment &F, const MCFixup &Fixup) { // Evaluate the fixup. MCValue Target; uint64_t FixedValue; - if (!EvaluateFixup(Layout, Fixup, &F, Target, FixedValue)) { + if (!evaluateFixup(Layout, Fixup, &F, Target, FixedValue)) { // The fixup was unresolved, we need a relocation. Inform the object // writer of the relocation, and give it an opportunity to adjust the // fixup value if need be. @@ -592,7 +592,7 @@ void MCAssembler::Finish() { } // Layout until everything fits. - while (LayoutOnce(Layout)) + while (layoutOnce(Layout)) continue; DEBUG_WITH_TYPE("mc-dump", { @@ -600,7 +600,7 @@ void MCAssembler::Finish() { dump(); }); // Finalize the layout, including fragment lowering. - FinishLayout(Layout); + finishLayout(Layout); DEBUG_WITH_TYPE("mc-dump", { llvm::errs() << "assembler backend - final-layout\n--\n"; @@ -621,7 +621,7 @@ void MCAssembler::Finish() { for (MCDataFragment::fixup_iterator it3 = DF->fixup_begin(), ie3 = DF->fixup_end(); it3 != ie3; ++it3) { MCFixup &Fixup = *it3; - uint64_t FixedValue = HandleFixup(Layout, *DF, Fixup); + uint64_t FixedValue = handleFixup(Layout, *DF, Fixup); getBackend().ApplyFixup(Fixup, DF->getContents().data(), DF->getContents().size(), FixedValue); } @@ -631,7 +631,7 @@ void MCAssembler::Finish() { for (MCInstFragment::fixup_iterator it3 = IF->fixup_begin(), ie3 = IF->fixup_end(); it3 != ie3; ++it3) { MCFixup &Fixup = *it3; - uint64_t FixedValue = HandleFixup(Layout, *IF, Fixup); + uint64_t FixedValue = handleFixup(Layout, *IF, Fixup); getBackend().ApplyFixup(Fixup, IF->getCode().data(), IF->getCode().size(), FixedValue); } @@ -645,8 +645,8 @@ void MCAssembler::Finish() { stats::ObjectBytes += OS.tell() - StartOffset; } -bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup, - const MCFragment *DF, +bool MCAssembler::fixupNeedsRelaxation(const MCFixup &Fixup, + const MCInstFragment *DF, const MCAsmLayout &Layout) const { if (getRelaxAll()) return true; @@ -654,16 +654,13 @@ bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup, // If we cannot resolve the fixup value, it requires relaxation. MCValue Target; uint64_t Value; - if (!EvaluateFixup(Layout, Fixup, DF, Target, Value)) + if (!evaluateFixup(Layout, Fixup, DF, Target, Value)) return true; - // Otherwise, relax if the value is too big for a (signed) i8. - // - // FIXME: This is target dependent! - return int64_t(Value) != int64_t(int8_t(Value)); + return getBackend().fixupNeedsRelaxation(Fixup, Value, DF, Layout); } -bool MCAssembler::FragmentNeedsRelaxation(const MCInstFragment *IF, +bool MCAssembler::fragmentNeedsRelaxation(const MCInstFragment *IF, const MCAsmLayout &Layout) const { // If this inst doesn't ever need relaxation, ignore it. This occurs when we // are intentionally pushing out inst fragments, or because we relaxed a @@ -673,15 +670,15 @@ bool MCAssembler::FragmentNeedsRelaxation(const MCInstFragment *IF, for (MCInstFragment::const_fixup_iterator it = IF->fixup_begin(), ie = IF->fixup_end(); it != ie; ++it) - if (FixupNeedsRelaxation(*it, IF, Layout)) + if (fixupNeedsRelaxation(*it, IF, Layout)) return true; return false; } -bool MCAssembler::RelaxInstruction(MCAsmLayout &Layout, +bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, MCInstFragment &IF) { - if (!FragmentNeedsRelaxation(&IF, Layout)) + if (!fragmentNeedsRelaxation(&IF, Layout)) return false; ++stats::RelaxedInstructions; @@ -715,7 +712,7 @@ bool MCAssembler::RelaxInstruction(MCAsmLayout &Layout, return true; } -bool MCAssembler::RelaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { +bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { int64_t Value = 0; uint64_t OldSize = LF.getContents().size(); bool IsAbs = LF.getValue().EvaluateAsAbsolute(Value, Layout); @@ -732,8 +729,8 @@ bool MCAssembler::RelaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { return OldSize != LF.getContents().size(); } -bool MCAssembler::RelaxDwarfLineAddr(MCAsmLayout &Layout, - MCDwarfLineAddrFragment &DF) { +bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, + MCDwarfLineAddrFragment &DF) { int64_t AddrDelta = 0; uint64_t OldSize = DF.getContents().size(); bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout); @@ -749,7 +746,7 @@ bool MCAssembler::RelaxDwarfLineAddr(MCAsmLayout &Layout, return OldSize != Data.size(); } -bool MCAssembler::RelaxDwarfCallFrameFragment(MCAsmLayout &Layout, +bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout, MCDwarfCallFrameFragment &DF) { int64_t AddrDelta = 0; uint64_t OldSize = DF.getContents().size(); @@ -764,7 +761,7 @@ bool MCAssembler::RelaxDwarfCallFrameFragment(MCAsmLayout &Layout, return OldSize != Data.size(); } -bool MCAssembler::LayoutSectionOnce(MCAsmLayout &Layout, +bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD) { MCFragment *FirstInvalidFragment = NULL; // Scan for fragments that need relaxation. @@ -776,19 +773,19 @@ bool MCAssembler::LayoutSectionOnce(MCAsmLayout &Layout, default: break; case MCFragment::FT_Inst: - relaxedFrag = RelaxInstruction(Layout, *cast<MCInstFragment>(it2)); + relaxedFrag = relaxInstruction(Layout, *cast<MCInstFragment>(it2)); break; case MCFragment::FT_Dwarf: - relaxedFrag = RelaxDwarfLineAddr(Layout, + relaxedFrag = relaxDwarfLineAddr(Layout, *cast<MCDwarfLineAddrFragment>(it2)); break; case MCFragment::FT_DwarfFrame: relaxedFrag = - RelaxDwarfCallFrameFragment(Layout, + relaxDwarfCallFrameFragment(Layout, *cast<MCDwarfCallFrameFragment>(it2)); break; case MCFragment::FT_LEB: - relaxedFrag = RelaxLEB(Layout, *cast<MCLEBFragment>(it2)); + relaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(it2)); break; } // Update the layout, and remember that we relaxed. @@ -802,20 +799,20 @@ bool MCAssembler::LayoutSectionOnce(MCAsmLayout &Layout, return false; } -bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) { +bool MCAssembler::layoutOnce(MCAsmLayout &Layout) { ++stats::RelaxationSteps; bool WasRelaxed = false; for (iterator it = begin(), ie = end(); it != ie; ++it) { MCSectionData &SD = *it; - while(LayoutSectionOnce(Layout, SD)) + while(layoutSectionOnce(Layout, SD)) WasRelaxed = true; } return WasRelaxed; } -void MCAssembler::FinishLayout(MCAsmLayout &Layout) { +void MCAssembler::finishLayout(MCAsmLayout &Layout) { // The layout is done. Mark every fragment as valid. for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) { Layout.getFragmentOffset(&*Layout.getSectionOrder()[i]->rbegin()); diff --git a/lib/MC/MCDisassembler/CMakeLists.txt b/lib/MC/MCDisassembler/CMakeLists.txt index 5cf5f1b..5e2cd83 100644 --- a/lib/MC/MCDisassembler/CMakeLists.txt +++ b/lib/MC/MCDisassembler/CMakeLists.txt @@ -2,12 +2,7 @@ add_llvm_library(LLVMMCDisassembler Disassembler.cpp EDDisassembler.cpp EDInst.cpp + EDMain.cpp EDOperand.cpp EDToken.cpp ) - -add_llvm_library_dependencies(LLVMMCDisassembler - LLVMMC - LLVMMCParser - LLVMSupport - ) diff --git a/lib/MC/MCDisassembler/EDMain.cpp b/lib/MC/MCDisassembler/EDMain.cpp new file mode 100644 index 0000000..3fd355b --- /dev/null +++ b/lib/MC/MCDisassembler/EDMain.cpp @@ -0,0 +1,280 @@ +//===-- EDMain.cpp - LLVM Enhanced Disassembly C API ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the enhanced disassembler's public C API. +// +//===----------------------------------------------------------------------===// + +#include "EDDisassembler.h" +#include "EDInst.h" +#include "EDOperand.h" +#include "EDToken.h" +#include "llvm-c/EnhancedDisassembly.h" +using namespace llvm; + +int EDGetDisassembler(EDDisassemblerRef *disassembler, + const char *triple, + EDAssemblySyntax_t syntax) { + EDDisassembler::AssemblySyntax Syntax; + switch (syntax) { + default: assert(0 && "Unknown assembly syntax!"); + case kEDAssemblySyntaxX86Intel: + Syntax = EDDisassembler::kEDAssemblySyntaxX86Intel; + break; + case kEDAssemblySyntaxX86ATT: + Syntax = EDDisassembler::kEDAssemblySyntaxX86ATT; + break; + case kEDAssemblySyntaxARMUAL: + Syntax = EDDisassembler::kEDAssemblySyntaxARMUAL; + break; + } + + EDDisassemblerRef ret = EDDisassembler::getDisassembler(triple, Syntax); + + if (!ret) + return -1; + *disassembler = ret; + return 0; +} + +int EDGetRegisterName(const char** regName, + EDDisassemblerRef disassembler, + unsigned regID) { + const char *name = ((EDDisassembler*)disassembler)->nameWithRegisterID(regID); + if (!name) + return -1; + *regName = name; + return 0; +} + +int EDRegisterIsStackPointer(EDDisassemblerRef disassembler, + unsigned regID) { + return ((EDDisassembler*)disassembler)->registerIsStackPointer(regID) ? 1 : 0; +} + +int EDRegisterIsProgramCounter(EDDisassemblerRef disassembler, + unsigned regID) { + return ((EDDisassembler*)disassembler)->registerIsProgramCounter(regID) ? 1:0; +} + +unsigned int EDCreateInsts(EDInstRef *insts, + unsigned int count, + EDDisassemblerRef disassembler, + ::EDByteReaderCallback byteReader, + uint64_t address, + void *arg) { + unsigned int index; + + for (index = 0; index < count; ++index) { + EDInst *inst = ((EDDisassembler*)disassembler)->createInst(byteReader, + address, arg); + + if (!inst) + return index; + + insts[index] = inst; + address += inst->byteSize(); + } + + return count; +} + +void EDReleaseInst(EDInstRef inst) { + delete ((EDInst*)inst); +} + +int EDInstByteSize(EDInstRef inst) { + return ((EDInst*)inst)->byteSize(); +} + +int EDGetInstString(const char **buf, + EDInstRef inst) { + return ((EDInst*)inst)->getString(*buf); +} + +int EDInstID(unsigned *instID, EDInstRef inst) { + *instID = ((EDInst*)inst)->instID(); + return 0; +} + +int EDInstIsBranch(EDInstRef inst) { + return ((EDInst*)inst)->isBranch(); +} + +int EDInstIsMove(EDInstRef inst) { + return ((EDInst*)inst)->isMove(); +} + +int EDBranchTargetID(EDInstRef inst) { + return ((EDInst*)inst)->branchTargetID(); +} + +int EDMoveSourceID(EDInstRef inst) { + return ((EDInst*)inst)->moveSourceID(); +} + +int EDMoveTargetID(EDInstRef inst) { + return ((EDInst*)inst)->moveTargetID(); +} + +int EDNumTokens(EDInstRef inst) { + return ((EDInst*)inst)->numTokens(); +} + +int EDGetToken(EDTokenRef *token, + EDInstRef inst, + int index) { + return ((EDInst*)inst)->getToken(*(EDToken**)token, index); +} + +int EDGetTokenString(const char **buf, + EDTokenRef token) { + return ((EDToken*)token)->getString(*buf); +} + +int EDOperandIndexForToken(EDTokenRef token) { + return ((EDToken*)token)->operandID(); +} + +int EDTokenIsWhitespace(EDTokenRef token) { + return ((EDToken*)token)->type() == EDToken::kTokenWhitespace; +} + +int EDTokenIsPunctuation(EDTokenRef token) { + return ((EDToken*)token)->type() == EDToken::kTokenPunctuation; +} + +int EDTokenIsOpcode(EDTokenRef token) { + return ((EDToken*)token)->type() == EDToken::kTokenOpcode; +} + +int EDTokenIsLiteral(EDTokenRef token) { + return ((EDToken*)token)->type() == EDToken::kTokenLiteral; +} + +int EDTokenIsRegister(EDTokenRef token) { + return ((EDToken*)token)->type() == EDToken::kTokenRegister; +} + +int EDTokenIsNegativeLiteral(EDTokenRef token) { + if (((EDToken*)token)->type() != EDToken::kTokenLiteral) + return -1; + + return ((EDToken*)token)->literalSign(); +} + +int EDLiteralTokenAbsoluteValue(uint64_t *value, EDTokenRef token) { + if (((EDToken*)token)->type() != EDToken::kTokenLiteral) + return -1; + + return ((EDToken*)token)->literalAbsoluteValue(*value); +} + +int EDRegisterTokenValue(unsigned *registerID, + EDTokenRef token) { + if (((EDToken*)token)->type() != EDToken::kTokenRegister) + return -1; + + return ((EDToken*)token)->registerID(*registerID); +} + +int EDNumOperands(EDInstRef inst) { + return ((EDInst*)inst)->numOperands(); +} + +int EDGetOperand(EDOperandRef *operand, + EDInstRef inst, + int index) { + return ((EDInst*)inst)->getOperand(*(EDOperand**)operand, index); +} + +int EDOperandIsRegister(EDOperandRef operand) { + return ((EDOperand*)operand)->isRegister(); +} + +int EDOperandIsImmediate(EDOperandRef operand) { + return ((EDOperand*)operand)->isImmediate(); +} + +int EDOperandIsMemory(EDOperandRef operand) { + return ((EDOperand*)operand)->isMemory(); +} + +int EDRegisterOperandValue(unsigned *value, EDOperandRef operand) { + if (!((EDOperand*)operand)->isRegister()) + return -1; + *value = ((EDOperand*)operand)->regVal(); + return 0; +} + +int EDImmediateOperandValue(uint64_t *value, EDOperandRef operand) { + if (!((EDOperand*)operand)->isImmediate()) + return -1; + *value = ((EDOperand*)operand)->immediateVal(); + return 0; +} + +int EDEvaluateOperand(uint64_t *result, EDOperandRef operand, + ::EDRegisterReaderCallback regReader, void *arg) { + return ((EDOperand*)operand)->evaluate(*result, regReader, arg); +} + +#ifdef __BLOCKS__ + +struct ByteReaderWrapper { + EDByteBlock_t byteBlock; +}; + +static int readerWrapperCallback(uint8_t *byte, + uint64_t address, + void *arg) { + struct ByteReaderWrapper *wrapper = (struct ByteReaderWrapper *)arg; + return wrapper->byteBlock(byte, address); +} + +unsigned int EDBlockCreateInsts(EDInstRef *insts, + int count, + EDDisassemblerRef disassembler, + EDByteBlock_t byteBlock, + uint64_t address) { + struct ByteReaderWrapper wrapper; + wrapper.byteBlock = byteBlock; + + return EDCreateInsts(insts, + count, + disassembler, + readerWrapperCallback, + address, + (void*)&wrapper); +} + +int EDBlockEvaluateOperand(uint64_t *result, EDOperandRef operand, + EDRegisterBlock_t regBlock) { + return ((EDOperand*)operand)->evaluate(*result, regBlock); +} + +int EDBlockVisitTokens(EDInstRef inst, ::EDTokenVisitor_t visitor) { + return ((EDInst*)inst)->visitTokens((llvm::EDTokenVisitor_t)visitor); +} + +#else + +extern "C" unsigned int EDBlockCreateInsts() { + return 0; +} + +extern "C" int EDBlockEvaluateOperand() { + return -1; +} + +extern "C" int EDBlockVisitTokens() { + return -1; +} + +#endif diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index d2bbd7d..46ab65f 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -19,9 +19,12 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" +#include "llvm/Config/config.h" using namespace llvm; // Given a special op, return the address skip amount (in units of @@ -423,6 +426,342 @@ void MCDwarfFile::dump() const { print(dbgs()); } +// Utility function to write a tuple for .debug_abbrev. +static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) { + MCOS->EmitULEB128IntValue(Name); + MCOS->EmitULEB128IntValue(Form); +} + +// When generating dwarf for assembly source files this emits +// the data for .debug_abbrev section which contains three DIEs. +static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { + MCContext &context = MCOS->getContext(); + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); + + // DW_TAG_compile_unit DIE abbrev (1). + MCOS->EmitULEB128IntValue(1); + MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit); + MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); + EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4); + EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); + EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); + EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); + EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string); + StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); + if (!DwarfDebugFlags.empty()) + EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string); + EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string); + EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2); + EmitAbbrev(MCOS, 0, 0); + + // DW_TAG_subprogram DIE abbrev (2). + MCOS->EmitULEB128IntValue(2); + MCOS->EmitULEB128IntValue(dwarf::DW_TAG_subprogram); + MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); + EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); + EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4); + EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4); + EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); + EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); + EmitAbbrev(MCOS, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag); + EmitAbbrev(MCOS, 0, 0); + + // DW_TAG_unspecified_parameters DIE abbrev (3). + MCOS->EmitULEB128IntValue(3); + MCOS->EmitULEB128IntValue(dwarf::DW_TAG_unspecified_parameters); + MCOS->EmitIntValue(dwarf::DW_CHILDREN_no, 1); + EmitAbbrev(MCOS, 0, 0); + + // Terminate the abbreviations for this compilation unit. + MCOS->EmitIntValue(0, 1); +} + +// When generating dwarf for assembly source files this emits the data for +// .debug_aranges section. Which contains a header and a table of pairs of +// PointerSize'ed values for the address and size of section(s) with line table +// entries (just the default .text in our case) and a terminating pair of zeros. +static void EmitGenDwarfAranges(MCStreamer *MCOS) { + MCContext &context = MCOS->getContext(); + + // Create a symbol at the end of the section that we are creating the dwarf + // debugging info to use later in here as part of the expression to calculate + // the size of the section for the table. + MCOS->SwitchSection(context.getGenDwarfSection()); + MCSymbol *SectionEndSym = context.CreateTempSymbol(); + MCOS->EmitLabel(SectionEndSym); + context.setGenDwarfSectionEndSym(SectionEndSym); + + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); + + // This will be the length of the .debug_aranges section, first account for + // the size of each item in the header (see below where we emit these items). + int Length = 4 + 2 + 4 + 1 + 1; + + // 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(); + int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1)); + if (Pad == 2 * AddrSize) + Pad = 0; + Length += Pad; + + // Add the size of the pair of PointerSize'ed values for the address and size + // of the one default .text section we have in the table. + Length += 2 * AddrSize; + // And the pair of terminating zeros. + Length += 2 * AddrSize; + + + // Emit the header for this section. + // The 4 byte length not including the 4 byte value for the length. + MCOS->EmitIntValue(Length - 4, 4); + // The 2 byte version, which is 2. + MCOS->EmitIntValue(2, 2); + // The 4 byte offset to the compile unit in the .debug_info from the start + // of the .debug_info, it is at the start of that section so this is zero. + MCOS->EmitIntValue(0, 4); + // The 1 byte size of an address. + MCOS->EmitIntValue(AddrSize, 1); + // The 1 byte size of a segment descriptor, we use a value of zero. + MCOS->EmitIntValue(0, 1); + // Align the header with the padding if needed, before we put out the table. + for(int i = 0; i < Pad; i++) + MCOS->EmitIntValue(0, 1); + + // Now emit the table of pairs of PointerSize'ed values for the section(s) + // address and size, in our case just the one default .text section. + const MCExpr *Addr = MCSymbolRefExpr::Create( + context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); + const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, + *context.getGenDwarfSectionStartSym(), *SectionEndSym, 0); + MCOS->EmitAbsValue(Addr, AddrSize); + MCOS->EmitAbsValue(Size, AddrSize); + + // And finally the pair of terminating zeros. + MCOS->EmitIntValue(0, AddrSize); + MCOS->EmitIntValue(0, AddrSize); +} + +// When generating dwarf for assembly source files this emits the data for +// .debug_info section which contains three parts. The header, the compile_unit +// DIE and a list of subprogram DIEs. +static void EmitGenDwarfInfo(MCStreamer *MCOS) { + MCContext &context = MCOS->getContext(); + + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); + + // Create a symbol at the start and end of this section used in here for the + // expression to calculate the length in the header. + MCSymbol *InfoStart = context.CreateTempSymbol(); + MCOS->EmitLabel(InfoStart); + MCSymbol *InfoEnd = context.CreateTempSymbol(); + + // First part: the header. + + // The 4 byte total length of the information for this compilation unit, not + // including these 4 bytes. + const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4); + MCOS->EmitAbsValue(Length, 4); + + // The 2 byte DWARF version, which is 2. + MCOS->EmitIntValue(2, 2); + + // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev, + // it is at the start of that section so this is zero. + MCOS->EmitIntValue(0, 4); + + const MCAsmInfo &asmInfo = context.getAsmInfo(); + int AddrSize = asmInfo.getPointerSize(); + // The 1 byte size of an address. + MCOS->EmitIntValue(AddrSize, 1); + + // Second part: the compile_unit DIE. + + // The DW_TAG_compile_unit DIE abbrev (1). + MCOS->EmitULEB128IntValue(1); + + // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section, + // which is at the start of that section so this is zero. + MCOS->EmitIntValue(0, 4); + + // AT_low_pc, the first address of the default .text section. + const MCExpr *Start = MCSymbolRefExpr::Create( + context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); + MCOS->EmitAbsValue(Start, AddrSize); + + // AT_high_pc, the last address of the default .text section. + const MCExpr *End = MCSymbolRefExpr::Create( + context.getGenDwarfSectionEndSym(), MCSymbolRefExpr::VK_None, context); + MCOS->EmitAbsValue(End, AddrSize); + + // AT_name, the name of the source file. Reconstruct from the first directory + // and file table entries. + const std::vector<StringRef> &MCDwarfDirs = + context.getMCDwarfDirs(); + if (MCDwarfDirs.size() > 0) { + MCOS->EmitBytes(MCDwarfDirs[0], 0); + MCOS->EmitBytes("/", 0); + } + const std::vector<MCDwarfFile *> &MCDwarfFiles = + MCOS->getContext().getMCDwarfFiles(); + MCOS->EmitBytes(MCDwarfFiles[1]->getName(), 0); + MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. + + // AT_comp_dir, the working directory the assembly was done in. + llvm::sys::Path CWD = llvm::sys::Path::GetCurrentDirectory(); + MCOS->EmitBytes(StringRef(CWD.c_str()), 0); + MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. + + // AT_APPLE_flags, the command line arguments of the assembler tool. + StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); + if (!DwarfDebugFlags.empty()){ + MCOS->EmitBytes(DwarfDebugFlags, 0); + MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. + } + + // AT_producer, the version of the assembler tool. + MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM "), 0); + MCOS->EmitBytes(StringRef(PACKAGE_VERSION), 0); + MCOS->EmitBytes(StringRef(")"), 0); + MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. + + // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2 + // draft has no standard code for assembler. + MCOS->EmitIntValue(dwarf::DW_LANG_Mips_Assembler, 2); + + // Third part: the list of subprogram DIEs. + + // Loop on saved info for dwarf subprograms and create the DIEs for them. + const std::vector<const MCGenDwarfSubprogramEntry *> &Entries = + MCOS->getContext().getMCGenDwarfSubprogramEntries(); + for (std::vector<const MCGenDwarfSubprogramEntry *>::const_iterator it = + Entries.begin(), ie = Entries.end(); it != ie; + ++it) { + const MCGenDwarfSubprogramEntry *Entry = *it; + + // The DW_TAG_subprogram DIE abbrev (2). + MCOS->EmitULEB128IntValue(2); + + // AT_name, of the label without any leading underbar. + MCOS->EmitBytes(Entry->getName(), 0); + MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. + + // AT_decl_file, index into the file table. + MCOS->EmitIntValue(Entry->getFileNumber(), 4); + + // AT_decl_line, source line number. + MCOS->EmitIntValue(Entry->getLineNumber(), 4); + + // AT_low_pc, start address of the label. + const MCExpr *AT_low_pc = MCSymbolRefExpr::Create(Entry->getLabel(), + MCSymbolRefExpr::VK_None, context); + MCOS->EmitAbsValue(AT_low_pc, AddrSize); + + // AT_high_pc, end address which is the next label or end of the section. + std::vector<const MCGenDwarfSubprogramEntry *>::const_iterator next = it+1; + if (next != Entries.end()){ + const MCGenDwarfSubprogramEntry *NextEntry = *next; + const MCExpr *AT_high_pc = MCSymbolRefExpr::Create(NextEntry->getLabel(), + MCSymbolRefExpr::VK_None, context); + MCOS->EmitAbsValue(AT_high_pc, AddrSize); + } else { + MCOS->EmitAbsValue(End, AddrSize); + } + + // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype. + MCOS->EmitIntValue(0, 1); + + // The DW_TAG_unspecified_parameters DIE abbrev (3). + MCOS->EmitULEB128IntValue(3); + + // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's. + MCOS->EmitIntValue(0, 1); + } + // Deallocate the MCGenDwarfSubprogramEntry classes that saved away the info + // for the dwarf subprograms. + for (std::vector<const MCGenDwarfSubprogramEntry *>::const_iterator it = + Entries.begin(), ie = Entries.end(); it != ie; + ++it) { + const MCGenDwarfSubprogramEntry *Entry = *it; + delete Entry; + } + + // Add the NULL DIE terminating the Compile Unit DIE's. + MCOS->EmitIntValue(0, 1); + + // Now set the value of the symbol at the end of the info section. + MCOS->EmitLabel(InfoEnd); +} + +// +// When generating dwarf for assembly source files this emits the Dwarf +// sections. +// +void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { + // Create the dwarf sections in this order (.debug_line already created). + MCContext &context = MCOS->getContext(); + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); + + // If there are no line table entries then do not emit any section contents. + if (context.getMCLineSections().empty()) + return; + + // Output the data for .debug_aranges section. + EmitGenDwarfAranges(MCOS); + + // Output the data for .debug_abbrev section. + EmitGenDwarfAbbrev(MCOS); + + // Output the data for .debug_info section. + EmitGenDwarfInfo(MCOS); +} + +// +// When generating dwarf for assembly source files this is called when symbol +// for a label is created. If this symbol is not a temporary and is in the +// section that dwarf is being generated for, save the needed info to create +// a dwarf subprogram. +// +void MCGenDwarfSubprogramEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, + SourceMgr &SrcMgr, SMLoc &Loc) { + // We won't create dwarf subprogram's for temporary symbols or symbols not in + // the default text. + if (Symbol->isTemporary()) + return; + MCContext &context = MCOS->getContext(); + if (context.getGenDwarfSection() != MCOS->getCurrentSection()) + return; + + // The dwarf subprogram's name does not have the symbol name's leading + // underbar if any. + StringRef Name = Symbol->getName(); + if (Name.startswith("_")) + Name = Name.substr(1, Name.size()-1); + + // Get the dwarf file number to be used for the dwarf subprogram. + unsigned FileNumber = context.getGenDwarfFileNumber(); + + // Finding the line number is the expensive part which is why we just don't + // pass it in as for some symbols we won't create a dwarf subprogram. + int CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); + unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer); + + // We create a temporary symbol for use for the AT_high_pc and AT_low_pc + // values so that they don't have things like an ARM thumb bit from the + // original symbol. So when used they won't get a low bit set after + // relocation. + MCSymbol *Label = context.CreateTempSymbol(); + MCOS->EmitLabel(Label); + + // Create and entry for the info and add it to the other entries. + MCGenDwarfSubprogramEntry *Entry = + new MCGenDwarfSubprogramEntry(Name, FileNumber, LineNumber, Label); + MCOS->getContext().addMCGenDwarfSubprogramEntry(Entry); +} + static int getDataAlignmentFactor(MCStreamer &streamer) { MCContext &context = streamer.getContext(); const MCAsmInfo &asmInfo = context.getAsmInfo(); @@ -1009,10 +1348,7 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getFrameInfos(); // Emit the compact unwind info if available. - // FIXME: This emits both the compact unwind and the old CIE/FDE - // information. Only one of those is needed. - // FIXME: Disable. This seems to still be causing failures. - if (false && IsEH && MOFI->getCompactUnwindSection()) + if (IsEH && MOFI->getCompactUnwindSection()) for (unsigned i = 0, n = Streamer.getNumFrameInfos(); i < n; ++i) { const MCDwarfFrameInfo &Frame = Streamer.getFrameInfo(i); if (Frame.CompactUnwindEncoding) diff --git a/lib/MC/MCELF.cpp b/lib/MC/MCELF.cpp index dad2e7b..f9f98e0 100644 --- a/lib/MC/MCELF.cpp +++ b/lib/MC/MCELF.cpp @@ -37,7 +37,7 @@ void MCELF::SetType(MCSymbolData &SD, unsigned Type) { assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || Type == ELF::STT_FILE || Type == ELF::STT_COMMON || - Type == ELF::STT_TLS); + Type == ELF::STT_TLS || Type == ELF::STT_GNU_IFUNC); uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STT_Shift); SD.setFlags(OtherFlags | (Type << ELF_STT_Shift)); @@ -48,7 +48,7 @@ unsigned MCELF::GetType(const MCSymbolData &SD) { assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || Type == ELF::STT_FILE || Type == ELF::STT_COMMON || - Type == ELF::STT_TLS); + Type == ELF::STT_TLS || Type == ELF::STT_GNU_IFUNC); return Type; } diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 0ea3c64..dcc4666 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -130,7 +130,6 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_WeakDefinition: case MCSA_WeakDefAutoPrivate: case MCSA_Invalid: - case MCSA_ELF_TypeIndFunction: case MCSA_IndirectSymbol: assert(0 && "Invalid symbol attribute for ELF!"); break; @@ -162,6 +161,10 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCELF::SetType(SD, ELF::STT_FUNC); break; + case MCSA_ELF_TypeIndFunction: + MCELF::SetType(SD, ELF::STT_GNU_IFUNC); + break; + case MCSA_ELF_TypeObject: MCELF::SetType(SD, ELF::STT_OBJECT); break; diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index aa35815..50ab1f8 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -156,8 +156,6 @@ void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { } void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) { - // FIXME: Flag the function ISA as thumb with DW_AT_APPLE_isa. - // Remember that the function is a thumb function. Fixup and relocation // values will need adjusted. getAssembler().setIsThumbFunc(Symbol); diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index 7d23541..32ba924 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -31,6 +31,8 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { if (T.isMacOSX() && T.isMacOSXVersionLT(10, 5)) CommDirectiveSupportsAlignment = false; + StructorOutputOrder = Structors::PriorityOrder; + TextSection // .text = Ctx->getMachOSection("__TEXT", "__text", MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, @@ -258,6 +260,8 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { } } + StructorOutputOrder = Structors::ReversePriorityOrder; + // ELF BSSSection = Ctx->getELFSection(".bss", ELF::SHT_NOBITS, @@ -385,6 +389,8 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { // COFF + StructorOutputOrder = Structors::ReversePriorityOrder; + TextSection = Ctx->getCOFFSection(".text", COFF::IMAGE_SCN_CNT_CODE | diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 90c957f..663d0ca 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -260,5 +260,9 @@ void MCObjectStreamer::Finish() { if (getContext().hasDwarfFiles()) MCDwarfFileTable::Emit(this); + // If we are generating dwarf for assembly source files dump out the sections. + if (getContext().getGenDwarfForAssembly()) + MCGenDwarfInfo::Emit(this); + getAssembler().Finish(); } diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 7883893..aac020d 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -181,6 +181,9 @@ private: /// EnterIncludeFile - Enter the specified file. This returns true on failure. bool EnterIncludeFile(const std::string &Filename); + /// ProcessIncbinFile - Process the specified file for the .incbin directive. + /// This returns true on failure. + bool ProcessIncbinFile(const std::string &Filename); /// \brief Reset the current lexer position to that given by \arg Loc. The /// current token is not set; clients should ensure Lex() is called @@ -227,6 +230,7 @@ private: bool ParseDirectiveAbort(); // ".abort" bool ParseDirectiveInclude(); // ".include" + bool ParseDirectiveIncbin(); // ".incbin" bool ParseDirectiveIf(SMLoc DirectiveLoc); // ".if" // ".ifdef" or ".ifndef", depending on expect_defined @@ -429,6 +433,21 @@ bool AsmParser::EnterIncludeFile(const std::string &Filename) { return false; } +/// Process the specified .incbin file by seaching for it in the include paths +/// then just emiting the byte contents of the file to the streamer. This +/// returns true on failure. +bool AsmParser::ProcessIncbinFile(const std::string &Filename) { + std::string IncludedFile; + int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); + if (NewBuf == -1) + return true; + + // Pick up the bytes from the file and emit them. + getStreamer().EmitBytes(SrcMgr.getMemoryBuffer(NewBuf)->getBuffer(), + DEFAULT_ADDRSPACE); + return false; +} + void AsmParser::JumpToLoc(SMLoc Loc) { CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), Loc.getPointer()); @@ -468,6 +487,9 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // section and generate a .file directive. if (getContext().getGenDwarfForAssembly()) { getContext().setGenDwarfSection(getStreamer().getCurrentSection()); + MCSymbol *SectionStartSym = getContext().CreateTempSymbol(); + getStreamer().EmitLabel(SectionStartSym); + getContext().setGenDwarfSectionStartSym(SectionStartSym); getStreamer().EmitDwarfFileDirective(getContext().nextGenDwarfFileNumber(), StringRef(), SrcMgr.getMemoryBuffer(CurBuffer)->getBufferIdentifier()); } @@ -1047,6 +1069,12 @@ bool AsmParser::ParseStatement() { // Emit the label. Out.EmitLabel(Sym); + // If we are generating dwarf for assembly source files then gather the + // info to make a dwarf subprogram entry for this label if needed. + if (getContext().getGenDwarfForAssembly()) + MCGenDwarfSubprogramEntry::Make(Sym, &getStreamer(), getSourceManager(), + IDLoc); + // Consume any end of statement token, if present, to avoid spurious // AddBlankLine calls(). if (Lexer.is(AsmToken::EndOfStatement)) { @@ -1174,6 +1202,8 @@ bool AsmParser::ParseStatement() { return ParseDirectiveAbort(); if (IDVal == ".include") return ParseDirectiveInclude(); + if (IDVal == ".incbin") + return ParseDirectiveIncbin(); if (IDVal == ".code16") return TokError(Twine(IDVal) + " not supported yet"); @@ -2197,6 +2227,31 @@ bool AsmParser::ParseDirectiveInclude() { return false; } +/// ParseDirectiveIncbin +/// ::= .incbin "filename" +bool AsmParser::ParseDirectiveIncbin() { + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in '.incbin' directive"); + + std::string Filename = getTok().getString(); + SMLoc IncbinLoc = getLexer().getLoc(); + Lex(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.incbin' directive"); + + // Strip the quotes. + Filename = Filename.substr(1, Filename.size()-2); + + // Attempt to process the included file. + if (ProcessIncbinFile(Filename)) { + Error(IncbinLoc, "Could not find incbin file '" + Filename + "'"); + return true; + } + + return false; +} + /// ParseDirectiveIf /// ::= .if expression bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { diff --git a/lib/MC/MCParser/CMakeLists.txt b/lib/MC/MCParser/CMakeLists.txt index 299d281..222f237 100644 --- a/lib/MC/MCParser/CMakeLists.txt +++ b/lib/MC/MCParser/CMakeLists.txt @@ -9,8 +9,3 @@ add_llvm_library(LLVMMCParser MCAsmParserExtension.cpp MCTargetAsmParser.cpp ) - -add_llvm_library_dependencies(LLVMMCParser - LLVMMC - LLVMSupport - ) diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index d891126..ffc400b 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -476,6 +476,7 @@ bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { .Case("common", MCSA_ELF_TypeCommon) .Case("notype", MCSA_ELF_TypeNoType) .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) + .Case("gnu_indirect_function", MCSA_ELF_TypeIndFunction) .Default(MCSA_Invalid); if (Attr == MCSA_Invalid) diff --git a/lib/MC/MCParser/LLVMBuild.txt b/lib/MC/MCParser/LLVMBuild.txt index 83146a9..bcb0feb 100644 --- a/lib/MC/MCParser/LLVMBuild.txt +++ b/lib/MC/MCParser/LLVMBuild.txt @@ -20,4 +20,3 @@ type = Library name = MCParser parent = MC required_libraries = MC Support - diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index a9219ad..e016f09 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -584,9 +584,14 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, // requires the compiler to use .set to absolutize the differences between // symbols which the compiler knows to be assembly time constants, so we // don't need to worry about considering symbol differences fully resolved. + // + // If the file isn't using sub-sections-via-symbols, we can make the + // same assumptions about any symbol that we normally make about + // assembler locals. if (!Asm.getBackend().hasReliableSymbolDifference()) { - if (!SA.isTemporary() || !SA.isInSection() || &SecA != &SecB) + if ((!SA.isTemporary() && Asm.getSubsectionsViaSymbols()) || + !SA.isInSection() || &SecA != &SecB) return false; return true; } @@ -628,7 +633,7 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, } void MachObjectWriter::WriteObject(MCAssembler &Asm, - const MCAsmLayout &Layout) { + const MCAsmLayout &Layout) { unsigned NumSections = Asm.size(); // The section data starts after the header, the segment load command (and @@ -731,7 +736,7 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, // Write the actual section data. for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { - Asm.WriteSectionData(it, Layout); + Asm.writeSectionData(it, Layout); uint64_t Pad = getPaddingSize(it, Layout); for (unsigned int i = 0; i < Pad; ++i) diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index 4d3b59c..4052374 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -850,7 +850,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, assert(OS.tell() == (*i)->Header.PointerToRawData && "Section::PointerToRawData is insane!"); - Asm.WriteSectionData(j, Layout); + Asm.writeSectionData(j, Layout); } if ((*i)->Relocations.size() > 0) { |