diff options
Diffstat (limited to 'tools')
30 files changed, 1348 insertions, 628 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 9b80ee5..6b7c884 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -44,6 +44,7 @@ add_subdirectory(llvm-mcmarkup) add_subdirectory(llvm-symbolizer) add_subdirectory(obj2yaml) +add_subdirectory(yaml2obj) if( NOT WIN32 ) add_subdirectory(lto) diff --git a/tools/Makefile b/tools/Makefile index b8f21d2..eaf9ed3 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -35,7 +35,7 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \ llvm-diff macho-dump llvm-objdump llvm-readobj \ llvm-rtdyld llvm-dwarfdump llvm-cov \ llvm-size llvm-stress llvm-mcmarkup \ - llvm-symbolizer obj2yaml + llvm-symbolizer obj2yaml yaml2obj # If Intel JIT Events support is configured, build an extra tool to test it. ifeq ($(USE_INTEL_JITEVENTS), 1) diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp index e49a96b..937d86a 100644 --- a/tools/bugpoint/BugDriver.cpp +++ b/tools/bugpoint/BugDriver.cpp @@ -122,7 +122,7 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) { outs() << "Read input file : '" << Filenames[0] << "'\n"; for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { - std::auto_ptr<Module> M(ParseInputFile(Filenames[i], Context)); + OwningPtr<Module> M(ParseInputFile(Filenames[i], Context)); if (M.get() == 0) return true; outs() << "Linking in input file: '" << Filenames[i] << "'\n"; diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 1dce9d7..8a462c6 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -200,7 +200,7 @@ int main(int argc, char **argv) { static int compileModule(char **argv, LLVMContext &Context) { // Load the module to be compiled... SMDiagnostic Err; - std::auto_ptr<Module> M; + OwningPtr<Module> M; Module *mod = 0; Triple TheTriple; @@ -281,7 +281,7 @@ static int compileModule(char **argv, LLVMContext &Context) { Options.UseInitArray = UseInitArray; Options.SSPBufferSize = SSPBufferSize; - std::auto_ptr<TargetMachine> + OwningPtr<TargetMachine> target(TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr, Options, RelocModel, CMModel, OLvl)); diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp index 273c427..d6f1919 100644 --- a/tools/llvm-as/llvm-as.cpp +++ b/tools/llvm-as/llvm-as.cpp @@ -94,7 +94,7 @@ int main(int argc, char **argv) { // Parse the file now... SMDiagnostic Err; - std::auto_ptr<Module> M(ParseAssemblyFile(InputFilename, Err, Context)); + OwningPtr<Module> M(ParseAssemblyFile(InputFilename, Err, Context)); if (M.get() == 0) { Err.print(argv[0], errs()); return 1; diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp index 2baa91d..067955e 100644 --- a/tools/llvm-dis/llvm-dis.cpp +++ b/tools/llvm-dis/llvm-dis.cpp @@ -123,7 +123,7 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n"); std::string ErrorMessage; - std::auto_ptr<Module> M; + OwningPtr<Module> M; // Use the bitcode streaming interface DataStreamer *streamer = getDataFileStreamer(InputFilename, &ErrorMessage); diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp index fd0a381..2f45b4e 100644 --- a/tools/llvm-extract/llvm-extract.cpp +++ b/tools/llvm-extract/llvm-extract.cpp @@ -100,7 +100,7 @@ int main(int argc, char **argv) { // Use lazy loading, since we only care about selected global values. SMDiagnostic Err; - std::auto_ptr<Module> M; + OwningPtr<Module> M; M.reset(getLazyIRFileModule(InputFilename, Err, Context)); if (M.get() == 0) { diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp index 83665cc..01a61c6 100644 --- a/tools/llvm-link/llvm-link.cpp +++ b/tools/llvm-link/llvm-link.cpp @@ -53,13 +53,12 @@ DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden); // LoadFile - Read the specified bitcode file in and return it. This routine // searches the link path for the specified file to try to find it... // -static inline std::auto_ptr<Module> LoadFile(const char *argv0, - const std::string &FN, - LLVMContext& Context) { +static inline Module *LoadFile(const char *argv0, const std::string &FN, + LLVMContext& Context) { sys::Path Filename; if (!Filename.set(FN)) { errs() << "Invalid file name: '" << FN << "'\n"; - return std::auto_ptr<Module>(); + return NULL; } SMDiagnostic Err; @@ -68,10 +67,10 @@ static inline std::auto_ptr<Module> LoadFile(const char *argv0, const std::string &FNStr = Filename.str(); Result = ParseIRFile(FNStr, Err, Context); - if (Result) return std::auto_ptr<Module>(Result); // Load successful! + if (Result) return Result; // Load successful! Err.print(argv0, errs()); - return std::auto_ptr<Module>(); + return NULL; } int main(int argc, char **argv) { @@ -86,17 +85,17 @@ int main(int argc, char **argv) { unsigned BaseArg = 0; std::string ErrorMessage; - std::auto_ptr<Module> Composite(LoadFile(argv[0], - InputFilenames[BaseArg], Context)); + OwningPtr<Module> Composite(LoadFile(argv[0], + InputFilenames[BaseArg], Context)); if (Composite.get() == 0) { errs() << argv[0] << ": error loading file '" << InputFilenames[BaseArg] << "'\n"; return 1; } + Linker L(Composite.get()); for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) { - std::auto_ptr<Module> M(LoadFile(argv[0], - InputFilenames[i], Context)); + OwningPtr<Module> M(LoadFile(argv[0], InputFilenames[i], Context)); if (M.get() == 0) { errs() << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n"; return 1; @@ -104,8 +103,7 @@ int main(int argc, char **argv) { if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n"; - if (Linker::LinkModules(Composite.get(), M.get(), Linker::DestroySource, - &ErrorMessage)) { + if (L.linkInModule(M.get(), &ErrorMessage)) { errs() << argv[0] << ": link error in '" << InputFilenames[i] << "': " << ErrorMessage << "\n"; return 1; diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 243899b..4b01c33 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -16,7 +16,6 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" @@ -27,7 +26,6 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCTargetAsmParser.h" -#include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/FormattedStream.h" @@ -40,7 +38,6 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/system_error.h" using namespace llvm; static cl::opt<std::string> diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index c324ff1..6797e2d 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -27,6 +27,7 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Object/MachO.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" @@ -52,27 +53,11 @@ static cl::opt<bool> static cl::opt<std::string> DSYMFile("dsym", cl::desc("Use .dSYM file for debug info")); -static const Target *GetTarget(const MachOObject *MachOObj) { +static const Target *GetTarget(const MachOObjectFile *MachOObj) { // Figure out the target triple. if (TripleName.empty()) { llvm::Triple TT("unknown-unknown-unknown"); - switch (MachOObj->getHeader().CPUType) { - case llvm::MachO::CPUTypeI386: - TT.setArch(Triple::ArchType(Triple::x86)); - break; - case llvm::MachO::CPUTypeX86_64: - TT.setArch(Triple::ArchType(Triple::x86_64)); - break; - case llvm::MachO::CPUTypeARM: - TT.setArch(Triple::ArchType(Triple::arm)); - break; - case llvm::MachO::CPUTypePowerPC: - TT.setArch(Triple::ArchType(Triple::ppc)); - break; - case llvm::MachO::CPUTypePowerPC64: - TT.setArch(Triple::ArchType(Triple::ppc64)); - break; - } + TT.setArch(Triple::ArchType(MachOObj->getArch())); TripleName = TT.str(); } @@ -108,7 +93,7 @@ struct SymbolSorter { // Print additional information about an address, if available. static void DumpAddress(uint64_t Address, ArrayRef<SectionRef> Sections, - MachOObject *MachOObj, raw_ostream &OS) { + const MachOObjectFile *MachOObj, raw_ostream &OS) { for (unsigned i = 0; i != Sections.size(); ++i) { uint64_t SectAddr = 0, SectSize = 0; Sections[i].getAddress(SectAddr); @@ -199,12 +184,12 @@ static void emitDOTFile(const char *FileName, const MCFunction &f, Out << "}\n"; } -static void getSectionsAndSymbols(const macho::Header &Header, - MachOObjectFile *MachOObj, - InMemoryStruct<macho::SymtabLoadCommand> *SymtabLC, - std::vector<SectionRef> &Sections, - std::vector<SymbolRef> &Symbols, - SmallVectorImpl<uint64_t> &FoundFns) { +static void +getSectionsAndSymbols(const macho::Header Header, + MachOObjectFile *MachOObj, + std::vector<SectionRef> &Sections, + std::vector<SymbolRef> &Symbols, + SmallVectorImpl<uint64_t> &FoundFns) { error_code ec; for (symbol_iterator SI = MachOObj->begin_symbols(), SE = MachOObj->end_symbols(); SI != SE; SI.increment(ec)) @@ -218,20 +203,28 @@ static void getSectionsAndSymbols(const macho::Header &Header, Sections.push_back(*SI); } - for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { - const MachOObject::LoadCommandInfo &LCI = - MachOObj->getObject()->getLoadCommandInfo(i); - if (LCI.Command.Type == macho::LCT_FunctionStarts) { + MachOObjectFile::LoadCommandInfo Command = + MachOObj->getFirstLoadCommandInfo(); + for (unsigned i = 0; ; ++i) { + if (Command.C.Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later // consumption. - InMemoryStruct<macho::LinkeditDataLoadCommand> LLC; - MachOObj->getObject()->ReadLinkeditDataLoadCommand(LCI, LLC); + macho::LinkeditDataLoadCommand LLC = + MachOObj->getLinkeditDataLoadCommand(Command); - MachOObj->getObject()->ReadULEB128s(LLC->DataOffset, FoundFns); + MachOObj->ReadULEB128s(LLC.DataOffset, FoundFns); } + + if (i == Header.NumLoadCommands - 1) + break; + else + Command = MachOObj->getNextLoadCommandInfo(Command); } } +static void DisassembleInputMachO2(StringRef Filename, + MachOObjectFile *MachOOF); + void llvm::DisassembleInputMachO(StringRef Filename) { OwningPtr<MemoryBuffer> Buff; @@ -242,9 +235,13 @@ void llvm::DisassembleInputMachO(StringRef Filename) { OwningPtr<MachOObjectFile> MachOOF(static_cast<MachOObjectFile*>( ObjectFile::createMachOObjectFile(Buff.take()))); - MachOObject *MachOObj = MachOOF->getObject(); - const Target *TheTarget = GetTarget(MachOObj); + DisassembleInputMachO2(Filename, MachOOF.get()); +} + +static void DisassembleInputMachO2(StringRef Filename, + MachOObjectFile *MachOOF) { + const Target *TheTarget = GetTarget(MachOOF); if (!TheTarget) { // GetTarget prints out stuff. return; @@ -272,31 +269,13 @@ void llvm::DisassembleInputMachO(StringRef Filename) { outs() << '\n' << Filename << ":\n\n"; - const macho::Header &Header = MachOObj->getHeader(); - - const MachOObject::LoadCommandInfo *SymtabLCI = 0; - // First, find the symbol table segment. - for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { - const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i); - if (LCI.Command.Type == macho::LCT_Symtab) { - SymtabLCI = &LCI; - break; - } - } - - // Read and register the symbol table data. - InMemoryStruct<macho::SymtabLoadCommand> SymtabLC; - if (SymtabLCI) { - MachOObj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC); - MachOObj->RegisterStringTable(*SymtabLC); - } + macho::Header Header = MachOOF->getHeader(); std::vector<SectionRef> Sections; std::vector<SymbolRef> Symbols; SmallVector<uint64_t, 8> FoundFns; - getSectionsAndSymbols(Header, MachOOF.get(), &SymtabLC, Sections, Symbols, - FoundFns); + getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns); // Make a copy of the unsorted symbol list. FIXME: duplication std::vector<SymbolRef> UnsortedSymbols(Symbols); @@ -310,7 +289,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { #endif OwningPtr<DIContext> diContext; - ObjectFile *DbgObj = MachOOF.get(); + ObjectFile *DbgObj = MachOOF; // Try to find debug info and set up the DIContext for it. if (UseDbg) { // A separate DSym file path was specified, parse it as a macho file, @@ -337,10 +316,9 @@ void llvm::DisassembleInputMachO(StringRef Filename) { SectName != "__text") continue; // Skip non-text sections - StringRef SegmentName; DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); - if (MachOOF->getSectionFinalSegmentName(DR, SegmentName) || - SegmentName != "__TEXT") + StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); + if (SegmentName != "__TEXT") continue; // Insert the functions from the function starts segment into our map. @@ -365,7 +343,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { for (relocation_iterator RI = Sections[SectIdx].begin_relocations(), RE = Sections[SectIdx].end_relocations(); RI != RE; RI.increment(ec)) { uint64_t RelocOffset, SectionAddress; - RI->getAddress(RelocOffset); + RI->getOffset(RelocOffset); Sections[SectIdx].getAddress(SectionAddress); RelocOffset -= SectionAddress; @@ -600,7 +578,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { Relocs[j].second.getName(SymName); outs() << "\t# " << SymName << ' '; - DumpAddress(Addr, Sections, MachOObj, outs()); + DumpAddress(Addr, Sections, MachOOF, outs()); } // If this instructions contains an address, see if we can evaluate @@ -609,7 +587,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { Inst.Address, Inst.Size); if (targ != -1ULL) - DumpAddress(targ, Sections, MachOObj, outs()); + DumpAddress(targ, Sections, MachOOF, outs()); // Print debug info. if (diContext) { diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 7832cf0..247b90f 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -186,8 +186,8 @@ void llvm::DumpBytes(StringRef bytes) { bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { uint64_t a_addr, b_addr; - if (error(a.getAddress(a_addr))) return false; - if (error(b.getAddress(b_addr))) return false; + if (error(a.getOffset(a_addr))) return false; + if (error(b.getOffset(b_addr))) return false; return a_addr < b_addr; } @@ -255,10 +255,10 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::sort(Rels.begin(), Rels.end(), RelocAddressLess); StringRef SegmentName = ""; - if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj)) { + if (const MachOObjectFile *MachO = + dyn_cast<const MachOObjectFile>(Obj)) { DataRefImpl DR = i->getRawDataRefImpl(); - if (error(MachO->getSectionFinalSegmentName(DR, SegmentName))) - break; + SegmentName = MachO->getSectionFinalSegmentName(DR); } StringRef name; if (error(i->getName(name))) break; @@ -378,7 +378,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { if (error(rel_cur->getHidden(hidden))) goto skip_print_rel; if (hidden) goto skip_print_rel; - if (error(rel_cur->getAddress(addr))) goto skip_print_rel; + if (error(rel_cur->getOffset(addr))) goto skip_print_rel; // Stop when rel_cur's address is past the current instruction. if (addr >= Index + Size) break; if (error(rel_cur->getTypeName(name))) goto skip_print_rel; @@ -417,7 +417,7 @@ static void PrintRelocations(const ObjectFile *o) { if (error(ri->getHidden(hidden))) continue; if (hidden) continue; if (error(ri->getTypeName(relocname))) continue; - if (error(ri->getAddress(address))) continue; + if (error(ri->getOffset(address))) continue; if (error(ri->getValueString(valuestr))) continue; outs() << address << " " << relocname << " " << valuestr << "\n"; } @@ -460,11 +460,19 @@ static void PrintSectionContents(const ObjectFile *o) { StringRef Name; StringRef Contents; uint64_t BaseAddr; + bool BSS; if (error(si->getName(Name))) continue; if (error(si->getContents(Contents))) continue; if (error(si->getAddress(BaseAddr))) continue; + if (error(si->isBSS(BSS))) continue; outs() << "Contents of section " << Name << ":\n"; + if (BSS) { + outs() << format("<skipping contents of bss section at [%04" PRIx64 + ", %04" PRIx64 ")>\n", BaseAddr, + BaseAddr + Contents.size()); + continue; + } // Dump out the content as hex and printable ascii characters. for (std::size_t addr = 0, end = Contents.size(); addr < end; addr += 16) { @@ -592,11 +600,10 @@ static void PrintSymbolTable(const ObjectFile *o) { else if (Section == o->end_sections()) outs() << "*UND*"; else { - if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(o)) { - StringRef SegmentName; + if (const MachOObjectFile *MachO = + dyn_cast<const MachOObjectFile>(o)) { DataRefImpl DR = Section->getRawDataRefImpl(); - if (error(MachO->getSectionFinalSegmentName(DR, SegmentName))) - SegmentName = ""; + StringRef SegmentName = MachO->getSectionFinalSegmentName(DR); outs() << SegmentName << ","; } StringRef SectionName; diff --git a/tools/llvm-ranlib/llvm-ranlib.cpp b/tools/llvm-ranlib/llvm-ranlib.cpp index fe9d3e2..e3e3bad 100644 --- a/tools/llvm-ranlib/llvm-ranlib.cpp +++ b/tools/llvm-ranlib/llvm-ranlib.cpp @@ -78,7 +78,7 @@ int main(int argc, char **argv) { } std::string err_msg; - std::auto_ptr<Archive> + OwningPtr<Archive> AutoArchive(Archive::OpenAndLoad(ArchivePath, Context, &err_msg)); Archive* TheArchive = AutoArchive.get(); if (!TheArchive) { diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index be4e76c..94aafa7 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -680,11 +680,18 @@ void COFFDumper::printRelocation(section_iterator SecI, if (error(Symbol.getName(SymbolName))) return; if (error(SecI->getContents(Contents))) return; - raw_ostream& OS = W.startLine(); - OS << W.hex(Offset) - << " " << RelocName - << " " << (SymbolName.size() > 0 ? SymbolName : "-") - << "\n"; + if (opts::ExpandRelocs) { + DictScope Group(W, "Relocation"); + W.printHex("Offset", Offset); + W.printNumber("Type", RelocName, RelocType); + W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); + } else { + raw_ostream& OS = W.startLine(); + OS << W.hex(Offset) + << " " << RelocName + << " " << (SymbolName.size() > 0 ? SymbolName : "-") + << "\n"; + } } void COFFDumper::printSymbols() { @@ -719,9 +726,9 @@ void COFFDumper::printSymbol(symbol_iterator SymI) { if (Obj->getSymbolName(Symbol, SymbolName)) SymbolName = ""; - StringRef SectionName; - if (Section && Obj->getSectionName(Section, SectionName)) - SectionName = ""; + StringRef SectionName = ""; + if (Section) + Obj->getSectionName(Section, SectionName); W.printString("Name", SymbolName); W.printNumber("Value", Symbol->Value); @@ -778,7 +785,12 @@ void COFFDumper::printSymbol(symbol_iterator SymI) { if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) break; - } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC) { + DictScope AS(W, "AuxFileRecord"); + W.printString("FileName", StringRef(Aux->FileName)); + + } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC || + (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + Symbol->SectionNumber != COFF::IMAGE_SYM_UNDEFINED)) { const coff_aux_section_definition *Aux; if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) break; @@ -792,7 +804,7 @@ void COFFDumper::printSymbol(symbol_iterator SymI) { W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect)); W.printBinary("Unused", makeArrayRef(Aux->Unused)); - if (Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT + if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { const coff_section *Assoc; StringRef AssocName; diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 9e111dd..ea1b83f 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -50,16 +50,18 @@ public: virtual void printDynamicTable() LLVM_OVERRIDE; virtual void printNeededLibraries() LLVM_OVERRIDE; + virtual void printProgramHeaders() LLVM_OVERRIDE; private: - typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr; - typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym; + typedef ELFObjectFile<ELFT> ELFO; + typedef typename ELFO::Elf_Shdr Elf_Shdr; + typedef typename ELFO::Elf_Sym Elf_Sym; void printSymbol(symbol_iterator SymI, bool IsDynamic = false); void printRelocation(section_iterator SecI, relocation_iterator RelI); - const ELFObjectFile<ELFT> *Obj; + const ELFO *Obj; }; } // namespace @@ -399,11 +401,37 @@ static const EnumEntry<unsigned> ElfSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP ) }; +static const EnumEntry<unsigned> ElfSegmentTypes[] = { + LLVM_READOBJ_ENUM_ENT(ELF, PT_NULL ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_LOAD ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_DYNAMIC), + LLVM_READOBJ_ENUM_ENT(ELF, PT_INTERP ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_NOTE ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_SHLIB ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_PHDR ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_TLS ), + + LLVM_READOBJ_ENUM_ENT(ELF, PT_GNU_EH_FRAME), + LLVM_READOBJ_ENUM_ENT(ELF, PT_SUNW_EH_FRAME), + LLVM_READOBJ_ENUM_ENT(ELF, PT_SUNW_UNWIND), + + LLVM_READOBJ_ENUM_ENT(ELF, PT_GNU_STACK), + LLVM_READOBJ_ENUM_ENT(ELF, PT_GNU_RELRO), + + LLVM_READOBJ_ENUM_ENT(ELF, PT_ARM_EXIDX), + LLVM_READOBJ_ENUM_ENT(ELF, PT_ARM_UNWIND) +}; + +static const EnumEntry<unsigned> ElfSegmentFlags[] = { + LLVM_READOBJ_ENUM_ENT(ELF, PF_X), + LLVM_READOBJ_ENUM_ENT(ELF, PF_W), + LLVM_READOBJ_ENUM_ENT(ELF, PF_R) +}; + template<class ELFT> void ELFDumper<ELFT>::printFileHeaders() { error_code EC; - typedef ELFObjectFile<ELFT> ELFO; const typename ELFO::Elf_Ehdr *Header = Obj->getElfHeader(); @@ -549,22 +577,36 @@ template<class ELFT> void ELFDumper<ELFT>::printRelocation(section_iterator Sec, relocation_iterator RelI) { uint64_t Offset; + uint64_t RelocType; SmallString<32> RelocName; int64_t Info; StringRef SymbolName; SymbolRef Symbol; - if (error(RelI->getOffset(Offset))) return; + if (Obj->getElfHeader()->e_type == ELF::ET_REL){ + if (error(RelI->getOffset(Offset))) return; + } else { + if (error(RelI->getAddress(Offset))) return; + } + if (error(RelI->getType(RelocType))) return; if (error(RelI->getTypeName(RelocName))) return; if (error(RelI->getAdditionalInfo(Info))) return; if (error(RelI->getSymbol(Symbol))) return; if (error(Symbol.getName(SymbolName))) return; - raw_ostream& OS = W.startLine(); - OS << W.hex(Offset) - << " " << RelocName - << " " << (SymbolName.size() > 0 ? SymbolName : "-") - << " " << W.hex(Info) - << "\n"; + if (opts::ExpandRelocs) { + DictScope Group(W, "Relocation"); + W.printHex("Offset", Offset); + W.printNumber("Type", RelocName, RelocType); + W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); + W.printHex("Info", Info); + } else { + raw_ostream& OS = W.startLine(); + OS << W.hex(Offset) + << " " << RelocName + << " " << (SymbolName.size() > 0 ? SymbolName : "-") + << " " << W.hex(Info) + << "\n"; + } } template<class ELFT> @@ -605,9 +647,9 @@ void ELFDumper<ELFT>::printSymbol(symbol_iterator SymI, bool IsDynamic) { if (SymI->getName(SymbolName)) SymbolName = ""; - StringRef SectionName; - if (Section && Obj->getSectionName(Section, SectionName)) - SectionName = ""; + StringRef SectionName = ""; + if (Section) + Obj->getSectionName(Section, SectionName); std::string FullSymbolName(SymbolName); if (IsDynamic) { @@ -735,7 +777,6 @@ void ELFDumper<ELFT>::printUnwindInfo() { template<class ELFT> void ELFDumper<ELFT>::printDynamicTable() { - typedef ELFObjectFile<ELFT> ELFO; typedef typename ELFO::Elf_Dyn_iterator EDI; EDI Start = Obj->begin_dynamic_table(), End = Obj->end_dynamic_table(true); @@ -798,3 +839,22 @@ void ELFDumper<ELFT>::printNeededLibraries() { outs() << " " << Path << "\n"; } } + +template<class ELFT> +void ELFDumper<ELFT>::printProgramHeaders() { + ListScope L(W, "ProgramHeaders"); + + for (typename ELFO::Elf_Phdr_Iter PI = Obj->begin_program_headers(), + PE = Obj->end_program_headers(); + PI != PE; ++PI) { + DictScope P(W, "ProgramHeader"); + W.printEnum ("Type", PI->p_type, makeArrayRef(ElfSegmentTypes)); + W.printHex ("Offset", PI->p_offset); + W.printHex ("VirtualAddress", PI->p_vaddr); + W.printHex ("PhysicalAddress", PI->p_paddr); + W.printNumber("FileSize", PI->p_filesz); + W.printNumber("MemSize", PI->p_memsz); + W.printFlags ("Flags", PI->p_flags, makeArrayRef(ElfSegmentFlags)); + W.printNumber("Alignment", PI->p_align); + } +} diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 798c941..31dc5ce 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -27,7 +27,7 @@ namespace { class MachODumper : public ObjDumper { public: - MachODumper(const llvm::object::MachOObjectFile *Obj, StreamWriter& Writer) + MachODumper(const MachOObjectFile *Obj, StreamWriter& Writer) : ObjDumper(Writer) , Obj(Obj) { } @@ -43,7 +43,12 @@ private: void printRelocation(section_iterator SecI, relocation_iterator RelI); - const llvm::object::MachOObjectFile *Obj; + void printRelocation(const MachOObjectFile *Obj, + section_iterator SecI, relocation_iterator RelI); + + void printSections(const MachOObjectFile *Obj); + + const MachOObjectFile *Obj; }; } // namespace @@ -157,97 +162,53 @@ namespace { }; } -static StringRef parseSegmentOrSectionName(ArrayRef<char> P) { - if (P[15] == 0) - // Null terminated. - return StringRef(P.data()); - // Not null terminated, so this is a 16 char string. - return StringRef(P.data(), 16); -} - -static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - if (LCI.Command.Type == macho::LCT_Segment64) - return true; - assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); - return false; -} - -static void getSection(const MachOObject *MachOObj, - DataRefImpl DRI, +static void getSection(const MachOObjectFile *Obj, + DataRefImpl Sec, MachOSection &Section) { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - if (is64BitLoadCommand(MachOObj, DRI)) { - InMemoryStruct<macho::Section64> Sect; - MachOObj->ReadSection64(LCI, DRI.d.b, Sect); - - Section.Name = ArrayRef<char>(Sect->Name); - Section.SegmentName = ArrayRef<char>(Sect->SegmentName); - Section.Address = Sect->Address; - Section.Size = Sect->Size; - Section.Offset = Sect->Offset; - Section.Alignment = Sect->Align; - Section.RelocationTableOffset = Sect->RelocationTableOffset; - Section.NumRelocationTableEntries = Sect->NumRelocationTableEntries; - Section.Flags = Sect->Flags; - Section.Reserved1 = Sect->Reserved1; - Section.Reserved2 = Sect->Reserved2; - } else { - InMemoryStruct<macho::Section> Sect; - MachOObj->ReadSection(LCI, DRI.d.b, Sect); - - Section.Name = Sect->Name; - Section.SegmentName = Sect->SegmentName; - Section.Address = Sect->Address; - Section.Size = Sect->Size; - Section.Offset = Sect->Offset; - Section.Alignment = Sect->Align; - Section.RelocationTableOffset = Sect->RelocationTableOffset; - Section.NumRelocationTableEntries = Sect->NumRelocationTableEntries; - Section.Flags = Sect->Flags; - Section.Reserved1 = Sect->Reserved1; - Section.Reserved2 = Sect->Reserved2; + if (!Obj->is64Bit()) { + macho::Section Sect = Obj->getSection(Sec); + Section.Address = Sect.Address; + Section.Size = Sect.Size; + Section.Offset = Sect.Offset; + Section.Alignment = Sect.Align; + Section.RelocationTableOffset = Sect.RelocationTableOffset; + Section.NumRelocationTableEntries = Sect.NumRelocationTableEntries; + Section.Flags = Sect.Flags; + Section.Reserved1 = Sect.Reserved1; + Section.Reserved2 = Sect.Reserved2; + return; } + macho::Section64 Sect = Obj->getSection64(Sec); + Section.Address = Sect.Address; + Section.Size = Sect.Size; + Section.Offset = Sect.Offset; + Section.Alignment = Sect.Align; + Section.RelocationTableOffset = Sect.RelocationTableOffset; + Section.NumRelocationTableEntries = Sect.NumRelocationTableEntries; + Section.Flags = Sect.Flags; + Section.Reserved1 = Sect.Reserved1; + Section.Reserved2 = Sect.Reserved2; } -static void getSymbolTableEntry(const MachOObject *MachO, - DataRefImpl DRI, - InMemoryStruct<macho::SymbolTableEntry> &Res) { - InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; - LoadCommandInfo LCI = MachO->getLoadCommandInfo(DRI.d.a); - MachO->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); - MachO->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, Res); -} -static void getSymbol64TableEntry(const MachOObject *MachO, - DataRefImpl DRI, - InMemoryStruct<macho::Symbol64TableEntry> &Res) { - InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; - LoadCommandInfo LCI = MachO->getLoadCommandInfo(DRI.d.a); - MachO->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); - MachO->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, Res); -} - -static void getSymbol(const MachOObject *MachOObj, +static void getSymbol(const MachOObjectFile *Obj, DataRefImpl DRI, MachOSymbol &Symbol) { - if (MachOObj->is64Bit()) { - InMemoryStruct<macho::Symbol64TableEntry> Entry; - getSymbol64TableEntry(MachOObj, DRI, Entry); - Symbol.StringIndex = Entry->StringIndex; - Symbol.Type = Entry->Type; - Symbol.SectionIndex = Entry->SectionIndex; - Symbol.Flags = Entry->Flags; - Symbol.Value = Entry->Value; - } else { - InMemoryStruct<macho::SymbolTableEntry> Entry; - getSymbolTableEntry(MachOObj, DRI, Entry); - Symbol.StringIndex = Entry->StringIndex; - Symbol.Type = Entry->Type; - Symbol.SectionIndex = Entry->SectionIndex; - Symbol.Flags = Entry->Flags; - Symbol.Value = Entry->Value; + if (!Obj->is64Bit()) { + macho::SymbolTableEntry Entry = Obj->getSymbolTableEntry(DRI); + Symbol.StringIndex = Entry.StringIndex; + Symbol.Type = Entry.Type; + Symbol.SectionIndex = Entry.SectionIndex; + Symbol.Flags = Entry.Flags; + Symbol.Value = Entry.Value; + return; } + macho::Symbol64TableEntry Entry = Obj->getSymbol64TableEntry(DRI); + Symbol.StringIndex = Entry.StringIndex; + Symbol.Type = Entry.Type; + Symbol.SectionIndex = Entry.SectionIndex; + Symbol.Flags = Entry.Flags; + Symbol.Value = Entry.Value; } void MachODumper::printFileHeaders() { @@ -255,6 +216,10 @@ void MachODumper::printFileHeaders() { } void MachODumper::printSections() { + return printSections(Obj); +} + +void MachODumper::printSections(const MachOObjectFile *Obj) { ListScope Group(W, "Sections"); int SectionIndex = -1; @@ -266,19 +231,22 @@ void MachODumper::printSections() { ++SectionIndex; - const MachOObject *MachO = const_cast<MachOObjectFile*>(Obj)->getObject(); - MachOSection Section; - getSection(MachO, SecI->getRawDataRefImpl(), Section); + getSection(Obj, SecI->getRawDataRefImpl(), Section); + DataRefImpl DR = SecI->getRawDataRefImpl(); + StringRef Name; if (error(SecI->getName(Name))) Name = ""; + ArrayRef<char> RawName = Obj->getSectionRawName(DR); + StringRef SegmentName = Obj->getSectionFinalSegmentName(DR); + ArrayRef<char> RawSegmentName = Obj->getSectionRawFinalSegmentName(DR); + DictScope SectionD(W, "Section"); W.printNumber("Index", SectionIndex); - W.printBinary("Name", Name, Section.Name); - W.printBinary("Segment", parseSegmentOrSectionName(Section.SegmentName), - Section.SegmentName); + W.printBinary("Name", Name, RawName); + W.printBinary("Segment", SegmentName, RawSegmentName); W.printHex ("Address", Section.Address); W.printHex ("Size", Section.Size); W.printNumber("Offset", Section.Offset); @@ -364,23 +332,53 @@ void MachODumper::printRelocations() { void MachODumper::printRelocation(section_iterator SecI, relocation_iterator RelI) { + return printRelocation(Obj, SecI, RelI); +} + +void MachODumper::printRelocation(const MachOObjectFile *Obj, + section_iterator SecI, + relocation_iterator RelI) { uint64_t Offset; SmallString<32> RelocName; - int64_t Info; StringRef SymbolName; SymbolRef Symbol; if (error(RelI->getOffset(Offset))) return; if (error(RelI->getTypeName(RelocName))) return; - if (error(RelI->getAdditionalInfo(Info))) return; if (error(RelI->getSymbol(Symbol))) return; - if (error(Symbol.getName(SymbolName))) return; - - raw_ostream& OS = W.startLine(); - OS << W.hex(Offset) - << " " << RelocName - << " " << (SymbolName.size() > 0 ? SymbolName : "-") - << " " << W.hex(Info) - << "\n"; + if (symbol_iterator(Symbol) != Obj->end_symbols() && + error(Symbol.getName(SymbolName))) + return; + + DataRefImpl DR = RelI->getRawDataRefImpl(); + macho::RelocationEntry RE = Obj->getRelocation(DR); + bool IsScattered = Obj->isRelocationScattered(RE); + + if (opts::ExpandRelocs) { + DictScope Group(W, "Relocation"); + W.printHex("Offset", Offset); + W.printNumber("PCRel", Obj->getAnyRelocationPCRel(RE)); + W.printNumber("Length", Obj->getAnyRelocationLength(RE)); + if (IsScattered) + W.printString("Extern", StringRef("N/A")); + else + W.printNumber("Extern", Obj->getPlainRelocationExternal(RE)); + W.printNumber("Type", RelocName, Obj->getAnyRelocationType(RE)); + W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); + W.printNumber("Scattered", IsScattered); + } else { + raw_ostream& OS = W.startLine(); + OS << W.hex(Offset) + << " " << Obj->getAnyRelocationPCRel(RE) + << " " << Obj->getAnyRelocationLength(RE); + if (IsScattered) + OS << " n/a"; + else + OS << " " << Obj->getPlainRelocationExternal(RE); + OS << " " << RelocName + << " " << IsScattered + << " " << (SymbolName.size() > 0 ? SymbolName : "-") + << "\n"; + } } void MachODumper::printSymbols() { @@ -407,16 +405,14 @@ void MachODumper::printSymbol(symbol_iterator SymI) { if (SymI->getName(SymbolName)) SymbolName = ""; - const MachOObject *MachO = const_cast<MachOObjectFile*>(Obj)->getObject(); - MachOSymbol Symbol; - getSymbol(MachO, SymI->getRawDataRefImpl(), Symbol); + getSymbol(Obj, SymI->getRawDataRefImpl(), Symbol); - StringRef SectionName; + StringRef SectionName = ""; section_iterator SecI(Obj->end_sections()); - if (error(SymI->getSection(SecI)) || - error(SecI->getName(SectionName))) - SectionName = ""; + if (!error(SymI->getSection(SecI)) && + SecI != Obj->end_sections()) + error(SecI->getName(SectionName)); DictScope D(W, "Symbol"); W.printNumber("Name", SymbolName, Symbol.StringIndex); diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index 8d191cb..6918e28 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -38,6 +38,7 @@ public: // Only implemented for ELF at this time. virtual void printDynamicTable() { } virtual void printNeededLibraries() { } + virtual void printProgramHeaders() { } protected: StreamWriter& W; diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index 67c9a98..2e95b6b 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -120,6 +120,14 @@ namespace opts { // -needed-libs cl::opt<bool> NeededLibraries("needed-libs", cl::desc("Display the needed libraries")); + + // -program-headers + cl::opt<bool> ProgramHeaders("program-headers", + cl::desc("Display ELF program headers")); + + // -expand-relocs + cl::opt<bool> ExpandRelocs("expand-relocs", + cl::desc("Expand each shown relocation to multiple lines")); } // namespace opts namespace llvm { @@ -135,8 +143,8 @@ bool error(error_code EC) { bool relocAddressLess(RelocationRef a, RelocationRef b) { uint64_t a_addr, b_addr; - if (error(a.getAddress(a_addr))) return false; - if (error(b.getAddress(b_addr))) return false; + if (error(a.getOffset(a_addr))) return false; + if (error(b.getOffset(b_addr))) return false; return a_addr < b_addr; } @@ -211,6 +219,8 @@ static void dumpObject(const ObjectFile *Obj) { Dumper->printDynamicTable(); if (opts::NeededLibraries) Dumper->printNeededLibraries(); + if (opts::ProgramHeaders) + Dumper->printProgramHeaders(); } diff --git a/tools/llvm-readobj/llvm-readobj.h b/tools/llvm-readobj/llvm-readobj.h index be18268..3f75610 100644 --- a/tools/llvm-readobj/llvm-readobj.h +++ b/tools/llvm-readobj/llvm-readobj.h @@ -37,6 +37,7 @@ namespace opts { extern llvm::cl::opt<bool> Symbols; extern llvm::cl::opt<bool> DynamicSymbols; extern llvm::cl::opt<bool> UnwindInfo; + extern llvm::cl::opt<bool> ExpandRelocs; } // namespace opts #define LLVM_READOBJ_ENUM_ENT(ns, enum) \ diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index 4d8d345..ead541a 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -17,7 +17,7 @@ #include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" -#include "llvm/Object/MachOObject.h" +#include "llvm/Object/MachO.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Memory.h" diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index e7c83f9..57e7a2d 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -69,7 +69,7 @@ const char* LTOCodeGenerator::getVersionString() { LTOCodeGenerator::LTOCodeGenerator() : _context(getGlobalContext()), - _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL), + _linker(new Module("ld-temp.o", _context)), _target(NULL), _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false), _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), _nativeObjectFile(NULL) { @@ -81,6 +81,7 @@ LTOCodeGenerator::LTOCodeGenerator() LTOCodeGenerator::~LTOCodeGenerator() { delete _target; delete _nativeObjectFile; + delete _linker.getModule(); for (std::vector<char*>::iterator I = _codegenOptions.begin(), E = _codegenOptions.end(); I != E; ++I) @@ -88,7 +89,7 @@ LTOCodeGenerator::~LTOCodeGenerator() { } bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { - bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg); + bool ret = _linker.linkInModule(mod->getLLVVMModule(), &errMsg); const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs(); for (int i = 0, e = undefs.size(); i != e; ++i) @@ -287,9 +288,7 @@ static void findUsedValues(GlobalVariable *LLVMUsed, SmallPtrSet<GlobalValue*, 8> &UsedValues) { if (LLVMUsed == 0) return; - ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer()); - if (Inits == 0) return; - + ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer()); for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) if (GlobalValue *GV = dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) @@ -326,24 +325,26 @@ void LTOCodeGenerator::applyScopeRestrictions() { if (LLVMCompilerUsed) LLVMCompilerUsed->eraseFromParent(); - llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context); - std::vector<Constant*> asmUsed2; - for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(), - e = asmUsed.end(); i !=e; ++i) { - GlobalValue *GV = *i; - Constant *c = ConstantExpr::getBitCast(GV, i8PTy); - asmUsed2.push_back(c); + if (!asmUsed.empty()) { + llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context); + std::vector<Constant*> asmUsed2; + for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(), + e = asmUsed.end(); i !=e; ++i) { + GlobalValue *GV = *i; + Constant *c = ConstantExpr::getBitCast(GV, i8PTy); + asmUsed2.push_back(c); + } + + llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size()); + LLVMCompilerUsed = + new llvm::GlobalVariable(*mergedModule, ATy, false, + llvm::GlobalValue::AppendingLinkage, + llvm::ConstantArray::get(ATy, asmUsed2), + "llvm.compiler.used"); + + LLVMCompilerUsed->setSection("llvm.metadata"); } - llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size()); - LLVMCompilerUsed = - new llvm::GlobalVariable(*mergedModule, ATy, false, - llvm::GlobalValue::AppendingLinkage, - llvm::ConstantArray::get(ATy, asmUsed2), - "llvm.compiler.used"); - - LLVMCompilerUsed->setSection("llvm.metadata"); - passes.add(createInternalizePass(mustPreserveList)); // apply scope restrictions diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h index 601dbfa..a4ade9f 100644 --- a/tools/lto/LTOCodeGenerator.h +++ b/tools/lto/LTOCodeGenerator.h @@ -19,6 +19,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/Linker.h" #include <string> +#include <vector> namespace llvm { class LLVMContext; diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index ff67769..d805f49 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -743,7 +743,7 @@ namespace { AddValueSymbols(Inst.getOperand(i).getExpr()); } virtual void EmitLabel(MCSymbol *Symbol) { - Symbol->setSection(*getCurrentSection()); + Symbol->setSection(*getCurrentSection().first); markDefined(*Symbol); } virtual void EmitDebugLabel(MCSymbol *Symbol) { @@ -771,7 +771,8 @@ namespace { virtual void EmitBundleUnlock() {} // Noop calls. - virtual void ChangeSection(const MCSection *Section) {} + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection) {} virtual void InitToTextSection() {} virtual void InitSections() {} virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp index 3bd3ecc..88fd452 100644 --- a/tools/macho-dump/macho-dump.cpp +++ b/tools/macho-dump/macho-dump.cpp @@ -11,9 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Object/MachOObject.h" +#include "llvm/Object/MachO.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" @@ -66,7 +67,8 @@ static void DumpSegmentCommandData(StringRef Name, outs() << " ('flags', " << Flags << ")\n"; } -static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name, +static int DumpSectionData(const MachOObjectFile &Obj, unsigned Index, + StringRef Name, StringRef SegmentName, uint64_t Address, uint64_t Size, uint32_t Offset, uint32_t Align, uint32_t RelocationTableOffset, @@ -92,26 +94,22 @@ static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name, outs() << " ),\n"; // Dump the relocation entries. - int Res = 0; outs() << " ('_relocations', [\n"; - for (unsigned i = 0; i != NumRelocationTableEntries; ++i) { - InMemoryStruct<macho::RelocationEntry> RE; - Obj.ReadRelocationEntry(RelocationTableOffset, i, RE); - if (!RE) { - Res = Error("unable to read relocation table entry '" + Twine(i) + "'"); - break; - } - - outs() << " # Relocation " << i << "\n"; - outs() << " (('word-0', " << format("0x%x", RE->Word0) << "),\n"; - outs() << " ('word-1', " << format("0x%x", RE->Word1) << ")),\n"; + unsigned RelNum = 0; + error_code EC; + for (relocation_iterator I = Obj.getSectionRelBegin(Index), + E = Obj.getSectionRelEnd(Index); I != E; I.increment(EC), ++RelNum) { + macho::RelocationEntry RE = Obj.getRelocation(I->getRawDataRefImpl()); + outs() << " # Relocation " << RelNum << "\n"; + outs() << " (('word-0', " << format("0x%x", RE.Word0) << "),\n"; + outs() << " ('word-1', " << format("0x%x", RE.Word1) << ")),\n"; } outs() << " ])\n"; // Dump the section data, if requested. if (ShowSectionData) { outs() << " ('_section_data', '"; - StringRef Data = Obj.getData(Offset, Size); + StringRef Data = Obj.getData().substr(Offset, Size); for (unsigned i = 0; i != Data.size(); ++i) { if (i && (i % 4) == 0) outs() << ' '; @@ -121,208 +119,162 @@ static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name, outs() << "')\n"; } - return Res; + return 0; } -static int DumpSegmentCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct<macho::SegmentLoadCommand> SLC; - Obj.ReadSegmentLoadCommand(LCI, SLC); - if (!SLC) - return Error("unable to read segment load command"); +static int DumpSegmentCommand(const MachOObjectFile &Obj, + const MachOObjectFile::LoadCommandInfo &LCI) { + macho::SegmentLoadCommand SLC = Obj.getSegmentLoadCommand(LCI); - DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, - SLC->VMSize, SLC->FileOffset, SLC->FileSize, - SLC->MaxVMProtection, SLC->InitialVMProtection, - SLC->NumSections, SLC->Flags); + DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress, + SLC.VMSize, SLC.FileOffset, SLC.FileSize, + SLC.MaxVMProtection, SLC.InitialVMProtection, + SLC.NumSections, SLC.Flags); // Dump the sections. - int Res = 0; outs() << " ('sections', [\n"; - for (unsigned i = 0; i != SLC->NumSections; ++i) { - InMemoryStruct<macho::Section> Sect; - Obj.ReadSection(LCI, i, Sect); - if (!SLC) { - Res = Error("unable to read section '" + Twine(i) + "'"); - break; - } - - if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16), - StringRef(Sect->SegmentName, 16), Sect->Address, - Sect->Size, Sect->Offset, Sect->Align, - Sect->RelocationTableOffset, - Sect->NumRelocationTableEntries, Sect->Flags, - Sect->Reserved1, Sect->Reserved2))) - break; + for (unsigned i = 0; i != SLC.NumSections; ++i) { + macho::Section Sect = Obj.getSection(LCI, i); + DumpSectionData(Obj, i, StringRef(Sect.Name, 16), + StringRef(Sect.SegmentName, 16), Sect.Address, + Sect.Size, Sect.Offset, Sect.Align, + Sect.RelocationTableOffset, + Sect.NumRelocationTableEntries, Sect.Flags, + Sect.Reserved1, Sect.Reserved2); } outs() << " ])\n"; - return Res; + return 0; } -static int DumpSegment64Command(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct<macho::Segment64LoadCommand> SLC; - Obj.ReadSegment64LoadCommand(LCI, SLC); - if (!SLC) - return Error("unable to read segment load command"); - - DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, - SLC->VMSize, SLC->FileOffset, SLC->FileSize, - SLC->MaxVMProtection, SLC->InitialVMProtection, - SLC->NumSections, SLC->Flags); +static int DumpSegment64Command(const MachOObjectFile &Obj, + const MachOObjectFile::LoadCommandInfo &LCI) { + macho::Segment64LoadCommand SLC = Obj.getSegment64LoadCommand(LCI); + DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress, + SLC.VMSize, SLC.FileOffset, SLC.FileSize, + SLC.MaxVMProtection, SLC.InitialVMProtection, + SLC.NumSections, SLC.Flags); // Dump the sections. - int Res = 0; outs() << " ('sections', [\n"; - for (unsigned i = 0; i != SLC->NumSections; ++i) { - InMemoryStruct<macho::Section64> Sect; - Obj.ReadSection64(LCI, i, Sect); - if (!SLC) { - Res = Error("unable to read section '" + Twine(i) + "'"); - break; - } - - if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16), - StringRef(Sect->SegmentName, 16), Sect->Address, - Sect->Size, Sect->Offset, Sect->Align, - Sect->RelocationTableOffset, - Sect->NumRelocationTableEntries, Sect->Flags, - Sect->Reserved1, Sect->Reserved2, - Sect->Reserved3))) - break; + for (unsigned i = 0; i != SLC.NumSections; ++i) { + macho::Section64 Sect = Obj.getSection64(LCI, i); + + DumpSectionData(Obj, i, StringRef(Sect.Name, 16), + StringRef(Sect.SegmentName, 16), Sect.Address, + Sect.Size, Sect.Offset, Sect.Align, + Sect.RelocationTableOffset, + Sect.NumRelocationTableEntries, Sect.Flags, + Sect.Reserved1, Sect.Reserved2, + Sect.Reserved3); } outs() << " ])\n"; - return Res; + return 0; } -static void DumpSymbolTableEntryData(MachOObject &Obj, +static void DumpSymbolTableEntryData(const MachOObjectFile &Obj, unsigned Index, uint32_t StringIndex, uint8_t Type, uint8_t SectionIndex, - uint16_t Flags, uint64_t Value) { + uint16_t Flags, uint64_t Value, + StringRef StringTable) { + const char *Name = &StringTable.data()[StringIndex]; outs() << " # Symbol " << Index << "\n"; outs() << " (('n_strx', " << StringIndex << ")\n"; outs() << " ('n_type', " << format("0x%x", Type) << ")\n"; outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n"; outs() << " ('n_desc', " << Flags << ")\n"; outs() << " ('n_value', " << Value << ")\n"; - outs() << " ('_string', '" << Obj.getStringAtIndex(StringIndex) << "')\n"; + outs() << " ('_string', '" << Name << "')\n"; outs() << " ),\n"; } -static int DumpSymtabCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct<macho::SymtabLoadCommand> SLC; - Obj.ReadSymtabLoadCommand(LCI, SLC); - if (!SLC) - return Error("unable to read segment load command"); - - outs() << " ('symoff', " << SLC->SymbolTableOffset << ")\n"; - outs() << " ('nsyms', " << SLC->NumSymbolTableEntries << ")\n"; - outs() << " ('stroff', " << SLC->StringTableOffset << ")\n"; - outs() << " ('strsize', " << SLC->StringTableSize << ")\n"; +static int DumpSymtabCommand(const MachOObjectFile &Obj) { + macho::SymtabLoadCommand SLC = Obj.getSymtabLoadCommand(); - // Cache the string table data. - Obj.RegisterStringTable(*SLC); + outs() << " ('symoff', " << SLC.SymbolTableOffset << ")\n"; + outs() << " ('nsyms', " << SLC.NumSymbolTableEntries << ")\n"; + outs() << " ('stroff', " << SLC.StringTableOffset << ")\n"; + outs() << " ('strsize', " << SLC.StringTableSize << ")\n"; // Dump the string data. outs() << " ('_string_data', '"; - outs().write_escaped(Obj.getStringTableData(), + StringRef StringTable = Obj.getStringTableData(); + outs().write_escaped(StringTable, /*UseHexEscapes=*/true) << "')\n"; // Dump the symbol table. - int Res = 0; outs() << " ('_symbols', [\n"; - for (unsigned i = 0; i != SLC->NumSymbolTableEntries; ++i) { + error_code EC; + unsigned SymNum = 0; + for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E; + I.increment(EC), ++SymNum) { + DataRefImpl DRI = I->getRawDataRefImpl(); if (Obj.is64Bit()) { - InMemoryStruct<macho::Symbol64TableEntry> STE; - Obj.ReadSymbol64TableEntry(SLC->SymbolTableOffset, i, STE); - if (!STE) { - Res = Error("unable to read symbol: '" + Twine(i) + "'"); - break; - } - - DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, - STE->SectionIndex, STE->Flags, STE->Value); + macho::Symbol64TableEntry STE = Obj.getSymbol64TableEntry(DRI); + DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type, + STE.SectionIndex, STE.Flags, STE.Value, + StringTable); } else { - InMemoryStruct<macho::SymbolTableEntry> STE; - Obj.ReadSymbolTableEntry(SLC->SymbolTableOffset, i, STE); - if (!SLC) { - Res = Error("unable to read symbol: '" + Twine(i) + "'"); - break; - } - - DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, - STE->SectionIndex, STE->Flags, STE->Value); + macho::SymbolTableEntry STE = Obj.getSymbolTableEntry(DRI); + DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type, + STE.SectionIndex, STE.Flags, STE.Value, + StringTable); } } outs() << " ])\n"; - return Res; + return 0; } -static int DumpDysymtabCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct<macho::DysymtabLoadCommand> DLC; - Obj.ReadDysymtabLoadCommand(LCI, DLC); - if (!DLC) - return Error("unable to read segment load command"); - - outs() << " ('ilocalsym', " << DLC->LocalSymbolsIndex << ")\n"; - outs() << " ('nlocalsym', " << DLC->NumLocalSymbols << ")\n"; - outs() << " ('iextdefsym', " << DLC->ExternalSymbolsIndex << ")\n"; - outs() << " ('nextdefsym', " << DLC->NumExternalSymbols << ")\n"; - outs() << " ('iundefsym', " << DLC->UndefinedSymbolsIndex << ")\n"; - outs() << " ('nundefsym', " << DLC->NumUndefinedSymbols << ")\n"; - outs() << " ('tocoff', " << DLC->TOCOffset << ")\n"; - outs() << " ('ntoc', " << DLC->NumTOCEntries << ")\n"; - outs() << " ('modtaboff', " << DLC->ModuleTableOffset << ")\n"; - outs() << " ('nmodtab', " << DLC->NumModuleTableEntries << ")\n"; - outs() << " ('extrefsymoff', " << DLC->ReferenceSymbolTableOffset << ")\n"; +static int DumpDysymtabCommand(const MachOObjectFile &Obj) { + macho::DysymtabLoadCommand DLC = Obj.getDysymtabLoadCommand(); + + outs() << " ('ilocalsym', " << DLC.LocalSymbolsIndex << ")\n"; + outs() << " ('nlocalsym', " << DLC.NumLocalSymbols << ")\n"; + outs() << " ('iextdefsym', " << DLC.ExternalSymbolsIndex << ")\n"; + outs() << " ('nextdefsym', " << DLC.NumExternalSymbols << ")\n"; + outs() << " ('iundefsym', " << DLC.UndefinedSymbolsIndex << ")\n"; + outs() << " ('nundefsym', " << DLC.NumUndefinedSymbols << ")\n"; + outs() << " ('tocoff', " << DLC.TOCOffset << ")\n"; + outs() << " ('ntoc', " << DLC.NumTOCEntries << ")\n"; + outs() << " ('modtaboff', " << DLC.ModuleTableOffset << ")\n"; + outs() << " ('nmodtab', " << DLC.NumModuleTableEntries << ")\n"; + outs() << " ('extrefsymoff', " << DLC.ReferenceSymbolTableOffset << ")\n"; outs() << " ('nextrefsyms', " - << DLC->NumReferencedSymbolTableEntries << ")\n"; - outs() << " ('indirectsymoff', " << DLC->IndirectSymbolTableOffset << ")\n"; + << DLC.NumReferencedSymbolTableEntries << ")\n"; + outs() << " ('indirectsymoff', " << DLC.IndirectSymbolTableOffset << ")\n"; outs() << " ('nindirectsyms', " - << DLC->NumIndirectSymbolTableEntries << ")\n"; - outs() << " ('extreloff', " << DLC->ExternalRelocationTableOffset << ")\n"; - outs() << " ('nextrel', " << DLC->NumExternalRelocationTableEntries << ")\n"; - outs() << " ('locreloff', " << DLC->LocalRelocationTableOffset << ")\n"; - outs() << " ('nlocrel', " << DLC->NumLocalRelocationTableEntries << ")\n"; + << DLC.NumIndirectSymbolTableEntries << ")\n"; + outs() << " ('extreloff', " << DLC.ExternalRelocationTableOffset << ")\n"; + outs() << " ('nextrel', " << DLC.NumExternalRelocationTableEntries << ")\n"; + outs() << " ('locreloff', " << DLC.LocalRelocationTableOffset << ")\n"; + outs() << " ('nlocrel', " << DLC.NumLocalRelocationTableEntries << ")\n"; // Dump the indirect symbol table. - int Res = 0; outs() << " ('_indirect_symbols', [\n"; - for (unsigned i = 0; i != DLC->NumIndirectSymbolTableEntries; ++i) { - InMemoryStruct<macho::IndirectSymbolTableEntry> ISTE; - Obj.ReadIndirectSymbolTableEntry(*DLC, i, ISTE); - if (!ISTE) { - Res = Error("unable to read segment load command"); - break; - } - + for (unsigned i = 0; i != DLC.NumIndirectSymbolTableEntries; ++i) { + macho::IndirectSymbolTableEntry ISTE = + Obj.getIndirectSymbolTableEntry(DLC, i); outs() << " # Indirect Symbol " << i << "\n"; outs() << " (('symbol_index', " - << format("0x%x", ISTE->Index) << "),),\n"; + << format("0x%x", ISTE.Index) << "),),\n"; } outs() << " ])\n"; - return Res; + return 0; } -static int DumpLinkeditDataCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct<macho::LinkeditDataLoadCommand> LLC; - Obj.ReadLinkeditDataLoadCommand(LCI, LLC); - if (!LLC) - return Error("unable to read segment load command"); - - outs() << " ('dataoff', " << LLC->DataOffset << ")\n" - << " ('datasize', " << LLC->DataSize << ")\n" +static int +DumpLinkeditDataCommand(const MachOObjectFile &Obj, + const MachOObjectFile::LoadCommandInfo &LCI) { + macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI); + outs() << " ('dataoff', " << LLC.DataOffset << ")\n" + << " ('datasize', " << LLC.DataSize << ")\n" << " ('_addresses', [\n"; SmallVector<uint64_t, 8> Addresses; - Obj.ReadULEB128s(LLC->DataOffset, Addresses); + Obj.ReadULEB128s(LLC.DataOffset, Addresses); for (unsigned i = 0, e = Addresses.size(); i != e; ++i) outs() << " # Address " << i << '\n' << " ('address', " << format("0x%x", Addresses[i]) << "),\n"; @@ -332,28 +284,22 @@ static int DumpLinkeditDataCommand(MachOObject &Obj, return 0; } -static int DumpDataInCodeDataCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct<macho::LinkeditDataLoadCommand> LLC; - Obj.ReadLinkeditDataLoadCommand(LCI, LLC); - if (!LLC) - return Error("unable to read data-in-code load command"); - - outs() << " ('dataoff', " << LLC->DataOffset << ")\n" - << " ('datasize', " << LLC->DataSize << ")\n" +static int +DumpDataInCodeDataCommand(const MachOObjectFile &Obj, + const MachOObjectFile::LoadCommandInfo &LCI) { + macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI); + outs() << " ('dataoff', " << LLC.DataOffset << ")\n" + << " ('datasize', " << LLC.DataSize << ")\n" << " ('_data_regions', [\n"; - - unsigned NumRegions = LLC->DataSize / 8; + unsigned NumRegions = LLC.DataSize / 8; for (unsigned i = 0; i < NumRegions; ++i) { - InMemoryStruct<macho::DataInCodeTableEntry> DICE; - Obj.ReadDataInCodeTableEntry(LLC->DataOffset, i, DICE); - if (!DICE) - return Error("unable to read DataInCodeTableEntry"); + macho::DataInCodeTableEntry DICE = + Obj.getDataInCodeTableEntry(LLC.DataOffset, i); outs() << " # DICE " << i << "\n" - << " ('offset', " << DICE->Offset << ")\n" - << " ('length', " << DICE->Length << ")\n" - << " ('kind', " << DICE->Kind << ")\n"; + << " ('offset', " << DICE.Offset << ")\n" + << " ('length', " << DICE.Length << ")\n" + << " ('kind', " << DICE.Kind << ")\n"; } outs() <<" ])\n"; @@ -361,99 +307,111 @@ static int DumpDataInCodeDataCommand(MachOObject &Obj, return 0; } -static int DumpLinkerOptionsCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct<macho::LinkerOptionsLoadCommand> LOLC; - Obj.ReadLinkerOptionsLoadCommand(LCI, LOLC); - if (!LOLC) - return Error("unable to read linker options load command"); - - outs() << " ('count', " << LOLC->Count << ")\n" - << " ('_strings', [\n"; - - uint64_t DataSize = LOLC->Size - sizeof(macho::LinkerOptionsLoadCommand); - StringRef Data = Obj.getData( - LCI.Offset + sizeof(macho::LinkerOptionsLoadCommand), DataSize); - for (unsigned i = 0; i != LOLC->Count; ++i) { - std::pair<StringRef,StringRef> Split = Data.split('\0'); - outs() << "\t\""; - outs().write_escaped(Split.first); - outs() << "\",\n"; - Data = Split.second; - } - outs() <<" ])\n"; +static int +DumpLinkerOptionsCommand(const MachOObjectFile &Obj, + const MachOObjectFile::LoadCommandInfo &LCI) { + macho::LinkerOptionsLoadCommand LOLC = Obj.getLinkerOptionsLoadCommand(LCI); + outs() << " ('count', " << LOLC.Count << ")\n" + << " ('_strings', [\n"; + + uint64_t DataSize = LOLC.Size - sizeof(macho::LinkerOptionsLoadCommand); + const char *P = LCI.Ptr + sizeof(macho::LinkerOptionsLoadCommand); + StringRef Data(P, DataSize); + for (unsigned i = 0; i != LOLC.Count; ++i) { + std::pair<StringRef,StringRef> Split = Data.split('\0'); + outs() << "\t\""; + outs().write_escaped(Split.first); + outs() << "\",\n"; + Data = Split.second; + } + outs() <<" ])\n"; return 0; } - -static int DumpLoadCommand(MachOObject &Obj, unsigned Index) { - const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index); - int Res = 0; - - outs() << " # Load Command " << Index << "\n" - << " (('command', " << LCI.Command.Type << ")\n" - << " ('size', " << LCI.Command.Size << ")\n"; - switch (LCI.Command.Type) { +static int DumpLoadCommand(const MachOObjectFile &Obj, + MachOObjectFile::LoadCommandInfo &LCI) { + switch (LCI.C.Type) { case macho::LCT_Segment: - Res = DumpSegmentCommand(Obj, LCI); - break; + return DumpSegmentCommand(Obj, LCI); case macho::LCT_Segment64: - Res = DumpSegment64Command(Obj, LCI); - break; + return DumpSegment64Command(Obj, LCI); case macho::LCT_Symtab: - Res = DumpSymtabCommand(Obj, LCI); - break; + return DumpSymtabCommand(Obj); case macho::LCT_Dysymtab: - Res = DumpDysymtabCommand(Obj, LCI); - break; + return DumpDysymtabCommand(Obj); case macho::LCT_CodeSignature: case macho::LCT_SegmentSplitInfo: case macho::LCT_FunctionStarts: - Res = DumpLinkeditDataCommand(Obj, LCI); - break; + return DumpLinkeditDataCommand(Obj, LCI); case macho::LCT_DataInCode: - Res = DumpDataInCodeDataCommand(Obj, LCI); - break; + return DumpDataInCodeDataCommand(Obj, LCI); case macho::LCT_LinkerOptions: - Res = DumpLinkerOptionsCommand(Obj, LCI); - break; + return DumpLinkerOptionsCommand(Obj, LCI); default: - Warning("unknown load command: " + Twine(LCI.Command.Type)); - break; + Warning("unknown load command: " + Twine(LCI.C.Type)); + return 0; } - outs() << " ),\n"; +} + +static int DumpLoadCommand(const MachOObjectFile &Obj, unsigned Index, + MachOObjectFile::LoadCommandInfo &LCI) { + outs() << " # Load Command " << Index << "\n" + << " (('command', " << LCI.C.Type << ")\n" + << " ('size', " << LCI.C.Size << ")\n"; + int Res = DumpLoadCommand(Obj, LCI); + outs() << " ),\n"; return Res; } +static void printHeader(const MachOObjectFile *Obj, + const macho::Header &Header) { + outs() << "('cputype', " << Header.CPUType << ")\n"; + outs() << "('cpusubtype', " << Header.CPUSubtype << ")\n"; + outs() << "('filetype', " << Header.FileType << ")\n"; + outs() << "('num_load_commands', " << Header.NumLoadCommands << ")\n"; + outs() << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n"; + outs() << "('flag', " << Header.Flags << ")\n"; + + // Print extended header if 64-bit. + if (Obj->is64Bit()) { + macho::Header64Ext Header64Ext = Obj->getHeader64Ext(); + outs() << "('reserved', " << Header64Ext.Reserved << ")\n"; + } +} + int main(int argc, char **argv) { ProgramName = argv[0]; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n"); - // Load the input file. - std::string ErrorStr; - OwningPtr<MemoryBuffer> InputBuffer; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer)) - return Error("unable to read input: '" + ec.message() + "'"); + OwningPtr<Binary> Binary; + if (error_code EC = createBinary(InputFile, Binary)) + return Error("unable to read input: '" + EC.message() + "'"); - // Construct the Mach-O wrapper object. - OwningPtr<MachOObject> InputObject( - MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr)); + const MachOObjectFile *InputObject = dyn_cast<MachOObjectFile>(Binary.get()); if (!InputObject) - return Error("unable to load object: '" + ErrorStr + "'"); + return Error("Not a MachO object"); // Print the header - InputObject->printHeader(outs()); + macho::Header Header = InputObject->getHeader(); + printHeader(InputObject, Header); // Print the load commands. int Res = 0; + MachOObjectFile::LoadCommandInfo Command = + InputObject->getFirstLoadCommandInfo(); outs() << "('load_commands', [\n"; - for (unsigned i = 0; i != InputObject->getHeader().NumLoadCommands; ++i) - if ((Res = DumpLoadCommand(*InputObject, i))) + for (unsigned i = 0; ; ++i) { + if (DumpLoadCommand(*InputObject, i, Command)) break; + + if (i == Header.NumLoadCommands - 1) + break; + Command = InputObject->getNextLoadCommandInfo(Command); + } outs() << "])\n"; return Res; diff --git a/tools/obj2yaml/coff2yaml.cpp b/tools/obj2yaml/coff2yaml.cpp index f0241d9..5106a4a 100644 --- a/tools/obj2yaml/coff2yaml.cpp +++ b/tools/obj2yaml/coff2yaml.cpp @@ -10,6 +10,7 @@ #include "obj2yaml.h" #include "llvm/Object/COFF.h" +using namespace llvm; template <typename One, typename Two> struct pod_pair { // I'd much rather use std::pair, but it's not a POD @@ -17,8 +18,8 @@ struct pod_pair { // I'd much rather use std::pair, but it's not a POD Two second; }; -#define STRING_PAIR(x) {llvm::COFF::x, #x} -static const pod_pair<llvm::COFF::MachineTypes, const char *> +#define STRING_PAIR(x) {COFF::x, #x} +static const pod_pair<COFF::MachineTypes, const char *> MachineTypePairs [] = { STRING_PAIR(IMAGE_FILE_MACHINE_UNKNOWN), STRING_PAIR(IMAGE_FILE_MACHINE_AM33), @@ -43,7 +44,7 @@ MachineTypePairs [] = { STRING_PAIR(IMAGE_FILE_MACHINE_WCEMIPSV2) }; -static const pod_pair<llvm::COFF::SectionCharacteristics, const char *> +static const pod_pair<COFF::SectionCharacteristics, const char *> SectionCharacteristicsPairs1 [] = { STRING_PAIR(IMAGE_SCN_TYPE_NO_PAD), STRING_PAIR(IMAGE_SCN_CNT_CODE), @@ -60,7 +61,7 @@ SectionCharacteristicsPairs1 [] = { STRING_PAIR(IMAGE_SCN_MEM_PRELOAD) }; -static const pod_pair<llvm::COFF::SectionCharacteristics, const char *> +static const pod_pair<COFF::SectionCharacteristics, const char *> SectionCharacteristicsPairsAlignment [] = { STRING_PAIR(IMAGE_SCN_ALIGN_1BYTES), STRING_PAIR(IMAGE_SCN_ALIGN_2BYTES), @@ -78,7 +79,7 @@ SectionCharacteristicsPairsAlignment [] = { STRING_PAIR(IMAGE_SCN_ALIGN_8192BYTES) }; -static const pod_pair<llvm::COFF::SectionCharacteristics, const char *> +static const pod_pair<COFF::SectionCharacteristics, const char *> SectionCharacteristicsPairs2 [] = { STRING_PAIR(IMAGE_SCN_LNK_NRELOC_OVFL), STRING_PAIR(IMAGE_SCN_MEM_DISCARDABLE), @@ -89,8 +90,8 @@ SectionCharacteristicsPairs2 [] = { STRING_PAIR(IMAGE_SCN_MEM_READ), STRING_PAIR(IMAGE_SCN_MEM_WRITE) }; - -static const pod_pair<llvm::COFF::SymbolBaseType, const char *> + +static const pod_pair<COFF::SymbolBaseType, const char *> SymbolBaseTypePairs [] = { STRING_PAIR(IMAGE_SYM_TYPE_NULL), STRING_PAIR(IMAGE_SYM_TYPE_VOID), @@ -110,15 +111,15 @@ SymbolBaseTypePairs [] = { STRING_PAIR(IMAGE_SYM_TYPE_DWORD) }; -static const pod_pair<llvm::COFF::SymbolComplexType, const char *> +static const pod_pair<COFF::SymbolComplexType, const char *> SymbolComplexTypePairs [] = { STRING_PAIR(IMAGE_SYM_DTYPE_NULL), STRING_PAIR(IMAGE_SYM_DTYPE_POINTER), STRING_PAIR(IMAGE_SYM_DTYPE_FUNCTION), STRING_PAIR(IMAGE_SYM_DTYPE_ARRAY), }; - -static const pod_pair<llvm::COFF::SymbolStorageClass, const char *> + +static const pod_pair<COFF::SymbolStorageClass, const char *> SymbolStorageClassPairs [] = { STRING_PAIR(IMAGE_SYM_CLASS_END_OF_FUNCTION), STRING_PAIR(IMAGE_SYM_CLASS_NULL), @@ -149,7 +150,7 @@ SymbolStorageClassPairs [] = { STRING_PAIR(IMAGE_SYM_CLASS_CLR_TOKEN), }; -static const pod_pair<llvm::COFF::RelocationTypeX86, const char *> +static const pod_pair<COFF::RelocationTypeX86, const char *> RelocationTypeX86Pairs [] = { STRING_PAIR(IMAGE_REL_I386_ABSOLUTE), STRING_PAIR(IMAGE_REL_I386_DIR16), @@ -181,7 +182,7 @@ RelocationTypeX86Pairs [] = { STRING_PAIR(IMAGE_REL_AMD64_SSPAN32) }; -static const pod_pair<llvm::COFF::RelocationTypesARM, const char *> +static const pod_pair<COFF::RelocationTypesARM, const char *> RelocationTypesARMPairs [] = { STRING_PAIR(IMAGE_REL_ARM_ABSOLUTE), STRING_PAIR(IMAGE_REL_ARM_ADDR32), @@ -201,13 +202,8 @@ RelocationTypesARMPairs [] = { }; #undef STRING_PAIR - -static const char endl = '\n'; - -namespace yaml { // COFF-specific yaml-writing specific routines - -static llvm::raw_ostream &writeName(llvm::raw_ostream &Out, - const char *Name, std::size_t NameSize) { +static raw_ostream &writeName(raw_ostream &Out, + const char *Name, std::size_t NameSize) { for (std::size_t i = 0; i < NameSize; ++i) { if (!Name[i]) break; Out << Name[i]; @@ -217,20 +213,19 @@ static llvm::raw_ostream &writeName(llvm::raw_ostream &Out, // Given an array of pod_pair<enum, const char *>, write all enums that match template <typename T, std::size_t N> -static llvm::raw_ostream &writeBitMask(llvm::raw_ostream &Out, - const pod_pair<T, const char *> (&Arr)[N], unsigned long Val) { +static raw_ostream &writeBitMask(raw_ostream &Out, + const pod_pair<T, const char *> (&Arr)[N], + unsigned long Val) { for (std::size_t i = 0; i < N; ++i) if (Val & Arr[i].first) Out << Arr[i].second << ", "; return Out; } -} // end of yaml namespace - // Given an array of pod_pair<enum, const char *>, look up a value template <typename T, std::size_t N> -const char *nameLookup(const pod_pair<T, const char *> (&Arr)[N], - unsigned long Val, const char *NotFound = NULL) { +const char *nameLookup(const pod_pair<T, const char *> (&Arr)[N], + unsigned long Val, const char *NotFound = NULL) { T n = static_cast<T>(Val); for (std::size_t i = 0; i < N; ++i) if (n == Arr[i].first) @@ -238,124 +233,122 @@ const char *nameLookup(const pod_pair<T, const char *> (&Arr)[N], return NotFound; } - -static llvm::raw_ostream &yamlCOFFHeader( - const llvm::object::coff_file_header *Header,llvm::raw_ostream &Out) { - - Out << "header: !Header" << endl; +static void yamlCOFFHeader(const object::coff_file_header *Header, + raw_ostream &Out) { + Out << "header: !Header\n"; Out << " Machine: "; Out << nameLookup(MachineTypePairs, Header->Machine, "# Unknown_MachineTypes") << " # ("; - return yaml::writeHexNumber(Out, Header->Machine) << ")" << endl << endl; + objyaml::writeHexNumber(Out, Header->Machine) << ")\n\n"; } -static llvm::raw_ostream &yamlCOFFSections(llvm::object::COFFObjectFile &Obj, - std::size_t NumSections, llvm::raw_ostream &Out) { - llvm::error_code ec; - Out << "sections:" << endl; - for (llvm::object::section_iterator iter = Obj.begin_sections(); - iter != Obj.end_sections(); iter.increment(ec)) { - const llvm::object::coff_section *sect = Obj.getCOFFSection(iter); - - Out << " - !Section" << endl; +static void yamlCOFFSections(object::COFFObjectFile &Obj, + std::size_t NumSections, raw_ostream &Out) { + error_code ec; + Out << "sections:\n"; + for (object::section_iterator iter = Obj.begin_sections(); + iter != Obj.end_sections(); iter.increment(ec)) { + const object::coff_section *sect = Obj.getCOFFSection(iter); + + Out << " - !Section\n"; Out << " Name: "; - yaml::writeName(Out, sect->Name, sizeof(sect->Name)) << endl; + writeName(Out, sect->Name, sizeof(sect->Name)) << '\n'; Out << " Characteristics: ["; - yaml::writeBitMask(Out, SectionCharacteristicsPairs1, sect->Characteristics); - Out << nameLookup(SectionCharacteristicsPairsAlignment, - sect->Characteristics & 0x00F00000, "# Unrecognized_IMAGE_SCN_ALIGN") + writeBitMask(Out, SectionCharacteristicsPairs1, sect->Characteristics); + Out << nameLookup(SectionCharacteristicsPairsAlignment, + sect->Characteristics & 0x00F00000, "# Unrecognized_IMAGE_SCN_ALIGN") << ", "; - yaml::writeBitMask(Out, SectionCharacteristicsPairs2, sect->Characteristics); + writeBitMask(Out, SectionCharacteristicsPairs2, sect->Characteristics); Out << "] # "; - yaml::writeHexNumber(Out, sect->Characteristics) << endl; + objyaml::writeHexNumber(Out, sect->Characteristics) << '\n'; - llvm::ArrayRef<uint8_t> sectionData; - Obj.getSectionContents(sect, sectionData); + ArrayRef<uint8_t> sectionData; + Obj.getSectionContents(sect, sectionData); Out << " SectionData: "; - yaml::writeHexStream(Out, sectionData) << endl; + objyaml::writeHexStream(Out, sectionData) << '\n'; if (iter->begin_relocations() != iter->end_relocations()) Out << " Relocations:\n"; - for (llvm::object::relocation_iterator rIter = iter->begin_relocations(); + for (object::relocation_iterator rIter = iter->begin_relocations(); rIter != iter->end_relocations(); rIter.increment(ec)) { - const llvm::object::coff_relocation *reloc = Obj.getCOFFRelocation(rIter); + const object::coff_relocation *reloc = Obj.getCOFFRelocation(rIter); - Out << " - !Relocation" << endl; + Out << " - !Relocation\n"; Out << " VirtualAddress: " ; - yaml::writeHexNumber(Out, reloc->VirtualAddress) << endl; - Out << " SymbolTableIndex: " << reloc->SymbolTableIndex << endl; - Out << " Type: " - << nameLookup(RelocationTypeX86Pairs, reloc->Type) << endl; + objyaml::writeHexNumber(Out, reloc->VirtualAddress) << '\n'; + Out << " SymbolTableIndex: " << reloc->SymbolTableIndex << '\n'; + Out << " Type: " + << nameLookup(RelocationTypeX86Pairs, reloc->Type) << '\n'; // TODO: Use the correct reloc type for the machine. - Out << endl; + Out << '\n'; } - } - return Out; + } } -static llvm::raw_ostream& yamlCOFFSymbols(llvm::object::COFFObjectFile &Obj, - std::size_t NumSymbols, llvm::raw_ostream &Out) { - llvm::error_code ec; - Out << "symbols:" << endl; - for (llvm::object::symbol_iterator iter = Obj.begin_symbols(); - iter != Obj.end_symbols(); iter.increment(ec)) { +static void yamlCOFFSymbols(object::COFFObjectFile &Obj, std::size_t NumSymbols, + raw_ostream &Out) { + error_code ec; + Out << "symbols:\n"; + for (object::symbol_iterator iter = Obj.begin_symbols(); + iter != Obj.end_symbols(); iter.increment(ec)) { // Gather all the info that we need - llvm::StringRef str; - const llvm::object::coff_symbol *symbol = Obj.getCOFFSymbol(iter); + StringRef str; + const object::coff_symbol *symbol = Obj.getCOFFSymbol(iter); Obj.getSymbolName(symbol, str); std::size_t simpleType = symbol->getBaseType(); std::size_t complexType = symbol->getComplexType(); std::size_t storageClass = symbol->StorageClass; - - Out << " - !Symbol" << endl; - Out << " Name: " << str << endl; - - Out << " Value: " << symbol->Value << endl; - Out << " SectionNumber: " << symbol->SectionNumber << endl; - - Out << " SimpleType: " - << nameLookup(SymbolBaseTypePairs, simpleType, - "# Unknown_SymbolBaseType") - << " # (" << simpleType << ")" << endl; - - Out << " ComplexType: " - << nameLookup(SymbolComplexTypePairs, complexType, - "# Unknown_SymbolComplexType") - << " # (" << complexType << ")" << endl; - - Out << " StorageClass: " + + Out << " - !Symbol\n"; + Out << " Name: " << str << '\n'; + + Out << " Value: " << symbol->Value << '\n'; + Out << " SectionNumber: " << symbol->SectionNumber << '\n'; + + Out << " SimpleType: " + << nameLookup(SymbolBaseTypePairs, simpleType, + "# Unknown_SymbolBaseType") + << " # (" << simpleType << ")\n"; + + Out << " ComplexType: " + << nameLookup(SymbolComplexTypePairs, complexType, + "# Unknown_SymbolComplexType") + << " # (" << complexType << ")\n"; + + Out << " StorageClass: " << nameLookup(SymbolStorageClassPairs, storageClass, - "# Unknown_StorageClass") - << " # (" << (int) storageClass << ")" << endl; + "# Unknown_StorageClass") + << " # (" << (int) storageClass << ")\n"; if (symbol->NumberOfAuxSymbols > 0) { - llvm::ArrayRef<uint8_t> aux = Obj.getSymbolAuxData(symbol); - Out << " NumberOfAuxSymbols: " - << (int) symbol->NumberOfAuxSymbols << endl; + ArrayRef<uint8_t> aux = Obj.getSymbolAuxData(symbol); + Out << " NumberOfAuxSymbols: " + << (int) symbol->NumberOfAuxSymbols << '\n'; Out << " AuxillaryData: "; - yaml::writeHexStream(Out, aux); + objyaml::writeHexStream(Out, aux); } - - Out << endl; - } - return Out; + Out << '\n'; + } } -llvm::error_code coff2yaml(llvm::raw_ostream &Out, llvm::MemoryBuffer *TheObj) { - llvm::error_code ec; - llvm::object::COFFObjectFile obj(TheObj, ec); - if (!ec) { - const llvm::object::coff_file_header *hd; - ec = obj.getHeader(hd); - if (!ec) { - yamlCOFFHeader(hd, Out); - yamlCOFFSections(obj, hd->NumberOfSections, Out); - yamlCOFFSymbols(obj, hd->NumberOfSymbols, Out); - } - } +error_code coff2yaml(raw_ostream &Out, MemoryBuffer *TheObj) { + error_code ec; + object::COFFObjectFile obj(TheObj, ec); + if (ec) + return ec; + + const object::coff_file_header *hd; + ec = obj.getHeader(hd); + if (ec) + return ec; + + yamlCOFFHeader(hd, Out); + yamlCOFFSections(obj, hd->NumberOfSections, Out); + yamlCOFFSymbols(obj, hd->NumberOfSymbols, Out); + return ec; } diff --git a/tools/obj2yaml/obj2yaml.cpp b/tools/obj2yaml/obj2yaml.cpp index bdc461a..821c9ac 100644 --- a/tools/obj2yaml/obj2yaml.cpp +++ b/tools/obj2yaml/obj2yaml.cpp @@ -16,20 +16,19 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" -const char endl = '\n'; +using namespace llvm; -namespace yaml { // generic yaml-writing specific routines +namespace objyaml { // generic yaml-writing specific routines unsigned char printable(unsigned char Ch) { return Ch >= ' ' && Ch <= '~' ? Ch : '.'; } - -llvm::raw_ostream &writeHexStream(llvm::raw_ostream &Out, - const llvm::ArrayRef<uint8_t> arr) { + +raw_ostream &writeHexStream(raw_ostream &Out, const ArrayRef<uint8_t> arr) { const char *hex = "0123456789ABCDEF"; Out << " !hex \""; - typedef llvm::ArrayRef<uint8_t>::const_iterator iter_t; + typedef ArrayRef<uint8_t>::const_iterator iter_t; const iter_t end = arr.end(); for (iter_t iter = arr.begin(); iter != end; ++iter) Out << hex[(*iter >> 4) & 0x0F] << hex[(*iter & 0x0F)]; @@ -37,49 +36,50 @@ llvm::raw_ostream &writeHexStream(llvm::raw_ostream &Out, Out << "\" # |"; for (iter_t iter = arr.begin(); iter != end; ++iter) Out << printable(*iter); - Out << "|" << endl; + Out << "|\n"; return Out; - } +} -llvm::raw_ostream &writeHexNumber(llvm::raw_ostream &Out, unsigned long long N) { +raw_ostream &writeHexNumber(raw_ostream &Out, unsigned long long N) { if (N >= 10) Out << "0x"; Out.write_hex(N); return Out; } +} // end namespace yaml + +namespace { +enum ObjectFileType { + coff +}; } +cl::opt<ObjectFileType> InputFormat( + cl::desc("Choose input format"), + cl::values(clEnumVal(coff, "process COFF object files"), clEnumValEnd)); -using namespace llvm; -enum ObjectFileType { coff }; +cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input file>"), + cl::init("-")); -cl::opt<ObjectFileType> InputFormat( - cl::desc("Choose input format"), - cl::values( - clEnumVal(coff, "process COFF object files"), - clEnumValEnd)); - -cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); - -int main(int argc, char * argv[]) { +int main(int argc, char *argv[]) { cl::ParseCommandLineOptions(argc, argv); sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); - llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. -// Process the input file + // Process the input file OwningPtr<MemoryBuffer> buf; -// TODO: If this is an archive, then burst it and dump each entry - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, buf)) - llvm::errs() << "Error: '" << ec.message() << "' opening file '" - << InputFilename << "'" << endl; - else { - ec = coff2yaml(llvm::outs(), buf.take()); + // TODO: If this is an archive, then burst it and dump each entry + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, buf)) { + errs() << "Error: '" << ec.message() << "' opening file '" << InputFilename + << "'\n"; + } else { + ec = coff2yaml(outs(), buf.take()); if (ec) - llvm::errs() << "Error: " << ec.message() << " dumping COFF file" << endl; + errs() << "Error: " << ec.message() << " dumping COFF file\n"; } return 0; diff --git a/tools/obj2yaml/obj2yaml.h b/tools/obj2yaml/obj2yaml.h index 0bc376a..7d52a2d 100644 --- a/tools/obj2yaml/obj2yaml.h +++ b/tools/obj2yaml/obj2yaml.h @@ -10,15 +10,15 @@ // source file, implement it. //===----------------------------------------------------------------------===// -#ifndef LLVM_UTILS_OBJ2YAML_H -#define LLVM_UTILS_OBJ2YAML_H +#ifndef LLVM_TOOLS_OBJ2YAML_H +#define LLVM_TOOLS_OBJ2YAML_H #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" -namespace yaml { // routines for writing YAML +namespace objyaml { // routines for writing YAML // Write a hex stream: // <Prefix> !hex: "<hex digits>" #|<ASCII chars>\n llvm::raw_ostream &writeHexStream diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index ba82bde..e385d7f5 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -589,7 +589,7 @@ int main(int argc, char **argv) { SMDiagnostic Err; // Load the input module... - std::auto_ptr<Module> M; + OwningPtr<Module> M; M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { @@ -656,7 +656,7 @@ int main(int argc, char **argv) { TargetMachine *Machine = 0; if (ModuleTriple.getArch()) Machine = GetTargetMachine(Triple(ModuleTriple)); - std::auto_ptr<TargetMachine> TM(Machine); + OwningPtr<TargetMachine> TM(Machine); // Add internal analysis passes from the target machine. if (TM.get()) diff --git a/tools/yaml2obj/CMakeLists.txt b/tools/yaml2obj/CMakeLists.txt new file mode 100644 index 0000000..f8b1197 --- /dev/null +++ b/tools/yaml2obj/CMakeLists.txt @@ -0,0 +1,5 @@ +add_llvm_utility(yaml2obj + yaml2obj.cpp + ) + +target_link_libraries(yaml2obj LLVMSupport) diff --git a/tools/yaml2obj/Makefile b/tools/yaml2obj/Makefile new file mode 100644 index 0000000..cb6f477 --- /dev/null +++ b/tools/yaml2obj/Makefile @@ -0,0 +1,20 @@ +##===- utils/yaml2obj/Makefile ----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = yaml2obj +LINK_COMPONENTS := support + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +# Don't install this utility +NO_INSTALL = 1 + +include $(LEVEL)/Makefile.common diff --git a/tools/yaml2obj/yaml2obj.cpp b/tools/yaml2obj/yaml2obj.cpp new file mode 100644 index 0000000..707b6b4 --- /dev/null +++ b/tools/yaml2obj/yaml2obj.cpp @@ -0,0 +1,680 @@ +//===- yaml2obj - Convert YAML to a binary object file --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This program takes a YAML description of an object file and outputs the +// binary equivalent. +// +// This is used for writing tests that require binary files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/COFF.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include <vector> + +using namespace llvm; + +static cl::opt<std::string> + Input(cl::Positional, cl::desc("<input>"), cl::init("-")); + +// The structure of the yaml files is not an exact 1:1 match to COFF. In order +// to use yaml::IO, we use these structures which are closer to the source. +namespace COFFYAML { + struct Section { + COFF::section Header; + unsigned Alignment; + StringRef SectionData; + std::vector<COFF::relocation> Relocations; + StringRef Name; + Section() { + memset(&Header, 0, sizeof(COFF::section)); + } + }; + + struct Symbol { + COFF::symbol Header; + COFF::SymbolBaseType SimpleType; + COFF::SymbolComplexType ComplexType; + StringRef AuxiliaryData; + StringRef Name; + Symbol() { + memset(&Header, 0, sizeof(COFF::symbol)); + } + }; + + struct Object { + COFF::header Header; + std::vector<Section> Sections; + std::vector<Symbol> Symbols; + Object() { + memset(&Header, 0, sizeof(COFF::header)); + } + }; +} + +/// This parses a yaml stream that represents a COFF object file. +/// See docs/yaml2obj for the yaml scheema. +struct COFFParser { + COFFParser(COFFYAML::Object &Obj) : Obj(Obj) { + // A COFF string table always starts with a 4 byte size field. Offsets into + // it include this size, so allocate it now. + StringTable.append(4, 0); + } + + bool parseSections() { + for (std::vector<COFFYAML::Section>::iterator i = Obj.Sections.begin(), + e = Obj.Sections.end(); i != e; ++i) { + COFFYAML::Section &Sec = *i; + + // If the name is less than 8 bytes, store it in place, otherwise + // store it in the string table. + StringRef Name = Sec.Name; + + if (Name.size() <= COFF::NameSize) { + std::copy(Name.begin(), Name.end(), Sec.Header.Name); + } else { + // Add string to the string table and format the index for output. + unsigned Index = getStringIndex(Name); + std::string str = utostr(Index); + if (str.size() > 7) { + errs() << "String table got too large"; + return false; + } + Sec.Header.Name[0] = '/'; + std::copy(str.begin(), str.end(), Sec.Header.Name + 1); + } + + Sec.Header.Characteristics |= (Log2_32(Sec.Alignment) + 1) << 20; + } + return true; + } + + bool parseSymbols() { + for (std::vector<COFFYAML::Symbol>::iterator i = Obj.Symbols.begin(), + e = Obj.Symbols.end(); i != e; ++i) { + COFFYAML::Symbol &Sym = *i; + + // If the name is less than 8 bytes, store it in place, otherwise + // store it in the string table. + StringRef Name = Sym.Name; + if (Name.size() <= COFF::NameSize) { + std::copy(Name.begin(), Name.end(), Sym.Header.Name); + } else { + // Add string to the string table and format the index for output. + unsigned Index = getStringIndex(Name); + *reinterpret_cast<support::aligned_ulittle32_t*>( + Sym.Header.Name + 4) = Index; + } + + Sym.Header.Type = Sym.SimpleType; + Sym.Header.Type |= Sym.ComplexType << COFF::SCT_COMPLEX_TYPE_SHIFT; + } + return true; + } + + bool parse() { + if (!parseSections()) + return false; + if (!parseSymbols()) + return false; + return true; + } + + unsigned getStringIndex(StringRef Str) { + StringMap<unsigned>::iterator i = StringTableMap.find(Str); + if (i == StringTableMap.end()) { + unsigned Index = StringTable.size(); + StringTable.append(Str.begin(), Str.end()); + StringTable.push_back(0); + StringTableMap[Str] = Index; + return Index; + } + return i->second; + } + + COFFYAML::Object &Obj; + + StringMap<unsigned> StringTableMap; + std::string StringTable; +}; + +// Take a CP and assign addresses and sizes to everything. Returns false if the +// layout is not valid to do. +static bool layoutCOFF(COFFParser &CP) { + uint32_t SectionTableStart = 0; + uint32_t SectionTableSize = 0; + + // The section table starts immediately after the header, including the + // optional header. + SectionTableStart = sizeof(COFF::header) + CP.Obj.Header.SizeOfOptionalHeader; + SectionTableSize = sizeof(COFF::section) * CP.Obj.Sections.size(); + + uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize; + + // Assign each section data address consecutively. + for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(), + e = CP.Obj.Sections.end(); + i != e; ++i) { + if (!i->SectionData.empty()) { + i->Header.SizeOfRawData = i->SectionData.size()/2; + i->Header.PointerToRawData = CurrentSectionDataOffset; + CurrentSectionDataOffset += i->Header.SizeOfRawData; + if (!i->Relocations.empty()) { + i->Header.PointerToRelocations = CurrentSectionDataOffset; + i->Header.NumberOfRelocations = i->Relocations.size(); + CurrentSectionDataOffset += i->Header.NumberOfRelocations * + COFF::RelocationSize; + } + // TODO: Handle alignment. + } else { + i->Header.SizeOfRawData = 0; + i->Header.PointerToRawData = 0; + } + } + + uint32_t SymbolTableStart = CurrentSectionDataOffset; + + // Calculate number of symbols. + uint32_t NumberOfSymbols = 0; + for (std::vector<COFFYAML::Symbol>::iterator i = CP.Obj.Symbols.begin(), + e = CP.Obj.Symbols.end(); + i != e; ++i) { + unsigned AuxBytes = i->AuxiliaryData.size() / 2; + if (AuxBytes % COFF::SymbolSize != 0) { + errs() << "AuxiliaryData size not a multiple of symbol size!\n"; + return false; + } + i->Header.NumberOfAuxSymbols = AuxBytes / COFF::SymbolSize; + NumberOfSymbols += 1 + i->Header.NumberOfAuxSymbols; + } + + // Store all the allocated start addresses in the header. + CP.Obj.Header.NumberOfSections = CP.Obj.Sections.size(); + CP.Obj.Header.NumberOfSymbols = NumberOfSymbols; + CP.Obj.Header.PointerToSymbolTable = SymbolTableStart; + + *reinterpret_cast<support::ulittle32_t *>(&CP.StringTable[0]) + = CP.StringTable.size(); + + return true; +} + +template <typename value_type> +struct binary_le_impl { + value_type Value; + binary_le_impl(value_type V) : Value(V) {} +}; + +template <typename value_type> +raw_ostream &operator <<( raw_ostream &OS + , const binary_le_impl<value_type> &BLE) { + char Buffer[sizeof(BLE.Value)]; + support::endian::write<value_type, support::little, support::unaligned>( + Buffer, BLE.Value); + OS.write(Buffer, sizeof(BLE.Value)); + return OS; +} + +template <typename value_type> +binary_le_impl<value_type> binary_le(value_type V) { + return binary_le_impl<value_type>(V); +} + +static bool writeHexData(StringRef Data, raw_ostream &OS) { + unsigned Size = Data.size(); + if (Size % 2) + return false; + + for (unsigned I = 0; I != Size; I += 2) { + uint8_t Byte; + if (Data.substr(I, 2).getAsInteger(16, Byte)) + return false; + OS.write(Byte); + } + + return true; +} + +bool writeCOFF(COFFParser &CP, raw_ostream &OS) { + OS << binary_le(CP.Obj.Header.Machine) + << binary_le(CP.Obj.Header.NumberOfSections) + << binary_le(CP.Obj.Header.TimeDateStamp) + << binary_le(CP.Obj.Header.PointerToSymbolTable) + << binary_le(CP.Obj.Header.NumberOfSymbols) + << binary_le(CP.Obj.Header.SizeOfOptionalHeader) + << binary_le(CP.Obj.Header.Characteristics); + + // Output section table. + for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(), + e = CP.Obj.Sections.end(); + i != e; ++i) { + OS.write(i->Header.Name, COFF::NameSize); + OS << binary_le(i->Header.VirtualSize) + << binary_le(i->Header.VirtualAddress) + << binary_le(i->Header.SizeOfRawData) + << binary_le(i->Header.PointerToRawData) + << binary_le(i->Header.PointerToRelocations) + << binary_le(i->Header.PointerToLineNumbers) + << binary_le(i->Header.NumberOfRelocations) + << binary_le(i->Header.NumberOfLineNumbers) + << binary_le(i->Header.Characteristics); + } + + // Output section data. + for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(), + e = CP.Obj.Sections.end(); + i != e; ++i) { + if (!i->SectionData.empty()) { + if (!writeHexData(i->SectionData, OS)) { + errs() << "SectionData must be a collection of pairs of hex bytes"; + return false; + } + } + for (unsigned I2 = 0, E2 = i->Relocations.size(); I2 != E2; ++I2) { + const COFF::relocation &R = i->Relocations[I2]; + OS << binary_le(R.VirtualAddress) + << binary_le(R.SymbolTableIndex) + << binary_le(R.Type); + } + } + + // Output symbol table. + + for (std::vector<COFFYAML::Symbol>::const_iterator i = CP.Obj.Symbols.begin(), + e = CP.Obj.Symbols.end(); + i != e; ++i) { + OS.write(i->Header.Name, COFF::NameSize); + OS << binary_le(i->Header.Value) + << binary_le(i->Header.SectionNumber) + << binary_le(i->Header.Type) + << binary_le(i->Header.StorageClass) + << binary_le(i->Header.NumberOfAuxSymbols); + if (!i->AuxiliaryData.empty()) { + if (!writeHexData(i->AuxiliaryData, OS)) { + errs() << "AuxiliaryData must be a collection of pairs of hex bytes"; + return false; + } + } + } + + // Output string table. + OS.write(&CP.StringTable[0], CP.StringTable.size()); + return true; +} + +LLVM_YAML_IS_SEQUENCE_VECTOR(COFF::relocation) +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Section) +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Symbol) + +namespace llvm { + +namespace COFF { + Characteristics operator|(Characteristics a, Characteristics b) { + uint32_t Ret = static_cast<uint32_t>(a) | static_cast<uint32_t>(b); + return static_cast<Characteristics>(Ret); + } + + SectionCharacteristics + operator|(SectionCharacteristics a, SectionCharacteristics b) { + uint32_t Ret = static_cast<uint32_t>(a) | static_cast<uint32_t>(b); + return static_cast<SectionCharacteristics>(Ret); + } +} + +namespace yaml { + +#define BCase(X) IO.bitSetCase(Value, #X, COFF::X); + +template <> +struct ScalarBitSetTraits<COFF::SectionCharacteristics> { + static void bitset(IO &IO, COFF::SectionCharacteristics &Value) { + BCase(IMAGE_SCN_TYPE_NO_PAD); + BCase(IMAGE_SCN_CNT_CODE); + BCase(IMAGE_SCN_CNT_INITIALIZED_DATA); + BCase(IMAGE_SCN_CNT_UNINITIALIZED_DATA); + BCase(IMAGE_SCN_LNK_OTHER); + BCase(IMAGE_SCN_LNK_INFO); + BCase(IMAGE_SCN_LNK_REMOVE); + BCase(IMAGE_SCN_LNK_COMDAT); + BCase(IMAGE_SCN_GPREL); + BCase(IMAGE_SCN_MEM_PURGEABLE); + BCase(IMAGE_SCN_MEM_16BIT); + BCase(IMAGE_SCN_MEM_LOCKED); + BCase(IMAGE_SCN_MEM_PRELOAD); + BCase(IMAGE_SCN_LNK_NRELOC_OVFL); + BCase(IMAGE_SCN_MEM_DISCARDABLE); + BCase(IMAGE_SCN_MEM_NOT_CACHED); + BCase(IMAGE_SCN_MEM_NOT_PAGED); + BCase(IMAGE_SCN_MEM_SHARED); + BCase(IMAGE_SCN_MEM_EXECUTE); + BCase(IMAGE_SCN_MEM_READ); + BCase(IMAGE_SCN_MEM_WRITE); + } +}; + +template <> +struct ScalarBitSetTraits<COFF::Characteristics> { + static void bitset(IO &IO, COFF::Characteristics &Value) { + BCase(IMAGE_FILE_RELOCS_STRIPPED); + BCase(IMAGE_FILE_EXECUTABLE_IMAGE); + BCase(IMAGE_FILE_LINE_NUMS_STRIPPED); + BCase(IMAGE_FILE_LOCAL_SYMS_STRIPPED); + BCase(IMAGE_FILE_AGGRESSIVE_WS_TRIM); + BCase(IMAGE_FILE_LARGE_ADDRESS_AWARE); + BCase(IMAGE_FILE_BYTES_REVERSED_LO); + BCase(IMAGE_FILE_32BIT_MACHINE); + BCase(IMAGE_FILE_DEBUG_STRIPPED); + BCase(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP); + BCase(IMAGE_FILE_NET_RUN_FROM_SWAP); + BCase(IMAGE_FILE_SYSTEM); + BCase(IMAGE_FILE_DLL); + BCase(IMAGE_FILE_UP_SYSTEM_ONLY); + BCase(IMAGE_FILE_BYTES_REVERSED_HI); + } +}; +#undef BCase + +#define ECase(X) IO.enumCase(Value, #X, COFF::X); + +template <> +struct ScalarEnumerationTraits<COFF::SymbolComplexType> { + static void enumeration(IO &IO, COFF::SymbolComplexType &Value) { + ECase(IMAGE_SYM_DTYPE_NULL); + ECase(IMAGE_SYM_DTYPE_POINTER); + ECase(IMAGE_SYM_DTYPE_FUNCTION); + ECase(IMAGE_SYM_DTYPE_ARRAY); + } +}; + +template <> +struct ScalarEnumerationTraits<COFF::SymbolStorageClass> { + static void enumeration(IO &IO, COFF::SymbolStorageClass &Value) { + ECase(IMAGE_SYM_CLASS_END_OF_FUNCTION); + ECase(IMAGE_SYM_CLASS_NULL); + ECase(IMAGE_SYM_CLASS_AUTOMATIC); + ECase(IMAGE_SYM_CLASS_EXTERNAL); + ECase(IMAGE_SYM_CLASS_STATIC); + ECase(IMAGE_SYM_CLASS_REGISTER); + ECase(IMAGE_SYM_CLASS_EXTERNAL_DEF); + ECase(IMAGE_SYM_CLASS_LABEL); + ECase(IMAGE_SYM_CLASS_UNDEFINED_LABEL); + ECase(IMAGE_SYM_CLASS_MEMBER_OF_STRUCT); + ECase(IMAGE_SYM_CLASS_ARGUMENT); + ECase(IMAGE_SYM_CLASS_STRUCT_TAG); + ECase(IMAGE_SYM_CLASS_MEMBER_OF_UNION); + ECase(IMAGE_SYM_CLASS_UNION_TAG); + ECase(IMAGE_SYM_CLASS_TYPE_DEFINITION); + ECase(IMAGE_SYM_CLASS_UNDEFINED_STATIC); + ECase(IMAGE_SYM_CLASS_ENUM_TAG); + ECase(IMAGE_SYM_CLASS_MEMBER_OF_ENUM); + ECase(IMAGE_SYM_CLASS_REGISTER_PARAM); + ECase(IMAGE_SYM_CLASS_BIT_FIELD); + ECase(IMAGE_SYM_CLASS_BLOCK); + ECase(IMAGE_SYM_CLASS_FUNCTION); + ECase(IMAGE_SYM_CLASS_END_OF_STRUCT); + ECase(IMAGE_SYM_CLASS_FILE); + ECase(IMAGE_SYM_CLASS_SECTION); + ECase(IMAGE_SYM_CLASS_WEAK_EXTERNAL); + ECase(IMAGE_SYM_CLASS_CLR_TOKEN); + } +}; + +template <> +struct ScalarEnumerationTraits<COFF::SymbolBaseType> { + static void enumeration(IO &IO, COFF::SymbolBaseType &Value) { + ECase(IMAGE_SYM_TYPE_NULL); + ECase(IMAGE_SYM_TYPE_VOID); + ECase(IMAGE_SYM_TYPE_CHAR); + ECase(IMAGE_SYM_TYPE_SHORT); + ECase(IMAGE_SYM_TYPE_INT); + ECase(IMAGE_SYM_TYPE_LONG); + ECase(IMAGE_SYM_TYPE_FLOAT); + ECase(IMAGE_SYM_TYPE_DOUBLE); + ECase(IMAGE_SYM_TYPE_STRUCT); + ECase(IMAGE_SYM_TYPE_UNION); + ECase(IMAGE_SYM_TYPE_ENUM); + ECase(IMAGE_SYM_TYPE_MOE); + ECase(IMAGE_SYM_TYPE_BYTE); + ECase(IMAGE_SYM_TYPE_WORD); + ECase(IMAGE_SYM_TYPE_UINT); + ECase(IMAGE_SYM_TYPE_DWORD); + } +}; + +template <> +struct ScalarEnumerationTraits<COFF::MachineTypes> { + static void enumeration(IO &IO, COFF::MachineTypes &Value) { + ECase(IMAGE_FILE_MACHINE_UNKNOWN); + ECase(IMAGE_FILE_MACHINE_AM33); + ECase(IMAGE_FILE_MACHINE_AMD64); + ECase(IMAGE_FILE_MACHINE_ARM); + ECase(IMAGE_FILE_MACHINE_ARMV7); + ECase(IMAGE_FILE_MACHINE_EBC); + ECase(IMAGE_FILE_MACHINE_I386); + ECase(IMAGE_FILE_MACHINE_IA64); + ECase(IMAGE_FILE_MACHINE_M32R); + ECase(IMAGE_FILE_MACHINE_MIPS16); + ECase(IMAGE_FILE_MACHINE_MIPSFPU); + ECase(IMAGE_FILE_MACHINE_MIPSFPU16); + ECase(IMAGE_FILE_MACHINE_POWERPC); + ECase(IMAGE_FILE_MACHINE_POWERPCFP); + ECase(IMAGE_FILE_MACHINE_R4000); + ECase(IMAGE_FILE_MACHINE_SH3); + ECase(IMAGE_FILE_MACHINE_SH3DSP); + ECase(IMAGE_FILE_MACHINE_SH4); + ECase(IMAGE_FILE_MACHINE_SH5); + ECase(IMAGE_FILE_MACHINE_THUMB); + ECase(IMAGE_FILE_MACHINE_WCEMIPSV2); + } +}; + +template <> +struct ScalarEnumerationTraits<COFF::RelocationTypeX86> { + static void enumeration(IO &IO, COFF::RelocationTypeX86 &Value) { + ECase(IMAGE_REL_I386_ABSOLUTE); + ECase(IMAGE_REL_I386_DIR16); + ECase(IMAGE_REL_I386_REL16); + ECase(IMAGE_REL_I386_DIR32); + ECase(IMAGE_REL_I386_DIR32NB); + ECase(IMAGE_REL_I386_SEG12); + ECase(IMAGE_REL_I386_SECTION); + ECase(IMAGE_REL_I386_SECREL); + ECase(IMAGE_REL_I386_TOKEN); + ECase(IMAGE_REL_I386_SECREL7); + ECase(IMAGE_REL_I386_REL32); + ECase(IMAGE_REL_AMD64_ABSOLUTE); + ECase(IMAGE_REL_AMD64_ADDR64); + ECase(IMAGE_REL_AMD64_ADDR32); + ECase(IMAGE_REL_AMD64_ADDR32NB); + ECase(IMAGE_REL_AMD64_REL32); + ECase(IMAGE_REL_AMD64_REL32_1); + ECase(IMAGE_REL_AMD64_REL32_2); + ECase(IMAGE_REL_AMD64_REL32_3); + ECase(IMAGE_REL_AMD64_REL32_4); + ECase(IMAGE_REL_AMD64_REL32_5); + ECase(IMAGE_REL_AMD64_SECTION); + ECase(IMAGE_REL_AMD64_SECREL); + ECase(IMAGE_REL_AMD64_SECREL7); + ECase(IMAGE_REL_AMD64_TOKEN); + ECase(IMAGE_REL_AMD64_SREL32); + ECase(IMAGE_REL_AMD64_PAIR); + ECase(IMAGE_REL_AMD64_SSPAN32); + } +}; + +#undef ECase + +template <> +struct MappingTraits<COFFYAML::Symbol> { + struct NStorageClass { + NStorageClass(IO&) : StorageClass(COFF::SymbolStorageClass(0)) { + } + NStorageClass(IO&, uint8_t S) : StorageClass(COFF::SymbolStorageClass(S)) { + } + uint8_t denormalize(IO &) { + return StorageClass; + } + + COFF::SymbolStorageClass StorageClass; + }; + + static void mapping(IO &IO, COFFYAML::Symbol &S) { + MappingNormalization<NStorageClass, uint8_t> NS(IO, S.Header.StorageClass); + + IO.mapRequired("SimpleType", S.SimpleType); + IO.mapOptional("NumberOfAuxSymbols", S.Header.NumberOfAuxSymbols); + IO.mapRequired("Name", S.Name); + IO.mapRequired("StorageClass", NS->StorageClass); + IO.mapOptional("AuxiliaryData", S.AuxiliaryData); + IO.mapRequired("ComplexType", S.ComplexType); + IO.mapRequired("Value", S.Header.Value); + IO.mapRequired("SectionNumber", S.Header.SectionNumber); + } +}; + +template <> +struct MappingTraits<COFF::header> { + struct NMachine { + NMachine(IO&) : Machine(COFF::MachineTypes(0)) { + } + NMachine(IO&, uint16_t M) : Machine(COFF::MachineTypes(M)) { + } + uint16_t denormalize(IO &) { + return Machine; + } + COFF::MachineTypes Machine; + }; + + struct NCharacteristics { + NCharacteristics(IO&) : Characteristics(COFF::Characteristics(0)) { + } + NCharacteristics(IO&, uint16_t C) : + Characteristics(COFF::Characteristics(C)) { + } + uint16_t denormalize(IO &) { + return Characteristics; + } + + COFF::Characteristics Characteristics; + }; + + static void mapping(IO &IO, COFF::header &H) { + MappingNormalization<NMachine, uint16_t> NM(IO, H.Machine); + MappingNormalization<NCharacteristics, uint16_t> NC(IO, H.Characteristics); + + IO.mapRequired("Machine", NM->Machine); + IO.mapOptional("Characteristics", NC->Characteristics); + } +}; + +template <> +struct MappingTraits<COFF::relocation> { + struct NType { + NType(IO &) : Type(COFF::RelocationTypeX86(0)) { + } + NType(IO &, uint16_t T) : Type(COFF::RelocationTypeX86(T)) { + } + uint16_t denormalize(IO &) { + return Type; + } + COFF::RelocationTypeX86 Type; + }; + + static void mapping(IO &IO, COFF::relocation &Rel) { + MappingNormalization<NType, uint16_t> NT(IO, Rel.Type); + + IO.mapRequired("Type", NT->Type); + IO.mapRequired("VirtualAddress", Rel.VirtualAddress); + IO.mapRequired("SymbolTableIndex", Rel.SymbolTableIndex); + } +}; + +template <> +struct MappingTraits<COFFYAML::Section> { + struct NCharacteristics { + NCharacteristics(IO &) : Characteristics(COFF::SectionCharacteristics(0)) { + } + NCharacteristics(IO &, uint32_t C) : + Characteristics(COFF::SectionCharacteristics(C)) { + } + uint32_t denormalize(IO &) { + return Characteristics; + } + COFF::SectionCharacteristics Characteristics; + }; + + static void mapping(IO &IO, COFFYAML::Section &Sec) { + MappingNormalization<NCharacteristics, uint32_t> NC(IO, + Sec.Header.Characteristics); + IO.mapOptional("Relocations", Sec.Relocations); + IO.mapRequired("SectionData", Sec.SectionData); + IO.mapRequired("Characteristics", NC->Characteristics); + IO.mapRequired("Name", Sec.Name); + IO.mapOptional("Alignment", Sec.Alignment); + } +}; + +template <> +struct MappingTraits<COFFYAML::Object> { + static void mapping(IO &IO, COFFYAML::Object &Obj) { + IO.mapRequired("sections", Obj.Sections); + IO.mapRequired("header", Obj.Header); + IO.mapRequired("symbols", Obj.Symbols); + } +}; +} // end namespace yaml +} // end namespace llvm + +int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv); + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + OwningPtr<MemoryBuffer> Buf; + if (MemoryBuffer::getFileOrSTDIN(Input, Buf)) + return 1; + + yaml::Input YIn(Buf->getBuffer()); + COFFYAML::Object Doc; + YIn >> Doc; + if (YIn.error()) { + errs() << "yaml2obj: Failed to parse YAML file!\n"; + return 1; + } + + COFFParser CP(Doc); + if (!CP.parse()) { + errs() << "yaml2obj: Failed to parse YAML file!\n"; + return 1; + } + + if (!layoutCOFF(CP)) { + errs() << "yaml2obj: Failed to layout COFF file!\n"; + return 1; + } + if (!writeCOFF(CP, outs())) { + errs() << "yaml2obj: Failed to write COFF file!\n"; + return 1; + } +} |