From ab669421b20cbd5e5de2544d04781d0d1fc7c23b Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 21 Sep 2017 16:26:18 +0000 Subject: [PATCH] llvm-dwarfdump: Add support for the --arch command line option. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313888 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/tools/llvm-dwarfdump/X86/archive.test | 15 ++++- tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 73 +++++++++++++++++----- 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/test/tools/llvm-dwarfdump/X86/archive.test b/test/tools/llvm-dwarfdump/X86/archive.test index d5e053fd391..4ea5e3e4c20 100644 --- a/test/tools/llvm-dwarfdump/X86/archive.test +++ b/test/tools/llvm-dwarfdump/X86/archive.test @@ -1,5 +1,18 @@ -RUN: llvm-dwarfdump --debug-info %S/../../dsymutil/Inputs/libfat-test.a | FileCheck %s +RUN: llvm-dwarfdump --debug-info %S/../../dsymutil/Inputs/libfat-test.a \ +RUN: | FileCheck %s CHECK: libfat-test.a(x86_64)(fat-test.o): file format Mach-O 64-bit x86-64 CHECK: .debug_info contents: CHECK: libfat-test.a(i386)(fat-test.o): file format Mach-O 32-bit i386 CHECK: .debug_info contents: + +RUN: llvm-dwarfdump --debug-info %S/../../dsymutil/Inputs/libfat-test.a \ +RUN: --arch=i386 | FileCheck %s --check-prefix=I386 +I386-NOT: 64-bit +I386: file format Mach-O 32-bit i386 +I386-NOT: 64-bit + +RUN: llvm-dwarfdump --debug-info %S/../../dsymutil/Inputs/libfat-test.a \ +RUN: --arch=i386 --arch=x86_64 | FileCheck %s + +RUN: llvm-dwarfdump --debug-info %S/../../dsymutil/Inputs/libfat-test.a \ +RUN: --arch=7 | FileCheck %s --check-prefix=I386 diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 0f75f36af7e..5c9fe2421be 100644 --- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -126,6 +126,13 @@ static std::array, (unsigned)DIDT_ID_Count> static alias DumpDebugFrameAlias("eh-frame", desc("Alias for -debug-frame"), NotHidden, cat(SectionCategory), aliasopt(DumpDebugFrame)); +static list + ArchFilters("arch", + desc("Dump debug information for the specified CPU " + "architecture only. Architectures may be specified by " + "name or by number. This option can be specified " + "multiple times, once for each desired architecture."), + cat(DwarfDumpCategory)); static opt DumpUUID("uuid", desc("Show the UUID for each architecture"), cat(DwarfDumpCategory)); static alias DumpUUIDAlias("u", desc("Alias for -uuid"), aliasopt(DumpUUID)); @@ -190,28 +197,55 @@ static DIDumpOptions getDumpOpts() { return DumpOpts; } -static bool dumpObjectFile(ObjectFile &Obj, Twine Filename) { - std::unique_ptr DICtx = DWARFContext::create(Obj); - logAllUnhandledErrors(DICtx->loadRegisterInfo(Obj), errs(), +static uint32_t getCPUType(MachOObjectFile &MachO) { + if (MachO.is64Bit()) + return MachO.getHeader64().cputype; + else + return MachO.getHeader().cputype; +} + +/// Return true if the object file has not been filtered by an --arch option. +static bool filterArch(ObjectFile &Obj) { + if (ArchFilters.empty()) + return true; + if (auto *MachO = dyn_cast(&Obj)) { + std::string ObjArch = + Triple::getArchTypeName(MachO->getArchTriple().getArch()); + for (auto Arch : ArchFilters) { + if (Arch == ObjArch) + return true; + unsigned Value; + if (!StringRef(Arch).getAsInteger(0, Value)) + if (Value == getCPUType(*MachO)) + return true; + } + } + return false; +} + +using HandlerFn = std::function; + +static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx, + Twine Filename) { + logAllUnhandledErrors(DICtx.loadRegisterInfo(Obj), errs(), Filename.str() + ": "); // The UUID dump already contains all the same information. if (!(DumpType & DIDT_UUID) || DumpType == DIDT_All) outs() << Filename << ":\tfile format " << Obj.getFileFormatName() << '\n'; // Dump the complete DWARF structure. - DICtx->dump(outs(), getDumpOpts(), DumpOffsets); + DICtx.dump(outs(), getDumpOpts(), DumpOffsets); return true; } -static bool verifyObjectFile(ObjectFile &Obj, Twine Filename) { - std::unique_ptr DICtx = DWARFContext::create(Obj); - +static bool verifyObjectFile(ObjectFile &Obj, DWARFContext &DICtx, + Twine Filename) { // Verify the DWARF and exit with non-zero exit status if verification // fails. raw_ostream &stream = Quiet ? nulls() : outs(); stream << "Verifying " << Filename.str() << ":\tfile format " << Obj.getFileFormatName() << "\n"; - bool Result = DICtx->verify(stream, getDumpOpts()); + bool Result = DICtx.verify(stream, getDumpOpts()); if (Result) stream << "No errors.\n"; else @@ -220,10 +254,10 @@ static bool verifyObjectFile(ObjectFile &Obj, Twine Filename) { } static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer, - std::function HandleObj); + HandlerFn HandleObj); static bool handleArchive(StringRef Filename, Archive &Arch, - std::function HandleObj) { + HandlerFn HandleObj) { bool Result = true; Error Err = Error::success(); for (auto Child : Arch.children(Err)) { @@ -240,19 +274,27 @@ static bool handleArchive(StringRef Filename, Archive &Arch, } static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer, - std::function HandleObj) { + HandlerFn HandleObj) { Expected> BinOrErr = object::createBinary(Buffer); error(Filename, errorToErrorCode(BinOrErr.takeError())); bool Result = true; - if (auto *Obj = dyn_cast(BinOrErr->get())) - Result = HandleObj(*Obj, Filename); + if (auto *Obj = dyn_cast(BinOrErr->get())) { + if (filterArch(*Obj)) { + std::unique_ptr DICtx = DWARFContext::create(*Obj); + Result = HandleObj(*Obj, *DICtx, Filename); + } + } else if (auto *Fat = dyn_cast(BinOrErr->get())) for (auto &ObjForArch : Fat->objects()) { std::string ObjName = (Filename + "(" + ObjForArch.getArchFlagName() + ")").str(); if (auto MachOOrErr = ObjForArch.getAsObjectFile()) { - Result &= HandleObj(**MachOOrErr, ObjName); + auto &Obj = **MachOOrErr; + if (filterArch(Obj)) { + std::unique_ptr DICtx = DWARFContext::create(Obj); + Result &= HandleObj(Obj, *DICtx, ObjName); + } continue; } else consumeError(MachOOrErr.takeError()); @@ -268,8 +310,7 @@ static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer, return Result; } -static bool handleFile(StringRef Filename, - std::function HandleObj) { +static bool handleFile(StringRef Filename, HandlerFn HandleObj) { ErrorOr> BuffOrErr = MemoryBuffer::getFileOrSTDIN(Filename); error(Filename, BuffOrErr.getError()); -- 2.49.0