diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-08-07 23:01:33 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-08-07 23:01:33 +0000 |
commit | ee8648bdac07986a0f1ec897b02ec82a2f144d46 (patch) | |
tree | 52d1861acda1205241ee35a94aa63129c604d469 /tools | |
parent | 1a82d4c088707c791c792f6822f611b47a12bdfe (diff) |
Notes
Diffstat (limited to 'tools')
25 files changed, 671 insertions, 340 deletions
diff --git a/tools/dsymutil/DebugMap.cpp b/tools/dsymutil/DebugMap.cpp index cc7c0dc778b3a..e5cc87b3f3181 100644 --- a/tools/dsymutil/DebugMap.cpp +++ b/tools/dsymutil/DebugMap.cpp @@ -216,9 +216,7 @@ MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) { // during the test, we can't hardcode the symbols addresses, so // look them up here and rewrite them. for (const auto &Sym : ErrOrObjectFile->symbols()) { - uint64_t Address; - if (Sym.getAddress(Address)) - continue; + uint64_t Address = Sym.getValue(); ErrorOr<StringRef> Name = Sym.getName(); if (!Name) continue; diff --git a/tools/dsymutil/MachODebugMapParser.cpp b/tools/dsymutil/MachODebugMapParser.cpp index c58545aec999e..6c9fa9b513251 100644 --- a/tools/dsymutil/MachODebugMapParser.cpp +++ b/tools/dsymutil/MachODebugMapParser.cpp @@ -160,8 +160,6 @@ void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex, // symbol table to find its address as it might not be in the // debug map (for common symbols). Value = getMainBinarySymbolAddress(Name); - if (Value == UnknownAddress) - return; break; case MachO::N_FUN: // Functions are scopes in STABS. They have an end marker that @@ -197,10 +195,7 @@ void MachODebugMapParser::loadCurrentObjectFileSymbols() { CurrentObjectAddresses.clear(); for (auto Sym : CurrentObjectHolder.Get().symbols()) { - - uint64_t Addr; - if (Sym.getAddress(Addr) || Addr == UnknownAddress) - continue; + uint64_t Addr = Sym.getValue(); ErrorOr<StringRef> Name = Sym.getName(); if (!Name) continue; @@ -214,7 +209,7 @@ void MachODebugMapParser::loadCurrentObjectFileSymbols() { uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) { auto Sym = MainBinarySymbolAddresses.find(Name); if (Sym == MainBinarySymbolAddresses.end()) - return UnknownAddress; + return 0; return Sym->second; } @@ -228,15 +223,14 @@ void MachODebugMapParser::loadMainBinarySymbols() { // Skip undefined and STAB entries. if ((Type & SymbolRef::ST_Debug) || (Type & SymbolRef::ST_Unknown)) continue; - uint64_t Addr; // The only symbols of interest are the global variables. These // are the only ones that need to be queried because the address // of common data won't be described in the debug map. All other // addresses should be fetched for the debug map. - if (Sym.getAddress(Addr) || Addr == UnknownAddress || - !(Sym.getFlags() & SymbolRef::SF_Global) || Sym.getSection(Section) || - Section->isText()) + if (!(Sym.getFlags() & SymbolRef::SF_Global) || Sym.getSection(Section) || + Section == MainBinary.section_end() || Section->isText()) continue; + uint64_t Addr = Sym.getValue(); ErrorOr<StringRef> NameOrErr = Sym.getName(); if (!NameOrErr) continue; diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 88e7371609927..e33cd795d3ae2 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -333,29 +333,44 @@ static int compileModule(char **argv, LLVMContext &Context) { OS = BOS.get(); } + AnalysisID StartBeforeID = nullptr; AnalysisID StartAfterID = nullptr; AnalysisID StopAfterID = nullptr; const PassRegistry *PR = PassRegistry::getPassRegistry(); - if (!StartAfter.empty()) { - const PassInfo *PI = PR->getPassInfo(StartAfter); - if (!PI) { - errs() << argv[0] << ": start-after pass is not registered.\n"; + if (!RunPass.empty()) { + if (!StartAfter.empty() || !StopAfter.empty()) { + errs() << argv[0] << ": start-after and/or stop-after passes are " + "redundant when run-pass is specified.\n"; return 1; } - StartAfterID = PI->getTypeInfo(); - } - if (!StopAfter.empty()) { - const PassInfo *PI = PR->getPassInfo(StopAfter); + const PassInfo *PI = PR->getPassInfo(RunPass); if (!PI) { - errs() << argv[0] << ": stop-after pass is not registered.\n"; + errs() << argv[0] << ": run-pass pass is not registered.\n"; return 1; } - StopAfterID = PI->getTypeInfo(); + StopAfterID = StartBeforeID = PI->getTypeInfo(); + } else { + if (!StartAfter.empty()) { + const PassInfo *PI = PR->getPassInfo(StartAfter); + if (!PI) { + errs() << argv[0] << ": start-after pass is not registered.\n"; + return 1; + } + StartAfterID = PI->getTypeInfo(); + } + if (!StopAfter.empty()) { + const PassInfo *PI = PR->getPassInfo(StopAfter); + if (!PI) { + errs() << argv[0] << ": stop-after pass is not registered.\n"; + return 1; + } + StopAfterID = PI->getTypeInfo(); + } } // Ask the target to add backend passes as necessary. - if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, StartAfterID, - StopAfterID, MIR.get())) { + if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, StartBeforeID, + StartAfterID, StopAfterID, MIR.get())) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1; diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index 0fd2df4f5aa92..2c9668c63b8cc 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/LibDriver/LibDriver.h" @@ -70,6 +71,16 @@ static cl::list<std::string> static cl::opt<bool> MRI("M", cl::desc("")); +namespace { +enum Format { Default, GNU, BSD }; +} + +static cl::opt<Format> + FormatOpt("format", cl::desc("Archive format to create"), + cl::values(clEnumValN(Default, "defalut", "default"), + clEnumValN(GNU, "gnu", "gnu"), + clEnumValN(BSD, "bsd", "bsd"), clEnumValEnd)); + std::string Options; // Provide additional help output explaining the operations and modifiers of @@ -118,6 +129,7 @@ static bool OriginalDates = false; ///< 'o' modifier static bool OnlyUpdate = false; ///< 'u' modifier static bool Verbose = false; ///< 'v' modifier static bool Symtab = true; ///< 's' modifier +static bool Deterministic = true; ///< 'D' and 'U' modifiers // Relative Positional Argument (for insert/move). This variable holds // the name of the archive member to which the 'a', 'b' or 'i' modifier @@ -234,6 +246,12 @@ static ArchiveOperation parseCommandLine() { AddBefore = true; NumPositional++; break; + case 'D': + Deterministic = true; + break; + case 'U': + Deterministic = false; + break; default: cl::PrintHelpMessage(); } @@ -277,11 +295,13 @@ static ArchiveOperation parseCommandLine() { // Implements the 'p' operation. This function traverses the archive // looking for members that match the path list. -static void doPrint(StringRef Name, object::Archive::child_iterator I) { +static void doPrint(StringRef Name, const object::Archive::Child &C) { if (Verbose) outs() << "Printing " << Name << "\n"; - StringRef Data = I->getBuffer(); + ErrorOr<StringRef> DataOrErr = C.getBuffer(); + failIfError(DataOrErr.getError()); + StringRef Data = *DataOrErr; outs().write(Data.data(), Data.size()); } @@ -306,16 +326,16 @@ static void printMode(unsigned mode) { // the file names of each of the members. However, if verbose mode is requested // ('v' modifier) then the file type, permission mode, user, group, size, and // modification time are also printed. -static void doDisplayTable(StringRef Name, object::Archive::child_iterator I) { +static void doDisplayTable(StringRef Name, const object::Archive::Child &C) { if (Verbose) { - sys::fs::perms Mode = I->getAccessMode(); + sys::fs::perms Mode = C.getAccessMode(); printMode((Mode >> 6) & 007); printMode((Mode >> 3) & 007); printMode(Mode & 007); - outs() << ' ' << I->getUID(); - outs() << '/' << I->getGID(); - outs() << ' ' << format("%6llu", I->getSize()); - outs() << ' ' << I->getLastModified().str(); + outs() << ' ' << C.getUID(); + outs() << '/' << C.getGID(); + outs() << ' ' << format("%6llu", C.getSize()); + outs() << ' ' << C.getLastModified().str(); outs() << ' '; } outs() << Name << "\n"; @@ -323,9 +343,9 @@ static void doDisplayTable(StringRef Name, object::Archive::child_iterator I) { // Implement the 'x' operation. This function extracts files back to the file // system. -static void doExtract(StringRef Name, object::Archive::child_iterator I) { +static void doExtract(StringRef Name, const object::Archive::Child &C) { // Retain the original mode. - sys::fs::perms Mode = I->getAccessMode(); + sys::fs::perms Mode = C.getAccessMode(); SmallString<128> Storage = Name; int FD; @@ -337,7 +357,7 @@ static void doExtract(StringRef Name, object::Archive::child_iterator I) { raw_fd_ostream file(FD, false); // Get the data and its length - StringRef Data = I->getBuffer(); + StringRef Data = *C.getBuffer(); // Write the data. file.write(Data.data(), Data.size()); @@ -347,7 +367,7 @@ static void doExtract(StringRef Name, object::Archive::child_iterator I) { // now. if (OriginalDates) failIfError( - sys::fs::setLastModificationAndAccessTime(FD, I->getLastModified())); + sys::fs::setLastModificationAndAccessTime(FD, C.getLastModified())); if (close(FD)) fail("Could not close the file"); @@ -373,31 +393,43 @@ static bool shouldCreateArchive(ArchiveOperation Op) { static void performReadOperation(ArchiveOperation Operation, object::Archive *OldArchive) { - for (object::Archive::child_iterator I = OldArchive->child_begin(), - E = OldArchive->child_end(); - I != E; ++I) { - ErrorOr<StringRef> NameOrErr = I->getName(); + if (Operation == Extract && OldArchive->isThin()) { + errs() << "extracting from a thin archive is not supported\n"; + std::exit(1); + } + + bool Filter = !Members.empty(); + for (const object::Archive::Child &C : OldArchive->children()) { + ErrorOr<StringRef> NameOrErr = C.getName(); failIfError(NameOrErr.getError()); StringRef Name = NameOrErr.get(); - if (!Members.empty() && - std::find(Members.begin(), Members.end(), Name) == Members.end()) - continue; + if (Filter) { + auto I = std::find(Members.begin(), Members.end(), Name); + if (I == Members.end()) + continue; + Members.erase(I); + } switch (Operation) { default: llvm_unreachable("Not a read operation"); case Print: - doPrint(Name, I); + doPrint(Name, C); break; case DisplayTable: - doDisplayTable(Name, I); + doDisplayTable(Name, C); break; case Extract: - doExtract(Name, I); + doExtract(Name, C); break; } } + if (Members.empty()) + return; + for (StringRef Name : Members) + errs() << Name << " was not found\n"; + std::exit(1); } template <typename T> @@ -525,7 +557,8 @@ computeNewArchiveMembers(ArchiveOperation Operation, assert(unsigned(InsertPos) <= Ret.size()); Ret.insert(Ret.begin() + InsertPos, Moved.begin(), Moved.end()); - Ret.insert(Ret.begin() + InsertPos, Members.size(), NewArchiveIterator()); + Ret.insert(Ret.begin() + InsertPos, Members.size(), + NewArchiveIterator("", "")); int Pos = InsertPos; for (auto &Member : Members) { StringRef Name = sys::path::filename(Member); @@ -539,15 +572,33 @@ computeNewArchiveMembers(ArchiveOperation Operation, static void performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, std::vector<NewArchiveIterator> *NewMembersP) { + object::Archive::Kind Kind; + switch (FormatOpt) { + case Default: { + Triple T(sys::getProcessTriple()); + if (T.isOSDarwin()) + Kind = object::Archive::K_BSD; + else + Kind = object::Archive::K_GNU; + break; + } + case GNU: + Kind = object::Archive::K_GNU; + break; + case BSD: + Kind = object::Archive::K_BSD; + break; + } if (NewMembersP) { std::pair<StringRef, std::error_code> Result = - writeArchive(ArchiveName, *NewMembersP, Symtab); + writeArchive(ArchiveName, *NewMembersP, Symtab, Kind, Deterministic); failIfError(Result.second, Result.first); return; } std::vector<NewArchiveIterator> NewMembers = computeNewArchiveMembers(Operation, OldArchive); - auto Result = writeArchive(ArchiveName, NewMembers, Symtab); + auto Result = + writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic); failIfError(Result.second, Result.first); } diff --git a/tools/llvm-cxxdump/llvm-cxxdump.cpp b/tools/llvm-cxxdump/llvm-cxxdump.cpp index c627a662a9625..4e06be9e78b96 100644 --- a/tools/llvm-cxxdump/llvm-cxxdump.cpp +++ b/tools/llvm-cxxdump/llvm-cxxdump.cpp @@ -207,9 +207,10 @@ static void dumpCXXData(const ObjectFile *Obj) { StringRef SecContents; if (error(Sec.getContents(SecContents))) return; - uint64_t SymAddress; - if (error(Sym.getAddress(SymAddress))) + ErrorOr<uint64_t> SymAddressOrErr = Sym.getAddress(); + if (error(SymAddressOrErr.getError())) return; + uint64_t SymAddress = *SymAddressOrErr; uint64_t SecAddress = Sec.getAddress(); uint64_t SecSize = Sec.getSize(); uint64_t SymOffset = SymAddress - SecAddress; diff --git a/tools/llvm-jitlistener/CMakeLists.txt b/tools/llvm-jitlistener/CMakeLists.txt index 68a4303acef0f..61f8420a7ae59 100644 --- a/tools/llvm-jitlistener/CMakeLists.txt +++ b/tools/llvm-jitlistener/CMakeLists.txt @@ -6,7 +6,7 @@ include_directories( ${LLVM_INTEL_JITEVENTS_INCDIR} ) set(LLVM_LINK_COMPONENTS asmparser bitreader - debuginfo + DebugInfoDWARF inteljitevents interpreter irreader @@ -14,6 +14,10 @@ set(LLVM_LINK_COMPONENTS nativecodegen object selectiondag + Support + ExecutionEngine + RuntimeDyld + Core ) add_llvm_tool(llvm-jitlistener diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index c88f373345647..e7ee3124ed731 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -180,67 +180,25 @@ struct NMSymbol { uint64_t Size; char TypeChar; StringRef Name; - DataRefImpl Symb; + BasicSymbolRef Sym; }; } static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) { - if (!ReverseSort) { - if (A.Address < B.Address) - return true; - if (A.Address == B.Address && A.Name < B.Name) - return true; - if (A.Address == B.Address && A.Name == B.Name && A.Size < B.Size) - return true; - return false; - } - - if (A.Address > B.Address) - return true; - if (A.Address == B.Address && A.Name > B.Name) - return true; - if (A.Address == B.Address && A.Name == B.Name && A.Size > B.Size) - return true; - return false; + bool ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined); + bool BDefined = !(B.Sym.getFlags() & SymbolRef::SF_Undefined); + return std::make_tuple(ADefined, A.Address, A.Name, A.Size) < + std::make_tuple(BDefined, B.Address, B.Name, B.Size); } static bool compareSymbolSize(const NMSymbol &A, const NMSymbol &B) { - if (!ReverseSort) { - if (A.Size < B.Size) - return true; - if (A.Size == B.Size && A.Name < B.Name) - return true; - if (A.Size == B.Size && A.Name == B.Name && A.Address < B.Address) - return true; - return false; - } - - if (A.Size > B.Size) - return true; - if (A.Size == B.Size && A.Name > B.Name) - return true; - if (A.Size == B.Size && A.Name == B.Name && A.Address > B.Address) - return true; - return false; + return std::make_tuple(A.Size, A.Name, A.Address) < + std::make_tuple(B.Size, B.Name, B.Address); } static bool compareSymbolName(const NMSymbol &A, const NMSymbol &B) { - if (!ReverseSort) { - if (A.Name < B.Name) - return true; - if (A.Name == B.Name && A.Size < B.Size) - return true; - if (A.Name == B.Name && A.Size == B.Size && A.Address < B.Address) - return true; - return false; - } - if (A.Name > B.Name) - return true; - if (A.Name == B.Name && A.Size > B.Size) - return true; - if (A.Name == B.Name && A.Size == B.Size && A.Address > B.Address) - return true; - return false; + return std::make_tuple(A.Name, A.Size, A.Address) < + std::make_tuple(B.Name, B.Size, B.Address); } static char isSymbolList64Bit(SymbolicFile &Obj) { @@ -274,11 +232,12 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, uint16_t NDesc; uint32_t NStrx; uint64_t NValue; + DataRefImpl SymDRI = I->Sym.getRawDataRefImpl(); if (MachO->is64Bit()) { H_64 = MachO->MachOObjectFile::getHeader64(); Filetype = H_64.filetype; Flags = H_64.flags; - STE_64 = MachO->getSymbol64TableEntry(I->Symb); + STE_64 = MachO->getSymbol64TableEntry(SymDRI); NType = STE_64.n_type; NSect = STE_64.n_sect; NDesc = STE_64.n_desc; @@ -288,7 +247,7 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, H = MachO->MachOObjectFile::getHeader(); Filetype = H.filetype; Flags = H.flags; - STE = MachO->getSymbolTableEntry(I->Symb); + STE = MachO->getSymbolTableEntry(SymDRI); NType = STE.n_type; NSect = STE.n_sect; NDesc = STE.n_desc; @@ -356,7 +315,7 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, break; case MachO::N_SECT: { section_iterator Sec = MachO->section_end(); - MachO->getSymbolSection(I->Symb, Sec); + MachO->getSymbolSection(I->Sym.getRawDataRefImpl(), Sec); DataRefImpl Ref = Sec->getRawDataRefImpl(); StringRef SectionName; MachO->getSectionName(Ref, SectionName); @@ -415,7 +374,7 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, if ((NType & MachO::N_TYPE) == MachO::N_INDR) { outs() << I->Name << " (for "; StringRef IndirectName; - if (MachO->getIndirectName(I->Symb, IndirectName)) + if (MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName)) outs() << "?)"; else outs() << IndirectName << ")"; @@ -498,13 +457,14 @@ static void darwinPrintStab(MachOObjectFile *MachO, SymbolListT::iterator I) { uint8_t NType; uint8_t NSect; uint16_t NDesc; + DataRefImpl SymDRI = I->Sym.getRawDataRefImpl(); if (MachO->is64Bit()) { - STE_64 = MachO->getSymbol64TableEntry(I->Symb); + STE_64 = MachO->getSymbol64TableEntry(SymDRI); NType = STE_64.n_type; NSect = STE_64.n_sect; NDesc = STE_64.n_desc; } else { - STE = MachO->getSymbolTableEntry(I->Symb); + STE = MachO->getSymbolTableEntry(SymDRI); NType = STE.n_type; NSect = STE.n_sect; NDesc = STE.n_desc; @@ -526,12 +486,17 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, std::string ArchiveName, std::string ArchitectureName) { if (!NoSort) { + std::function<bool(const NMSymbol &, const NMSymbol &)> Cmp; if (NumericSort) - std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolAddress); + Cmp = compareSymbolAddress; else if (SizeSort) - std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolSize); + Cmp = compareSymbolSize; else - std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolName); + Cmp = compareSymbolName; + + if (ReverseSort) + Cmp = [=](const NMSymbol &A, const NMSymbol &B) { return Cmp(B, A); }; + std::sort(SymbolList.begin(), SymbolList.end(), Cmp); } if (!PrintFileName) { @@ -557,9 +522,11 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, for (SymbolListT::iterator I = SymbolList.begin(), E = SymbolList.end(); I != E; ++I) { - if ((I->TypeChar != 'U') && UndefinedOnly) + uint32_t SymFlags = I->Sym.getFlags(); + bool Undefined = SymFlags & SymbolRef::SF_Undefined; + if (!Undefined && UndefinedOnly) continue; - if ((I->TypeChar == 'U') && DefinedOnly) + if (Undefined && DefinedOnly) continue; if (SizeSort && !PrintAddress) continue; @@ -578,12 +545,12 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, char SymbolAddrStr[18] = ""; char SymbolSizeStr[18] = ""; - if (OutputFormat == sysv || I->Address == UnknownAddress) + if (OutputFormat == sysv || I->TypeChar == 'U') strcpy(SymbolAddrStr, printBlanks); if (OutputFormat == sysv) strcpy(SymbolSizeStr, printBlanks); - if (I->Address != UnknownAddress) + if (I->TypeChar != 'U') format(printFormat, I->Address) .print(SymbolAddrStr, sizeof(SymbolAddrStr)); format(printFormat, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); @@ -895,20 +862,23 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, continue; NMSymbol S; S.Size = 0; - S.Address = UnknownAddress; + S.Address = 0; if (PrintSize) { if (isa<ELFObjectFileBase>(&Obj)) S.Size = ELFSymbolRef(Sym).getSize(); } if (PrintAddress && isa<ObjectFile>(Obj)) { - if (error(SymbolRef(Sym).getAddress(S.Address))) + SymbolRef SymRef(Sym); + ErrorOr<uint64_t> AddressOrErr = SymRef.getAddress(); + if (error(AddressOrErr.getError())) break; + S.Address = *AddressOrErr; } S.TypeChar = getNMTypeChar(Obj, Sym); if (error(Sym.printName(OS))) break; OS << '\0'; - S.Symb = Sym.getRawDataRefImpl(); + S.Sym = Sym; SymbolList.push_back(S); } diff --git a/tools/llvm-objdump/COFFDump.cpp b/tools/llvm-objdump/COFFDump.cpp index 58bdddfa9918e..8b94a50ea28b5 100644 --- a/tools/llvm-objdump/COFFDump.cpp +++ b/tools/llvm-objdump/COFFDump.cpp @@ -161,8 +161,10 @@ static std::error_code resolveSectionAndAddress(const COFFObjectFile *Obj, const SymbolRef &Sym, const coff_section *&ResolvedSection, uint64_t &ResolvedAddr) { - if (std::error_code EC = Sym.getAddress(ResolvedAddr)) + ErrorOr<uint64_t> ResolvedAddrOrErr = Sym.getAddress(); + if (std::error_code EC = ResolvedAddrOrErr.getError()) return EC; + ResolvedAddr = *ResolvedAddrOrErr; section_iterator iter(Obj->section_begin()); if (std::error_code EC = Sym.getSection(iter)) return EC; diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 5263c33bf2dcc..04c72f4856c89 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -102,9 +102,6 @@ cl::list<std::string> cl::desc("Prints the specified segment,section for " "Mach-O objects (requires -macho)")); -cl::opt<bool> llvm::Raw("raw", - cl::desc("Have -section dump the raw binary contents")); - cl::opt<bool> llvm::InfoPlist("info-plist", cl::desc("Print the info plist section as strings for " @@ -178,18 +175,8 @@ static const Target *GetTarget(const MachOObjectFile *MachOObj, struct SymbolSorter { bool operator()(const SymbolRef &A, const SymbolRef &B) { - SymbolRef::Type AType = A.getType(); - SymbolRef::Type BType = B.getType(); - - uint64_t AAddr, BAddr; - if (AType != SymbolRef::ST_Function) - AAddr = 0; - else - A.getAddress(AAddr); - if (BType != SymbolRef::ST_Function) - BAddr = 0; - else - B.getAddress(BAddr); + uint64_t AAddr = (A.getType() != SymbolRef::ST_Function) ? 0 : A.getValue(); + uint64_t BAddr = (B.getType() != SymbolRef::ST_Function) ? 0 : B.getValue(); return AAddr < BAddr; } }; @@ -592,8 +579,7 @@ static void CreateSymbolAddressMap(MachOObjectFile *O, SymbolRef::Type ST = Symbol.getType(); if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || ST == SymbolRef::ST_Other) { - uint64_t Address; - Symbol.getAddress(Address); + uint64_t Address = Symbol.getValue(); ErrorOr<StringRef> SymNameOrErr = Symbol.getName(); if (std::error_code EC = SymNameOrErr.getError()) report_fatal_error(EC.message()); @@ -1057,11 +1043,6 @@ static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, uint32_t sect_size = BytesStr.size(); uint64_t sect_addr = Section.getAddress(); - if (Raw) { - outs().write(BytesStr.data(), BytesStr.size()); - continue; - } - outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; @@ -1190,8 +1171,7 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF, // UniversalHeaders or ArchiveHeaders. if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints || - DylibsUsed || DylibId || ObjcMetaData || - (DumpSections.size() != 0 && !Raw)) { + DylibsUsed || DylibId || ObjcMetaData || (DumpSections.size() != 0)) { outs() << Filename; if (!ArchiveMemberName.empty()) outs() << '(' << ArchiveMemberName << ')'; @@ -2424,7 +2404,7 @@ static const char *get_pointer_32(uint32_t Address, uint32_t &offset, // symbol is passed, look up that address in the info's AddrMap. static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, DisassembleInfo *info, uint64_t &n_value, - uint64_t ReferenceValue = UnknownAddress) { + uint64_t ReferenceValue = 0) { n_value = 0; if (!info->verbose) return nullptr; @@ -2456,9 +2436,7 @@ static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, // and return its name. const char *SymbolName = nullptr; if (reloc_found && isExtern) { - Symbol.getAddress(n_value); - if (n_value == UnknownAddress) - n_value = 0; + n_value = Symbol.getValue(); ErrorOr<StringRef> NameOrError = Symbol.getName(); if (std::error_code EC = NameOrError.getError()) report_fatal_error(EC.message()); @@ -2480,8 +2458,7 @@ static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, // We did not find an external relocation entry so look up the ReferenceValue // as an address of a symbol and if found return that symbol's name. - if (ReferenceValue != UnknownAddress) - SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); + SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); return SymbolName; } @@ -5640,7 +5617,7 @@ static const char *GuessLiteralPointer(uint64_t ReferenceValue, if (info->O->getAnyRelocationPCRel(RE)) { unsigned Type = info->O->getAnyRelocationType(RE); if (Type == MachO::X86_64_RELOC_SIGNED) { - Symbol.getAddress(ReferenceValue); + ReferenceValue = Symbol.getValue(); } } } @@ -6131,8 +6108,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, SymbolRef::Type ST = Symbol.getType(); if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || ST == SymbolRef::ST_Other) { - uint64_t Address; - Symbol.getAddress(Address); + uint64_t Address = Symbol.getValue(); ErrorOr<StringRef> SymNameOrErr = Symbol.getName(); if (std::error_code EC = SymNameOrErr.getError()) report_fatal_error(EC.message()); @@ -6194,9 +6170,8 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, continue; // Start at the address of the symbol relative to the section's address. - uint64_t Start = 0; + uint64_t Start = Symbols[SymIdx].getValue(); uint64_t SectionAddress = Sections[SectIdx].getAddress(); - Symbols[SymIdx].getAddress(Start); Start -= SectionAddress; // Stop disassembling either at the beginning of the next symbol or at @@ -6209,7 +6184,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, if (NextSymType == SymbolRef::ST_Function) { containsNextSym = Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); - Symbols[NextSymIdx].getAddress(NextSym); + NextSym = Symbols[NextSymIdx].getValue(); NextSym -= SectionAddress; break; } @@ -6815,8 +6790,7 @@ void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { if (Section == Obj->section_end()) continue; - uint64_t Addr; - SymRef.getAddress(Addr); + uint64_t Addr = SymRef.getValue(); Symbols.insert(std::make_pair(Addr, SymRef)); } diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 7869818546098..275eb9c6a454e 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -96,6 +96,10 @@ llvm::LazyBind("lazy-bind", cl::desc("Display mach-o lazy binding info")); cl::opt<bool> llvm::WeakBind("weak-bind", cl::desc("Display mach-o weak binding info")); +cl::opt<bool> +llvm::RawClangAST("raw-clang-ast", + cl::desc("Dump the raw binary contents of the clang AST section")); + static cl::opt<bool> MachOOpt("macho", cl::desc("Use MachO specific object file parser")); static cl::alias @@ -212,9 +216,7 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) { } bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { - uint64_t a_addr = a.getOffset(); - uint64_t b_addr = b.getOffset(); - return a_addr < b_addr; + return a.getOffset() < b.getOffset(); } namespace { @@ -455,13 +457,12 @@ static void printRelocationTargetName(const MachOObjectFile *O, for (const SymbolRef &Symbol : O->symbols()) { std::error_code ec; - uint64_t Addr; - ErrorOr<StringRef> Name = Symbol.getName(); - - if ((ec = Symbol.getAddress(Addr))) + ErrorOr<uint64_t> Addr = Symbol.getAddress(); + if ((ec = Addr.getError())) report_fatal_error(ec.message()); - if (Addr != Val) + if (*Addr != Val) continue; + ErrorOr<StringRef> Name = Symbol.getName(); if (std::error_code EC = Name.getError()) report_fatal_error(EC.message()); fmt << *Name; @@ -811,6 +812,30 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { SectionRelocMap[*Sec2].push_back(Section); } + // Create a mapping from virtual address to symbol name. This is used to + // pretty print the target of a call. + std::vector<std::pair<uint64_t, StringRef>> AllSymbols; + if (MIA) { + for (const SymbolRef &Symbol : Obj->symbols()) { + if (Symbol.getType() != SymbolRef::ST_Function) + continue; + + ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress(); + if (error(AddressOrErr.getError())) + break; + uint64_t Address = *AddressOrErr; + + ErrorOr<StringRef> Name = Symbol.getName(); + if (error(Name.getError())) + break; + if (Name->empty()) + continue; + AllSymbols.push_back(std::make_pair(Address, *Name)); + } + + array_pod_sort(AllSymbols.begin(), AllSymbols.end()); + } + for (const SectionRef &Section : Obj->sections()) { if (!Section.isText() || Section.isVirtual()) continue; @@ -824,11 +849,10 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::vector<std::pair<uint64_t, StringRef>> Symbols; for (const SymbolRef &Symbol : Obj->symbols()) { if (Section.containsSymbol(Symbol)) { - uint64_t Address; - if (error(Symbol.getAddress(Address))) + ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress(); + if (error(AddressOrErr.getError())) break; - if (Address == UnknownAddress) - continue; + uint64_t Address = *AddressOrErr; Address -= SectionAddr; if (Address >= SectSize) continue; @@ -916,6 +940,29 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { SectionAddr + Index, outs(), "", *STI); outs() << CommentStream.str(); Comments.clear(); + if (MIA && (MIA->isCall(Inst) || MIA->isUnconditionalBranch(Inst) || + MIA->isConditionalBranch(Inst))) { + uint64_t Target; + if (MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target)) { + auto TargetSym = std::upper_bound( + AllSymbols.begin(), AllSymbols.end(), Target, + [](uint64_t LHS, const std::pair<uint64_t, StringRef> &RHS) { + return LHS < RHS.first; + }); + if (TargetSym != AllSymbols.begin()) + --TargetSym; + else + TargetSym = AllSymbols.end(); + + if (TargetSym != AllSymbols.end()) { + outs() << " <" << TargetSym->second; + uint64_t Disp = Target - TargetSym->first; + if (Disp) + outs() << '+' << utohexstr(Disp); + outs() << '>'; + } + } + } outs() << "\n"; } else { errs() << ToolName << ": warning: invalid instruction encoding\n"; @@ -1113,12 +1160,13 @@ void llvm::PrintSymbolTable(const ObjectFile *o) { return; } for (const SymbolRef &Symbol : o->symbols()) { - uint64_t Address; + ErrorOr<uint64_t> AddressOrError = Symbol.getAddress(); + if (error(AddressOrError.getError())) + continue; + uint64_t Address = *AddressOrError; SymbolRef::Type Type = Symbol.getType(); uint32_t Flags = Symbol.getFlags(); section_iterator Section = o->section_end(); - if (error(Symbol.getAddress(Address))) - continue; if (error(Symbol.getSection(Section))) continue; StringRef Name; @@ -1137,11 +1185,6 @@ void llvm::PrintSymbolTable(const ObjectFile *o) { bool Common = Flags & SymbolRef::SF_Common; bool Hidden = Flags & SymbolRef::SF_Hidden; - if (Common) - Address = Symbol.getCommonSize(); - - if (Address == UnknownAddress) - Address = 0; char GlobLoc = ' '; if (Type != SymbolRef::ST_Unknown) GlobLoc = Global ? 'g' : 'l'; @@ -1269,6 +1312,43 @@ void llvm::printWeakBindTable(const ObjectFile *o) { } } +/// Dump the raw contents of the __clangast section so the output can be piped +/// into llvm-bcanalyzer. +void llvm::printRawClangAST(const ObjectFile *Obj) { + if (outs().is_displayed()) { + errs() << "The -raw-clang-ast option will dump the raw binary contents of " + "the clang ast section.\n" + "Please redirect the output to a file or another program such as " + "llvm-bcanalyzer.\n"; + return; + } + + StringRef ClangASTSectionName("__clangast"); + if (isa<COFFObjectFile>(Obj)) { + ClangASTSectionName = "clangast"; + } + + Optional<object::SectionRef> ClangASTSection; + for (auto Sec : Obj->sections()) { + StringRef Name; + Sec.getName(Name); + if (Name == ClangASTSectionName) { + ClangASTSection = Sec; + break; + } + } + if (!ClangASTSection) + return; + + StringRef ClangASTContents; + if (error(ClangASTSection.getValue().getContents(ClangASTContents))) { + errs() << "Could not read the " << ClangASTSectionName << " section!\n"; + return; + } + + outs().write(ClangASTContents.data(), ClangASTContents.size()); +} + static void printFaultMaps(const ObjectFile *Obj) { const char *FaultMapSectionName = nullptr; @@ -1323,9 +1403,12 @@ static void printPrivateFileHeader(const ObjectFile *o) { } static void DumpObject(const ObjectFile *o) { - outs() << '\n'; - outs() << o->getFileName() - << ":\tfile format " << o->getFileFormatName() << "\n\n"; + // Avoid other output when using a raw option. + if (!RawClangAST) { + outs() << '\n'; + outs() << o->getFileName() + << ":\tfile format " << o->getFileFormatName() << "\n\n"; + } if (Disassemble) DisassembleObject(o, Relocations); @@ -1351,6 +1434,8 @@ static void DumpObject(const ObjectFile *o) { printLazyBindTable(o); if (WeakBind) printWeakBindTable(o); + if (RawClangAST) + printRawClangAST(o); if (PrintFaultMaps) printFaultMaps(o); } @@ -1441,6 +1526,7 @@ int main(int argc, char **argv) { && !Bind && !LazyBind && !WeakBind + && !RawClangAST && !(UniversalHeaders && MachOOpt) && !(ArchiveHeaders && MachOOpt) && !(IndirectSymbols && MachOOpt) diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h index b4d34f4033bcf..eb10d8344f711 100644 --- a/tools/llvm-objdump/llvm-objdump.h +++ b/tools/llvm-objdump/llvm-objdump.h @@ -26,7 +26,6 @@ extern cl::opt<std::string> ArchName; extern cl::opt<std::string> MCPU; extern cl::list<std::string> MAttrs; extern cl::list<std::string> DumpSections; -extern cl::opt<bool> Raw; extern cl::opt<bool> Disassemble; extern cl::opt<bool> NoShowRawInsn; extern cl::opt<bool> PrivateHeaders; @@ -35,6 +34,7 @@ extern cl::opt<bool> Rebase; extern cl::opt<bool> Bind; extern cl::opt<bool> LazyBind; extern cl::opt<bool> WeakBind; +extern cl::opt<bool> RawClangAST; extern cl::opt<bool> UniversalHeaders; extern cl::opt<bool> ArchiveHeaders; extern cl::opt<bool> IndirectSymbols; @@ -72,6 +72,7 @@ void printRebaseTable(const object::ObjectFile *o); void printBindTable(const object::ObjectFile *o); void printLazyBindTable(const object::ObjectFile *o); void printWeakBindTable(const object::ObjectFile *o); +void printRawClangAST(const object::ObjectFile *o); void PrintRelocations(const object::ObjectFile *o); void PrintSectionHeaders(const object::ObjectFile *o); void PrintSectionContents(const object::ObjectFile *o); diff --git a/tools/llvm-readobj/ARMWinEHPrinter.cpp b/tools/llvm-readobj/ARMWinEHPrinter.cpp index a1ea79f3688ea..bf5ff8e1d0310 100644 --- a/tools/llvm-readobj/ARMWinEHPrinter.cpp +++ b/tools/llvm-readobj/ARMWinEHPrinter.cpp @@ -201,10 +201,10 @@ ErrorOr<object::SymbolRef> Decoder::getSymbol(const COFFObjectFile &COFF, if (FunctionOnly && Symbol.getType() != SymbolRef::ST_Function) continue; - uint64_t Address; - if (std::error_code EC = Symbol.getAddress(Address)) + ErrorOr<uint64_t> Address = Symbol.getAddress(); + if (std::error_code EC = Address.getError()) return EC; - if (Address == VA) + if (*Address == VA) return Symbol; } return readobj_error::unknown_symbol; @@ -605,7 +605,10 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF, if (std::error_code EC = FunctionNameOrErr.getError()) report_fatal_error(EC.message()); FunctionName = *FunctionNameOrErr; - Function->getAddress(FunctionAddress); + ErrorOr<uint64_t> FunctionAddressOrErr = Function->getAddress(); + if (std::error_code EC = FunctionAddressOrErr.getError()) + report_fatal_error(EC.message()); + FunctionAddress = *FunctionAddressOrErr; } else { const pe32_header *PEHeader; if (COFF.getPE32Header(PEHeader)) @@ -620,8 +623,10 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF, if (std::error_code EC = Name.getError()) report_fatal_error(EC.message()); - uint64_t Address; - XDataRecord->getAddress(Address); + ErrorOr<uint64_t> AddressOrErr = XDataRecord->getAddress(); + if (std::error_code EC = AddressOrErr.getError()) + report_fatal_error(EC.message()); + uint64_t Address = *AddressOrErr; SW.printString("ExceptionRecord", formatSymbol(*Name, Address)); @@ -666,7 +671,8 @@ bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF, if (std::error_code EC = FunctionNameOrErr.getError()) report_fatal_error(EC.message()); FunctionName = *FunctionNameOrErr; - Function->getAddress(FunctionAddress); + ErrorOr<uint64_t> FunctionAddressOrErr = Function->getAddress(); + FunctionAddress = *FunctionAddressOrErr; } else { const pe32_header *PEHeader; if (COFF.getPE32Header(PEHeader)) diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index f5effe2924419..cf897d7cb4840 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -48,7 +48,6 @@ public: COFFDumper(const llvm::object::COFFObjectFile *Obj, StreamWriter& Writer) : ObjDumper(Writer) , Obj(Obj) { - cacheRelocations(); } void printFileHeaders() override; @@ -92,6 +91,7 @@ private: typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy; const llvm::object::COFFObjectFile *Obj; + bool RelocCached = false; RelocMapTy RelocMap; StringRef CVFileIndexToStringOffsetTable; StringRef CVStringTable; @@ -119,6 +119,7 @@ std::error_code createCOFFDumper(const object::ObjectFile *Obj, // symbol used for the relocation at the offset. std::error_code COFFDumper::resolveSymbol(const coff_section *Section, uint64_t Offset, SymbolRef &Sym) { + cacheRelocations(); const auto &Relocations = RelocMap[Section]; for (const auto &Relocation : Relocations) { uint64_t RelocationOffset = Relocation.getOffset(); @@ -339,6 +340,10 @@ static std::error_code getSymbolAuxData(const COFFObjectFile *Obj, } void COFFDumper::cacheRelocations() { + if (RelocCached) + return; + RelocCached = true; + for (const SectionRef &S : Obj->sections()) { const coff_section *Section = Obj->getCOFFSection(S); @@ -580,7 +585,11 @@ void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) { W.printString("FunctionName", Name); DataExtractor DE(FunctionLineTables[Name], true, 4); - uint32_t Offset = 8; // Skip relocations. + uint32_t Offset = 6; // Skip relocations. + uint16_t Flags = DE.getU16(&Offset); + W.printHex("Flags", Flags); + bool HasColumnInformation = + Flags & COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS; uint32_t FunctionSize = DE.getU32(&Offset); W.printHex("CodeSize", FunctionSize); while (DE.isValidOffset(Offset)) { @@ -588,9 +597,12 @@ void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) { // in the line table. The filename string is accessed using double // indirection to the string table subsection using the index subsection. uint32_t OffsetInIndex = DE.getU32(&Offset), - SegmentLength = DE.getU32(&Offset), + SegmentLength = DE.getU32(&Offset), FullSegmentSize = DE.getU32(&Offset); - if (FullSegmentSize != 12 + 8 * SegmentLength) { + + if (FullSegmentSize != + 12 + 8 * SegmentLength + + (HasColumnInformation ? 4 * SegmentLength : 0)) { error(object_error::parse_failed); return; } @@ -631,6 +643,15 @@ void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) { format("+0x%X", PC).snprint(Buffer, 32); W.printNumber(Buffer, LineNumber); } + if (HasColumnInformation) { + for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset); + ++J) { + uint16_t ColStart = DE.getU16(&Offset); + W.printNumber("ColStart", ColStart); + uint16_t ColEnd = DE.getU16(&Offset); + W.printNumber("ColEnd", ColEnd); + } + } } } } diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index a4b25efeb9ba1..1cdf5529c0809 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -56,6 +56,7 @@ public: void printDynamicTable() override; void printNeededLibraries() override; void printProgramHeaders() override; + void printHashTable() override; void printAttributes() override; void printMipsPLTGOT() override; @@ -1119,6 +1120,18 @@ void ELFDumper<ELFT>::printProgramHeaders() { } } +template <typename ELFT> +void ELFDumper<ELFT>::printHashTable() { + DictScope D(W, "HashTable"); + auto HT = Obj->getHashTable(); + if (!HT) + return; + W.printNumber("Num Buckets", HT->nbucket); + W.printNumber("Num Chains", HT->nchain); + W.printList("Buckets", HT->buckets()); + W.printList("Chains", HT->chains()); +} + template <class ELFT> void ELFDumper<ELFT>::printAttributes() { W.startLine() << "Attributes not implemented.\n"; @@ -1162,9 +1175,10 @@ public: typedef typename ObjectFile::Elf_Shdr Elf_Shdr; typedef typename ObjectFile::Elf_Sym Elf_Sym; - MipsGOTParser(const ObjectFile *Obj, StreamWriter &W) : Obj(Obj), W(W) {} + MipsGOTParser(const ObjectFile *Obj, StreamWriter &W); - void parseGOT(const Elf_Shdr &GOTShdr); + void parseGOT(); + void parsePLT(); private: typedef typename ObjectFile::Elf_Addr GOTEntry; @@ -1173,35 +1187,79 @@ private: const ObjectFile *Obj; StreamWriter &W; + llvm::Optional<uint64_t> DtPltGot; + llvm::Optional<uint64_t> DtLocalGotNum; + llvm::Optional<uint64_t> DtGotSym; + llvm::Optional<uint64_t> DtMipsPltGot; + llvm::Optional<uint64_t> DtJmpRel; std::size_t getGOTTotal(ArrayRef<uint8_t> GOT) const; GOTIter makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum); - bool getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym); void printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It); void printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It, const Elf_Sym *Sym, bool IsDynamic); + void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It, + StringRef Purpose); + void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It, + const Elf_Sym *Sym); }; } template <class ELFT> -void MipsGOTParser<ELFT>::parseGOT(const Elf_Shdr &GOTShdr) { +MipsGOTParser<ELFT>::MipsGOTParser(const ObjectFile *Obj, StreamWriter &W) + : Obj(Obj), W(W) { + for (const auto &Entry : Obj->dynamic_table()) { + switch (Entry.getTag()) { + case ELF::DT_PLTGOT: + DtPltGot = Entry.getVal(); + break; + case ELF::DT_MIPS_LOCAL_GOTNO: + DtLocalGotNum = Entry.getVal(); + break; + case ELF::DT_MIPS_GOTSYM: + DtGotSym = Entry.getVal(); + break; + case ELF::DT_MIPS_PLTGOT: + DtMipsPltGot = Entry.getVal(); + break; + case ELF::DT_JMPREL: + DtJmpRel = Entry.getVal(); + break; + } + } +} + +template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() { // See "Global Offset Table" in Chapter 5 in the following document // for detailed GOT description. // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf + if (!DtPltGot) { + W.startLine() << "Cannot find PLTGOT dynamic table tag.\n"; + return; + } + if (!DtLocalGotNum) { + W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n"; + return; + } + if (!DtGotSym) { + W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n"; + return; + } - ErrorOr<ArrayRef<uint8_t>> GOT = Obj->getSectionContents(&GOTShdr); - if (!GOT) { - W.startLine() << "The .got section is empty.\n"; + const Elf_Shdr *GOTShdr = findSectionByAddress(Obj, *DtPltGot); + if (!GOTShdr) { + W.startLine() << "There is no .got section in the file.\n"; return; } - uint64_t DtLocalGotNum; - uint64_t DtGotSym; - if (!getGOTTags(DtLocalGotNum, DtGotSym)) + ErrorOr<ArrayRef<uint8_t>> GOT = Obj->getSectionContents(GOTShdr); + if (!GOT) { + W.startLine() << "The .got section is empty.\n"; return; + } - if (DtLocalGotNum > getGOTTotal(*GOT)) { + if (*DtLocalGotNum > getGOTTotal(*GOT)) { W.startLine() << "MIPS_LOCAL_GOTNO exceeds a number of GOT entries.\n"; return; } @@ -1210,37 +1268,37 @@ void MipsGOTParser<ELFT>::parseGOT(const Elf_Shdr &GOTShdr) { const Elf_Sym *DynSymEnd = Obj->dynamic_symbol_end(); std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd)); - if (DtGotSym > DynSymTotal) { + if (*DtGotSym > DynSymTotal) { W.startLine() << "MIPS_GOTSYM exceeds a number of dynamic symbols.\n"; return; } - std::size_t GlobalGotNum = DynSymTotal - DtGotSym; + std::size_t GlobalGotNum = DynSymTotal - *DtGotSym; - if (DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) { + if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) { W.startLine() << "Number of global GOT entries exceeds the size of GOT.\n"; return; } GOTIter GotBegin = makeGOTIter(*GOT, 0); - GOTIter GotLocalEnd = makeGOTIter(*GOT, DtLocalGotNum); + GOTIter GotLocalEnd = makeGOTIter(*GOT, *DtLocalGotNum); GOTIter It = GotBegin; DictScope GS(W, "Primary GOT"); - W.printHex("Canonical gp value", GOTShdr.sh_addr + 0x7ff0); + W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0); { ListScope RS(W, "Reserved entries"); { DictScope D(W, "Entry"); - printGotEntry(GOTShdr.sh_addr, GotBegin, It++); + printGotEntry(GOTShdr->sh_addr, GotBegin, It++); W.printString("Purpose", StringRef("Lazy resolver")); } if (It != GotLocalEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) { DictScope D(W, "Entry"); - printGotEntry(GOTShdr.sh_addr, GotBegin, It++); + printGotEntry(GOTShdr->sh_addr, GotBegin, It++); W.printString("Purpose", StringRef("Module pointer (GNU extension)")); } } @@ -1248,24 +1306,88 @@ void MipsGOTParser<ELFT>::parseGOT(const Elf_Shdr &GOTShdr) { ListScope LS(W, "Local entries"); for (; It != GotLocalEnd; ++It) { DictScope D(W, "Entry"); - printGotEntry(GOTShdr.sh_addr, GotBegin, It); + printGotEntry(GOTShdr->sh_addr, GotBegin, It); } } { ListScope GS(W, "Global entries"); - GOTIter GotGlobalEnd = makeGOTIter(*GOT, DtLocalGotNum + GlobalGotNum); - const Elf_Sym *GotDynSym = DynSymBegin + DtGotSym; + GOTIter GotGlobalEnd = makeGOTIter(*GOT, *DtLocalGotNum + GlobalGotNum); + const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym; for (; It != GotGlobalEnd; ++It) { DictScope D(W, "Entry"); - printGlobalGotEntry(GOTShdr.sh_addr, GotBegin, It, GotDynSym++, true); + printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, true); } } - std::size_t SpecGotNum = getGOTTotal(*GOT) - DtLocalGotNum - GlobalGotNum; + std::size_t SpecGotNum = getGOTTotal(*GOT) - *DtLocalGotNum - GlobalGotNum; W.printNumber("Number of TLS and multi-GOT entries", uint64_t(SpecGotNum)); } +template <class ELFT> void MipsGOTParser<ELFT>::parsePLT() { + if (!DtMipsPltGot) { + W.startLine() << "Cannot find MIPS_PLTGOT dynamic table tag.\n"; + return; + } + if (!DtJmpRel) { + W.startLine() << "Cannot find JMPREL dynamic table tag.\n"; + return; + } + + const Elf_Shdr *PLTShdr = findSectionByAddress(Obj, *DtMipsPltGot); + if (!PLTShdr) { + W.startLine() << "There is no .got.plt section in the file.\n"; + return; + } + ErrorOr<ArrayRef<uint8_t>> PLT = Obj->getSectionContents(PLTShdr); + if (!PLT) { + W.startLine() << "The .got.plt section is empty.\n"; + return; + } + + const Elf_Shdr *PLTRelShdr = findSectionByAddress(Obj, *DtJmpRel); + if (!PLTShdr) { + W.startLine() << "There is no .rel.plt section in the file.\n"; + return; + } + + GOTIter PLTBegin = makeGOTIter(*PLT, 0); + GOTIter PLTEnd = makeGOTIter(*PLT, getGOTTotal(*PLT)); + GOTIter It = PLTBegin; + + DictScope GS(W, "PLT GOT"); + { + ListScope RS(W, "Reserved entries"); + printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "PLT lazy resolver"); + if (It != PLTEnd) + printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "Module pointer"); + } + { + ListScope GS(W, "Entries"); + + switch (PLTRelShdr->sh_type) { + case ELF::SHT_REL: + for (typename ObjectFile::Elf_Rel_Iter RI = Obj->rel_begin(PLTRelShdr), + RE = Obj->rel_end(PLTRelShdr); + RI != RE && It != PLTEnd; ++RI, ++It) { + const Elf_Sym *Sym = + Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second; + printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, Sym); + } + break; + case ELF::SHT_RELA: + for (typename ObjectFile::Elf_Rela_Iter RI = Obj->rela_begin(PLTRelShdr), + RE = Obj->rela_end(PLTRelShdr); + RI != RE && It != PLTEnd; ++RI, ++It) { + const Elf_Sym *Sym = + Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second; + printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, Sym); + } + break; + } + } +} + template <class ELFT> std::size_t MipsGOTParser<ELFT>::getGOTTotal(ArrayRef<uint8_t> GOT) const { return GOT.size() / sizeof(GOTEntry); @@ -1279,36 +1401,6 @@ MipsGOTParser<ELFT>::makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum) { } template <class ELFT> -bool MipsGOTParser<ELFT>::getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym) { - bool FoundLocalGotNum = false; - bool FoundGotSym = false; - for (const auto &Entry : Obj->dynamic_table()) { - switch (Entry.getTag()) { - case ELF::DT_MIPS_LOCAL_GOTNO: - LocalGotNum = Entry.getVal(); - FoundLocalGotNum = true; - break; - case ELF::DT_MIPS_GOTSYM: - GotSym = Entry.getVal(); - FoundGotSym = true; - break; - } - } - - if (!FoundLocalGotNum) { - W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n"; - return false; - } - - if (!FoundGotSym) { - W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n"; - return false; - } - - return true; -} - -template <class ELFT> void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It) { int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); @@ -1335,32 +1427,44 @@ void MipsGOTParser<ELFT>::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, W.printNumber("Name", FullSymbolName, Sym->st_name); } -template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() { - if (Obj->getHeader()->e_machine != EM_MIPS) { - W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n"; - return; - } +template <class ELFT> +void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, + GOTIter It, StringRef Purpose) { + DictScope D(W, "Entry"); + int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); + W.printHex("Address", PLTAddr + Offset); + W.printHex("Initial", *It); + W.printString("Purpose", Purpose); +} - llvm::Optional<uint64_t> DtPltGot; - for (const auto &Entry : Obj->dynamic_table()) { - if (Entry.getTag() == ELF::DT_PLTGOT) { - DtPltGot = Entry.getVal(); - break; - } - } +template <class ELFT> +void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, + GOTIter It, const Elf_Sym *Sym) { + DictScope D(W, "Entry"); + int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry); + W.printHex("Address", PLTAddr + Offset); + W.printHex("Initial", *It); + W.printHex("Value", Sym->st_value); + W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes)); - if (!DtPltGot) { - W.startLine() << "Cannot find PLTGOT dynamic table tag.\n"; - return; - } + unsigned SectionIndex = 0; + StringRef SectionName; + getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex); + W.printHex("Section", SectionName, SectionIndex); - const Elf_Shdr *GotShdr = findSectionByAddress(Obj, *DtPltGot); - if (!GotShdr) { - W.startLine() << "There is no .got section in the file.\n"; + std::string FullSymbolName = getFullSymbolName(*Obj, Sym, true); + W.printNumber("Name", FullSymbolName, Sym->st_name); +} + +template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() { + if (Obj->getHeader()->e_machine != EM_MIPS) { + W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n"; return; } - MipsGOTParser<ELFT>(Obj, W).parseGOT(*GotShdr); + MipsGOTParser<ELFT> GOTParser(Obj, W); + GOTParser.parseGOT(); + GOTParser.parsePLT(); } static const EnumEntry<unsigned> ElfMipsISAExtType[] = { diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index 27e15b256cc57..5ecf0ec3d6fa0 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -37,6 +37,7 @@ public: virtual void printDynamicTable() { } virtual void printNeededLibraries() { } virtual void printProgramHeaders() { } + virtual void printHashTable() { } // Only implemented for ARM ELF at this time. virtual void printAttributes() { } diff --git a/tools/llvm-readobj/StreamWriter.h b/tools/llvm-readobj/StreamWriter.h index 245588ba06006..f3cc57ef940e7 100644 --- a/tools/llvm-readobj/StreamWriter.h +++ b/tools/llvm-readobj/StreamWriter.h @@ -181,8 +181,8 @@ public: startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n'; } - template <typename T_> - void printList(StringRef Label, const SmallVectorImpl<T_> &List) { + template <typename T> + void printList(StringRef Label, const T &List) { startLine() << Label << ": ["; bool Comma = false; for (const auto &Item : List) { diff --git a/tools/llvm-readobj/Win64EHDumper.cpp b/tools/llvm-readobj/Win64EHDumper.cpp index 5a8af4135bd75..f57eea20e2d9c 100644 --- a/tools/llvm-readobj/Win64EHDumper.cpp +++ b/tools/llvm-readobj/Win64EHDumper.cpp @@ -144,8 +144,10 @@ static std::error_code resolveRelocation(const Dumper::Context &Ctx, Ctx.ResolveSymbol(Section, Offset, Symbol, Ctx.UserData)) return EC; - if (std::error_code EC = Symbol.getAddress(ResolvedAddress)) + ErrorOr<uint64_t> ResolvedAddressOrErr = Symbol.getAddress(); + if (std::error_code EC = ResolvedAddressOrErr.getError()) return EC; + ResolvedAddress = *ResolvedAddressOrErr; section_iterator SI = Ctx.COFF.section_begin(); if (std::error_code EC = Symbol.getSection(SI)) diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index c5bccf9796094..12afacb0a858e 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -127,6 +127,10 @@ namespace opts { cl::opt<bool> ProgramHeaders("program-headers", cl::desc("Display ELF program headers")); + // -hash-table + cl::opt<bool> HashTable("hash-table", + cl::desc("Display ELF hash table")); + // -expand-relocs cl::opt<bool> ExpandRelocs("expand-relocs", cl::desc("Expand each shown relocation to multiple lines")); @@ -199,9 +203,7 @@ bool error(std::error_code EC) { } bool relocAddressLess(RelocationRef a, RelocationRef b) { - uint64_t a_addr = a.getOffset(); - uint64_t b_addr = b.getOffset(); - return a_addr < b_addr; + return a.getOffset() < b.getOffset(); } } // namespace llvm @@ -302,6 +304,8 @@ static void dumpObject(const ObjectFile *Obj) { Dumper->printNeededLibraries(); if (opts::ProgramHeaders) Dumper->printProgramHeaders(); + if (opts::HashTable) + Dumper->printHashTable(); if (Obj->getArch() == llvm::Triple::arm && Obj->isELF()) if (opts::ARMAttributes) Dumper->printAttributes(); diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index 98c6f5c4399cd..86f66f89b1595 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -115,8 +115,17 @@ TargetSectionSep("target-section-sep", static cl::list<std::string> SpecificSectionMappings("map-section", - cl::desc("Map a section to a specific address."), - cl::ZeroOrMore); + cl::desc("For -verify only: Map a section to a " + "specific address."), + cl::ZeroOrMore, + cl::Hidden); + +static cl::list<std::string> +DummySymbolMappings("dummy-extern", + cl::desc("For -verify only: Inject a symbol into the extern " + "symbol table."), + cl::ZeroOrMore, + cl::Hidden); /* *** */ @@ -147,10 +156,25 @@ public: // relocations) will get to the data cache but not to the instruction cache. virtual void invalidateInstructionCache(); + void addDummySymbol(const std::string &Name, uint64_t Addr) { + DummyExterns[Name] = Addr; + } + + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override { + auto I = DummyExterns.find(Name); + + if (I != DummyExterns.end()) + return RuntimeDyld::SymbolInfo(I->second, JITSymbolFlags::Exported); + + return RTDyldMemoryManager::findSymbol(Name); + } + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {} void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {} +private: + std::map<std::string, uint64_t> DummyExterns; }; uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, @@ -269,9 +293,10 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) { ErrorOr<StringRef> Name = Sym.getName(); if (!Name) continue; - uint64_t Addr; - if (Sym.getAddress(Addr)) + ErrorOr<uint64_t> AddrOrErr = Sym.getAddress(); + if (!AddrOrErr) continue; + uint64_t Addr = *AddrOrErr; uint64_t Size = P.second; // If we're not using the debug object, compute the address of the @@ -400,7 +425,7 @@ applySpecificSectionMappings(RuntimeDyldChecker &Checker) { for (StringRef Mapping : SpecificSectionMappings) { size_t EqualsIdx = Mapping.find_first_of("="); - StringRef SectionIDStr = Mapping.substr(0, EqualsIdx); + std::string SectionIDStr = Mapping.substr(0, EqualsIdx); size_t ComaIdx = Mapping.find_first_of(","); if (ComaIdx == StringRef::npos) { @@ -409,8 +434,8 @@ applySpecificSectionMappings(RuntimeDyldChecker &Checker) { exit(1); } - StringRef FileName = SectionIDStr.substr(0, ComaIdx); - StringRef SectionName = SectionIDStr.substr(ComaIdx + 1); + std::string FileName = SectionIDStr.substr(0, ComaIdx); + std::string SectionName = SectionIDStr.substr(ComaIdx + 1); uint64_t OldAddrInt; std::string ErrorMsg; @@ -424,11 +449,11 @@ applySpecificSectionMappings(RuntimeDyldChecker &Checker) { void* OldAddr = reinterpret_cast<void*>(static_cast<uintptr_t>(OldAddrInt)); - StringRef NewAddrStr = Mapping.substr(EqualsIdx + 1); + std::string NewAddrStr = Mapping.substr(EqualsIdx + 1); uint64_t NewAddr; - if (NewAddrStr.getAsInteger(0, NewAddr)) { - errs() << "Invalid section address in mapping: " << Mapping << "\n"; + if (StringRef(NewAddrStr).getAsInteger(0, NewAddr)) { + errs() << "Invalid section address in mapping '" << Mapping << "'.\n"; exit(1); } @@ -450,9 +475,9 @@ applySpecificSectionMappings(RuntimeDyldChecker &Checker) { // Defaults to zero. Set to something big // (e.g. 1 << 32) to stress-test stubs, GOTs, etc. // -static void remapSections(const llvm::Triple &TargetTriple, - const TrivialMemoryManager &MemMgr, - RuntimeDyldChecker &Checker) { +static void remapSectionsAndSymbols(const llvm::Triple &TargetTriple, + TrivialMemoryManager &MemMgr, + RuntimeDyldChecker &Checker) { // Set up a work list (section addr/size pairs). typedef std::list<std::pair<void*, uint64_t>> WorklistT; @@ -515,6 +540,27 @@ static void remapSections(const llvm::Triple &TargetTriple, Checker.getRTDyld().mapSectionAddress(CurEntry.first, NextSectionAddr); } + // Add dummy symbols to the memory manager. + for (const auto &Mapping : DummySymbolMappings) { + size_t EqualsIdx = Mapping.find_first_of("="); + + if (EqualsIdx == StringRef::npos) { + errs() << "Invalid dummy symbol specification '" << Mapping + << "'. Should be '<symbol name>=<addr>'\n"; + exit(1); + } + + std::string Symbol = Mapping.substr(0, EqualsIdx); + std::string AddrStr = Mapping.substr(EqualsIdx + 1); + + uint64_t Addr; + if (StringRef(AddrStr).getAsInteger(0, Addr)) { + errs() << "Invalid symbol mapping '" << Mapping << "'.\n"; + exit(1); + } + + MemMgr.addDummySymbol(Symbol, Addr); + } } // Load and link the objects specified on the command line, but do not execute @@ -603,8 +649,9 @@ static int linkAndVerify() { } } - // Re-map the section addresses into the phony target address space. - remapSections(TheTriple, MemMgr, Checker); + // Re-map the section addresses into the phony target address space and add + // dummy symbols. + remapSectionsAndSymbols(TheTriple, MemMgr, Checker); // Resolve all the relocations we can. Dyld.resolveRelocations(); diff --git a/tools/llvm-shlib/CMakeLists.txt b/tools/llvm-shlib/CMakeLists.txt index bc1b658ba7264..54d71d3f63200 100644 --- a/tools/llvm-shlib/CMakeLists.txt +++ b/tools/llvm-shlib/CMakeLists.txt @@ -15,6 +15,8 @@ if(NOT DEFINED LLVM_DYLIB_COMPONENTS) BitWriter CodeGen Core + DebugInfoDWARF + DebugInfoPDB ExecutionEngine IPA IPO diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp index 727d03f9d6ea4..6a1a248a05725 100644 --- a/tools/llvm-stress/llvm-stress.cpp +++ b/tools/llvm-stress/llvm-stress.cpp @@ -31,7 +31,8 @@ #include <set> #include <sstream> #include <vector> -using namespace llvm; + +namespace llvm { static cl::opt<unsigned> SeedCL("seed", cl::desc("Seed used for randomness"), cl::init(0)); @@ -42,16 +43,39 @@ static cl::opt<std::string> OutputFilename("o", cl::desc("Override output filename"), cl::value_desc("filename")); -static cl::opt<bool> GenHalfFloat("generate-half-float", - cl::desc("Generate half-length floating-point values"), cl::init(false)); -static cl::opt<bool> GenX86FP80("generate-x86-fp80", - cl::desc("Generate 80-bit X86 floating-point values"), cl::init(false)); -static cl::opt<bool> GenFP128("generate-fp128", - cl::desc("Generate 128-bit floating-point values"), cl::init(false)); -static cl::opt<bool> GenPPCFP128("generate-ppc-fp128", - cl::desc("Generate 128-bit PPC floating-point values"), cl::init(false)); -static cl::opt<bool> GenX86MMX("generate-x86-mmx", - cl::desc("Generate X86 MMX floating-point values"), cl::init(false)); +namespace cl { +template <> class parser<Type*> final : public basic_parser<Type*> { +public: + parser(Option &O) : basic_parser(O) {} + + // Parse options as IR types. Return true on error. + bool parse(Option &O, StringRef, StringRef Arg, Type *&Value) { + auto &Context = getGlobalContext(); + if (Arg == "half") Value = Type::getHalfTy(Context); + else if (Arg == "fp128") Value = Type::getFP128Ty(Context); + else if (Arg == "x86_fp80") Value = Type::getX86_FP80Ty(Context); + else if (Arg == "ppc_fp128") Value = Type::getPPC_FP128Ty(Context); + else if (Arg == "x86_mmx") Value = Type::getX86_MMXTy(Context); + else if (Arg.startswith("i")) { + unsigned N = 0; + Arg.drop_front().getAsInteger(10, N); + if (N > 0) + Value = Type::getIntNTy(Context, N); + } + + if (!Value) + return O.error("Invalid IR scalar type: '" + Arg + "'!"); + return false; + } + + const char *getValueName() const override { return "IR scalar type"; } +}; +} + + +static cl::list<Type*> AdditionalScalarTypes("types", cl::CommaSeparated, + cl::desc("Additional IR scalar types " + "(always includes i1, i8, i16, i32, i64, float and double)")); namespace { /// A utility class to provide a pseudo-random number generator which is @@ -243,35 +267,22 @@ protected: /// Pick a random scalar type. Type *pickScalarType() { - Type *t = nullptr; - do { - switch (Ran->Rand() % 30) { - case 0: t = Type::getInt1Ty(Context); break; - case 1: t = Type::getInt8Ty(Context); break; - case 2: t = Type::getInt16Ty(Context); break; - case 3: case 4: - case 5: t = Type::getFloatTy(Context); break; - case 6: case 7: - case 8: t = Type::getDoubleTy(Context); break; - case 9: case 10: - case 11: t = Type::getInt32Ty(Context); break; - case 12: case 13: - case 14: t = Type::getInt64Ty(Context); break; - case 15: case 16: - case 17: if (GenHalfFloat) t = Type::getHalfTy(Context); break; - case 18: case 19: - case 20: if (GenX86FP80) t = Type::getX86_FP80Ty(Context); break; - case 21: case 22: - case 23: if (GenFP128) t = Type::getFP128Ty(Context); break; - case 24: case 25: - case 26: if (GenPPCFP128) t = Type::getPPC_FP128Ty(Context); break; - case 27: case 28: - case 29: if (GenX86MMX) t = Type::getX86_MMXTy(Context); break; - default: llvm_unreachable("Invalid scalar value"); - } - } while (t == nullptr); + static std::vector<Type*> ScalarTypes; + if (ScalarTypes.empty()) { + ScalarTypes.assign({ + Type::getInt1Ty(Context), + Type::getInt8Ty(Context), + Type::getInt16Ty(Context), + Type::getInt32Ty(Context), + Type::getInt64Ty(Context), + Type::getFloatTy(Context), + Type::getDoubleTy(Context) + }); + ScalarTypes.insert(ScalarTypes.end(), + AdditionalScalarTypes.begin(), AdditionalScalarTypes.end()); + } - return t; + return ScalarTypes[Ran->Rand() % ScalarTypes.size()]; } /// Basic block to populate @@ -665,9 +676,13 @@ static void IntroduceControlFlow(Function *F, Random &R) { } } +} + int main(int argc, char **argv) { + using namespace llvm; + // Init LLVM, call llvm_shutdown() on exit, parse args, etc. - llvm::PrettyStackTraceProgram X(argc, argv); + PrettyStackTraceProgram X(argc, argv); cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n"); llvm_shutdown_obj Y; diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp index ec3fe4868db33..c57c219b11d23 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.cpp +++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -84,10 +84,10 @@ void ModuleInfo::addSymbol(const SymbolRef &Symbol, uint64_t SymbolSize, SymbolRef::Type SymbolType = Symbol.getType(); if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data) return; - uint64_t SymbolAddress; - if (error(Symbol.getAddress(SymbolAddress)) || - SymbolAddress == UnknownAddress) + ErrorOr<uint64_t> SymbolAddressOrErr = Symbol.getAddress(); + if (error(SymbolAddressOrErr.getError())) return; + uint64_t SymbolAddress = *SymbolAddressOrErr; if (OpdExtractor) { // For big-endian PowerPC64 ELF, symbols in the .opd section refer to // function descriptors. The first word of the descriptor is a pointer to diff --git a/tools/obj2yaml/elf2yaml.cpp b/tools/obj2yaml/elf2yaml.cpp index 9afcedef63982..f117a10d38222 100644 --- a/tools/obj2yaml/elf2yaml.cpp +++ b/tools/obj2yaml/elf2yaml.cpp @@ -40,6 +40,7 @@ class ELFDumper { ErrorOr<ELFYAML::RelocationSection *> dumpRelaSection(const Elf_Shdr *Shdr); ErrorOr<ELFYAML::RawContentSection *> dumpContentSection(const Elf_Shdr *Shdr); + ErrorOr<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr); ErrorOr<ELFYAML::Group *> dumpGroup(const Elf_Shdr *Shdr); ErrorOr<ELFYAML::MipsABIFlags *> dumpMipsABIFlags(const Elf_Shdr *Shdr); @@ -104,6 +105,13 @@ ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() { Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(G.get())); break; } + case ELF::SHT_NOBITS: { + ErrorOr<ELFYAML::NoBitsSection *> S = dumpNoBitsSection(&Sec); + if (std::error_code EC = S.getError()) + return EC; + Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get())); + break; + } default: { ErrorOr<ELFYAML::RawContentSection *> S = dumpContentSection(&Sec); if (std::error_code EC = S.getError()) @@ -305,6 +313,18 @@ ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) { } template <class ELFT> +ErrorOr<ELFYAML::NoBitsSection *> +ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) { + auto S = make_unique<ELFYAML::NoBitsSection>(); + + if (std::error_code EC = dumpCommonSection(Shdr, *S)) + return EC; + S->Size = Shdr->sh_size; + + return S.release(); +} + +template <class ELFT> ErrorOr<ELFYAML::Group *> ELFDumper<ELFT>::dumpGroup(const Elf_Shdr *Shdr) { auto S = make_unique<ELFYAML::Group>(); diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index 55426e7b27435..0db60d1444099 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -324,6 +324,7 @@ int main(int argc, char **argv) { initializeRewriteSymbolsPass(Registry); initializeWinEHPreparePass(Registry); initializeDwarfEHPreparePass(Registry); + initializeSjLjEHPreparePass(Registry); #ifdef LINK_POLLY_INTO_TOOLS polly::initializePollyPasses(Registry); diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp index 772b5b918ecab..a247f48c053dc 100644 --- a/tools/yaml2obj/yaml2elf.cpp +++ b/tools/yaml2obj/yaml2elf.cpp @@ -35,6 +35,8 @@ class ContiguousBlobAccumulator { /// \returns The new offset. uint64_t padToAlignment(unsigned Align) { + if (Align == 0) + Align = 1; uint64_t CurrentOffset = InitialOffset + OS.tell(); uint64_t AlignedOffset = RoundUpToAlignment(CurrentOffset, Align); for (; CurrentOffset != AlignedOffset; ++CurrentOffset) @@ -46,7 +48,7 @@ public: ContiguousBlobAccumulator(uint64_t InitialOffset_) : InitialOffset(InitialOffset_), Buf(), OS(Buf) {} template <class Integer> - raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align = 16) { + raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) { Offset = padToAlignment(Align); return OS; } @@ -241,6 +243,12 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, } else if (auto S = dyn_cast<ELFYAML::MipsABIFlags>(Sec.get())) { if (!writeSectionContent(SHeader, *S, CBA)) return false; + } else if (auto S = dyn_cast<ELFYAML::NoBitsSection>(Sec.get())) { + SHeader.sh_entsize = 0; + SHeader.sh_size = S->Size; + // SHT_NOBITS section does not have content + // so just to setup the section offset. + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); } else llvm_unreachable("Unknown section type"); @@ -259,6 +267,7 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, // One greater than symbol table index of the last local symbol. SHeader.sh_info = Doc.Symbols.Local.size() + 1; SHeader.sh_entsize = sizeof(Elf_Sym); + SHeader.sh_addralign = 8; std::vector<Elf_Sym> Syms; { @@ -281,8 +290,9 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL); addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK); - writeArrayData(CBA.getOSAndAlignedOffset(SHeader.sh_offset), - makeArrayRef(Syms)); + writeArrayData( + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign), + makeArrayRef(Syms)); SHeader.sh_size = arrayDataSize(makeArrayRef(Syms)); } @@ -293,7 +303,8 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, zero(SHeader); SHeader.sh_name = DotShStrtab.getOffset(Name); SHeader.sh_type = ELF::SHT_STRTAB; - CBA.getOSAndAlignedOffset(SHeader.sh_offset) << STB.data(); + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign) + << STB.data(); SHeader.sh_size = STB.data().size(); SHeader.sh_addralign = 1; } @@ -331,7 +342,8 @@ ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, ContiguousBlobAccumulator &CBA) { assert(Section.Size >= Section.Content.binary_size() && "Section size and section content are inconsistent"); - raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset); + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); Section.Content.writeAsBinary(OS); for (auto i = Section.Content.binary_size(); i < Section.Size; ++i) OS.write(0); @@ -358,7 +370,7 @@ ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, SHeader.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); SHeader.sh_size = SHeader.sh_entsize * Section.Relocations.size(); - auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset); + auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); for (const auto &Rel : Section.Relocations) { unsigned SymIdx = 0; @@ -396,7 +408,7 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, SHeader.sh_entsize = sizeof(Elf_Word); SHeader.sh_size = SHeader.sh_entsize * Section.Members.size(); - auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset); + auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); for (auto member : Section.Members) { Elf_Word SIdx; @@ -427,7 +439,7 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, SHeader.sh_entsize = sizeof(Flags); SHeader.sh_size = SHeader.sh_entsize; - auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset); + auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); Flags.version = Section.Version; Flags.isa_level = Section.ISALevel; Flags.isa_rev = Section.ISARevision; |