Index: test/tools/llvm-objdump/archive-headers-disas.test =================================================================== --- /dev/null +++ test/tools/llvm-objdump/archive-headers-disas.test @@ -0,0 +1,50 @@ +# RUN: llvm-objdump -a -d %p/Inputs/liblong_filenames.a | FileCheck %s + +# CHECK: rw-r--r-- 204299/200 1416 Tue Oct 30 15:33:29 2012 1.o +# CHECK: Disassembly of section .text: +# CHECK: main: +# CHECK: 0: 55 pushq %rbp +# CHECK: 1: 48 89 e5 movq %rsp, %rbp +# CHECK: 4: b8 00 00 00 00 movl $0, %eax +# CHECK: 9: e8 00 00 00 00 callq 0 +# CHECK: e: 5d popq %rbp +# CHECK: f: c3 retq + +# CHECK: rw-r--r-- 204299/200 1224 Tue Oct 30 15:33:29 2012 2.o +# CHECK: Disassembly of section .text: +# CHECK: fn1: +# CHECK: 0: 55 pushq %rbp +# CHECK: 1: 48 89 e5 movq %rsp, %rbp +# CHECK: 4: b8 00 00 00 00 movl $0, %eax +# CHECK: 9: 5d popq %rbp +# CHECK: a: c3 retq + +# CHECK: rw-r--r-- 204299/200 1312 Tue Oct 30 15:33:29 2012 3.o +# CHECK: Disassembly of section .text: +# CHECK: fn3: +# CHECK: 0: 55 pushq %rbp +# CHECK: 1: 48 89 e5 movq %rsp, %rbp +# CHECK: 4: b8 00 00 00 00 movl $0, %eax +# CHECK: 9: 5d popq %rbp +# CHECK: a: c3 retq +# CHECK: fn1: +# CHECK: b: 55 pushq %rbp +# CHECK: c: 48 89 e5 movq %rsp, %rbp +# CHECK: f: 5d popq %rbp +# CHECK: 10: c3 retq + +# CHECK: rw-r--r-- 204299/200 957 Tue Oct 30 15:33:29 2012 4.o +# CHECK: rw-r--r-- 204299/200 951 Tue Oct 30 15:33:29 2012 5.o +# CHECK: rw-r--r-- 204299/200 951 Tue Oct 30 15:33:29 2012 6.o +# CHECK: rw-r--r-- 204299/200 977 Tue Oct 30 15:33:29 2012 abcdefghijklmnopqrstuvwxyz1.o + +# CHECK: rw-r--r-- 204299/200 1272 Tue Oct 30 15:33:29 2012 abcdefghijklmnopqrstuvwxyz2.o +# CHECK: Disassembly of section .text: +# CHECK: bda: +# CHECK: 0: 55 pushq %rbp +# CHECK: 1: 48 89 e5 movq %rsp, %rbp +# CHECK: 4: b8 00 00 00 00 movl $0, %eax +# CHECK: 9: 5d popq %rbp +# CHECK: a: c3 retq + +# CHECK: rw-r--r-- 204299/200 977 Tue Oct 30 15:29:33 2012 abcdefghijklmnopq.o Index: test/tools/llvm-objdump/archive-headers.test =================================================================== --- /dev/null +++ test/tools/llvm-objdump/archive-headers.test @@ -0,0 +1,12 @@ +# RUN: llvm-objdump -a %p/Inputs/liblong_filenames.a | FileCheck %s +# RUN: llvm-objdump -archive-headers %p/Inputs/liblong_filenames.a | FileCheck %s + +# CHECK: rw-r--r-- 204299/200 1416 Tue Oct 30 15:33:29 2012 1.o +# CHECK: rw-r--r-- 204299/200 1224 Tue Oct 30 15:33:29 2012 2.o +# CHECK: rw-r--r-- 204299/200 1312 Tue Oct 30 15:33:29 2012 3.o +# CHECK: rw-r--r-- 204299/200 957 Tue Oct 30 15:33:29 2012 4.o +# CHECK: rw-r--r-- 204299/200 951 Tue Oct 30 15:33:29 2012 5.o +# CHECK: rw-r--r-- 204299/200 951 Tue Oct 30 15:33:29 2012 6.o +# CHECK: rw-r--r-- 204299/200 977 Tue Oct 30 15:33:29 2012 abcdefghijklmnopqrstuvwxyz1.o +# CHECK: rw-r--r-- 204299/200 1272 Tue Oct 30 15:33:29 2012 abcdefghijklmnopqrstuvwxyz2.o +# CHECK: rw-r--r-- 204299/200 977 Tue Oct 30 15:29:33 2012 abcdefghijklmnopq.o Index: tools/llvm-objdump/MachODump.cpp =================================================================== --- tools/llvm-objdump/MachODump.cpp +++ tools/llvm-objdump/MachODump.cpp @@ -75,11 +75,6 @@ cl::desc("Print Mach-O universal headers " "(requires -macho)")); -cl::opt - llvm::ArchiveHeaders("archive-headers", - cl::desc("Print archive headers for Mach-O archives " - "(requires -macho)")); - cl::opt ArchiveMemberOffsets("archive-member-offsets", cl::desc("Print the offset to each archive member for " Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -207,6 +207,14 @@ static cl::alias FileHeadersShort("f", cl::desc("Alias for --file-headers"), cl::aliasopt(FileHeaders)); +cl::opt + llvm::ArchiveHeaders("archive-headers", + cl::desc("Print archive headers for Mach-O archives ")); + +cl::alias +ArchiveHeadersShort("a", cl::desc("Alias for --archive-headers"), + cl::aliasopt(ArchiveHeaders)); + cl::opt llvm::PrintImmHex("print-imm-hex", cl::desc("Use hex format for immediate values")); @@ -2144,7 +2152,72 @@ << "\n"; } -static void DumpObject(ObjectFile *o, const Archive *a = nullptr) { +static void printArchiveChild(StringRef Filename, const Archive::Child &C) { + Expected ModeOrErr = C.getAccessMode(); + if (!ModeOrErr) { + consumeError(ModeOrErr.takeError()); + outs() << "ill-formed archive entry.\n"; + return; + } + sys::fs::perms Mode = ModeOrErr.get(); + outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); + outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); + outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); + outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); + outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); + outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); + outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); + outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); + outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); + + outs() << " "; + + Expected UIDOrErr = C.getUID(); + if (!UIDOrErr) + report_error(Filename, UIDOrErr.takeError()); + unsigned UID = UIDOrErr.get(); + outs() << format("%d/", UID); + + Expected GIDOrErr = C.getGID(); + if (!GIDOrErr) + report_error(Filename, GIDOrErr.takeError()); + unsigned GID = GIDOrErr.get(); + outs() << format("%-d ", GID); + + Expected Size = C.getRawSize(); + if (!Size) + report_error(Filename, Size.takeError()); + outs() << format("%6" PRId64, Size.get()) << " "; + + StringRef RawLastModified = C.getRawLastModified(); + unsigned Seconds; + if (RawLastModified.getAsInteger(10, Seconds)) + outs() << "(date: \"" << RawLastModified + << "\" contains non-decimal chars) "; + else { + // Since ctime(3) returns a 26 character string of the form: + // "Sun Sep 16 01:03:52 1973\n\0" + // just print 24 characters. + time_t t = Seconds; + outs() << format("%.24s ", ctime(&t)); + } + + StringRef Name = ""; + Expected NameOrErr = C.getName(); + if (!NameOrErr) { + consumeError(NameOrErr.takeError()); + Expected RawNameOrErr = C.getRawName(); + if (!RawNameOrErr) + report_error(Filename, NameOrErr.takeError()); + Name = RawNameOrErr.get(); + } else { + Name = NameOrErr.get(); + } + outs() << Name << "\n"; +} + +static void DumpObject(ObjectFile *o, const Archive *a = nullptr, + const Archive::Child *c = nullptr) { StringRef ArchiveName = a != nullptr ? a->getFileName() : ""; // Avoid other output when using a raw option. if (!RawClangAST) { @@ -2153,9 +2226,13 @@ outs() << a->getFileName() << "(" << o->getFileName() << ")"; else outs() << o->getFileName(); - outs() << ":\tfile format " << o->getFileFormatName() << "\n\n"; + outs() << ":\tfile format " << o->getFileFormatName() << "\n"; + if (!ArchiveHeaders || MachOOpt) + outs() << "\n"; } + if (ArchiveHeaders && !MachOOpt) + printArchiveChild(a->getFileName(), *c); if (Disassemble) DisassembleObject(o, Relocations); if (Relocations && !Disassemble) @@ -2197,7 +2274,8 @@ } } -static void DumpObject(const COFFImportFile *I, const Archive *A) { +static void DumpObject(const COFFImportFile *I, const Archive *A, + const Archive::Child *C = nullptr) { StringRef ArchiveName = A ? A->getFileName() : ""; // Avoid other output when using a raw option. @@ -2207,6 +2285,8 @@ << ":\tfile format COFF-import-file" << "\n\n"; + if (ArchiveHeaders && !MachOOpt) + printArchiveChild(A->getFileName(), *C); if (SymbolTable) printCOFFSymbolTable(I); } @@ -2222,9 +2302,9 @@ continue; } if (ObjectFile *o = dyn_cast(&*ChildOrErr.get())) - DumpObject(o, a); + DumpObject(o, a, &C); else if (COFFImportFile *I = dyn_cast(&*ChildOrErr.get())) - DumpObject(I, a); + DumpObject(I, a, &C); else report_error(a->getFileName(), object_error::invalid_file_type); } @@ -2299,7 +2379,7 @@ && !WeakBind && !RawClangAST && !(UniversalHeaders && MachOOpt) - && !(ArchiveHeaders && MachOOpt) + && !ArchiveHeaders && !(IndirectSymbols && MachOOpt) && !(DataInCode && MachOOpt) && !(LinkOptHints && MachOOpt)