llvm.org GIT mirror llvm / cdfe54f
Add the option, -archive-headers, used with -macho to print the Mach-O archive headers to llvm-objdump. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226228 91177308-0d34-0410-b5e6-96231b3b80d8 Kevin Enderby 4 years ago
6 changed file(s) with 151 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
4040
4141 sys::fs::perms getAccessMode() const;
4242 sys::TimeValue getLastModified() const;
43 llvm::StringRef getRawLastModified() const {
44 return StringRef(LastModified, sizeof(LastModified)).rtrim(" ");
45 }
4346 unsigned getUID() const;
4447 unsigned getGID() const;
4548 };
7780 sys::TimeValue getLastModified() const {
7881 return getHeader()->getLastModified();
7982 }
83 StringRef getRawLastModified() const {
84 return getHeader()->getRawLastModified();
85 }
8086 unsigned getUID() const { return getHeader()->getUID(); }
8187 unsigned getGID() const { return getHeader()->getGID(); }
8288 sys::fs::perms getAccessMode() const {
8490 }
8591 /// \return the size of the archive member without the header or padding.
8692 uint64_t getSize() const;
93 /// \return the size of the archive member with the header and padding.
94 uint64_t getRawSize() const;
8795
8896 StringRef getBuffer() const {
8997 return StringRef(Data.data() + StartOfFile, getSize());
9098 }
99 uint64_t getChildOffset() const;
91100
92101 ErrorOr getMemoryBufferRef() const;
93102
193202 child_iterator findSym(StringRef name) const;
194203
195204 bool hasSymbolTable() const;
205 child_iterator getSymbolTableChild() const { return SymbolTable; }
196206
197207 private:
198208 child_iterator SymbolTable;
109109 return Data.size() - StartOfFile;
110110 }
111111
112 uint64_t Archive::Child::getRawSize() const {
113 if (Parent->IsThin)
114 return getHeader()->getSize();
115 return Data.size();
116 }
117
112118 Archive::Child Archive::Child::getNext() const {
113119 size_t SpaceToSkip = Data.size();
114120 // If it's odd, add 1 to make it even.
122128 return Child(Parent, nullptr);
123129
124130 return Child(Parent, NextLoc);
131 }
132
133 uint64_t Archive::Child::getChildOffset() const {
134 const char *a = Parent->Data.getBuffer().data();
135 const char *c = Data.data();
136 uint64_t offset = c - a;
137 return offset;
125138 }
126139
127140 ErrorOr Archive::Child::getName() const {
0 RUN: llvm-objdump %p/Inputs/macho-universal-archive.x86_64.i386 -macho -archive-headers -arch all \
1 RUN: | FileCheck %s
2
3 # Note the date as printed by ctime(3) is time zone dependent and not checked.
4 CHECK: Archive : {{.*}}/macho-universal-archive.x86_64.i386 (architecture x86_64)
5 CHECK: -rw-r--r--124/11 44 {{.*}} __.SYMDEF SORTED
6 CHECK: -rw-r--r--124/0 860 {{.*}} hello.o
7 CHECK: Archive : {{.*}}/macho-universal-archive.x86_64.i386 (architecture i386)
8 CHECK: -rw-r--r--124/11 60 {{.*}} __.SYMDEF SORTED
9 CHECK: -rw-r--r--124/0 388 {{.*}} foo.o
6565 PrintImmHex("print-imm-hex",
6666 cl::desc("Use hex format for immediate values"));
6767
68 cl::opt llvm::UniversalHeaders("universal-headers",
69 cl::desc("Print Mach-O universal headers "
70 "(requires -macho)"));
71
6872 cl::opt
69 llvm::UniversalHeaders("universal-headers",
70 cl::desc("Print Mach-O universal headers"));
73 llvm::ArchiveHeaders("archive-headers",
74 cl::desc("Print archive headers for Mach-O archives "
75 "(requires -macho)"));
7176
7277 static cl::list
7378 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
513518 }
514519 }
515520
521 static void printArchiveChild(Archive::Child &C, bool verbose,
522 bool print_offset) {
523 if (print_offset)
524 outs() << C.getChildOffset() << "\t";
525 sys::fs::perms Mode = C.getAccessMode();
526 if (verbose) {
527 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
528 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
529 outs() << "-";
530 if (Mode & sys::fs::owner_read)
531 outs() << "r";
532 else
533 outs() << "-";
534 if (Mode & sys::fs::owner_write)
535 outs() << "w";
536 else
537 outs() << "-";
538 if (Mode & sys::fs::owner_exe)
539 outs() << "x";
540 else
541 outs() << "-";
542 if (Mode & sys::fs::group_read)
543 outs() << "r";
544 else
545 outs() << "-";
546 if (Mode & sys::fs::group_write)
547 outs() << "w";
548 else
549 outs() << "-";
550 if (Mode & sys::fs::group_exe)
551 outs() << "x";
552 else
553 outs() << "-";
554 if (Mode & sys::fs::others_read)
555 outs() << "r";
556 else
557 outs() << "-";
558 if (Mode & sys::fs::others_write)
559 outs() << "w";
560 else
561 outs() << "-";
562 if (Mode & sys::fs::others_exe)
563 outs() << "x";
564 else
565 outs() << "-";
566 } else {
567 outs() << format("0%o ", Mode);
568 }
569
570 unsigned UID = C.getUID();
571 outs() << format("%3d/", UID);
572 unsigned GID = C.getGID();
573 outs() << format("%-3d ", GID);
574 uint64_t Size = C.getRawSize() - sizeof(object::ArchiveMemberHeader);
575 outs() << format("%5d ", Size);
576
577 StringRef RawLastModified = C.getRawLastModified();
578 if (verbose) {
579 unsigned Seconds;
580 if (RawLastModified.getAsInteger(10, Seconds))
581 outs() << "(date: \"%s\" contains non-decimal chars) " << RawLastModified;
582 else {
583 // Since cime(3) returns a 26 character string of the form:
584 // "Sun Sep 16 01:03:52 1973\n\0"
585 // just print 24 characters.
586 time_t t = Seconds;
587 outs() << format("%.24s ", ctime(&t));
588 }
589 } else {
590 outs() << RawLastModified << " ";
591 }
592
593 if (verbose) {
594 ErrorOr NameOrErr = C.getName();
595 if (NameOrErr.getError()) {
596 StringRef RawName = C.getRawName();
597 outs() << RawName << "\n";
598 } else {
599 StringRef Name = NameOrErr.get();
600 outs() << Name << "\n";
601 }
602 } else {
603 StringRef RawName = C.getRawName();
604 outs() << RawName << "\n";
605 }
606 }
607
608 static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) {
609 if (A->hasSymbolTable()) {
610 Archive::child_iterator S = A->getSymbolTableChild();
611 Archive::Child C = *S;
612 printArchiveChild(C, verbose, print_offset);
613 }
614 for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E;
615 ++I) {
616 Archive::Child C = *I;
617 printArchiveChild(C, verbose, print_offset);
618 }
619 }
620
516621 // ParseInputMachO() parses the named Mach-O file in Filename and handles the
517622 // -arch flags selecting just those slices as specified by them and also parses
518623 // archive files. Then for each individual Mach-O file ProcessMachO() is
541646
542647 if (Archive *A = dyn_cast(&Bin)) {
543648 outs() << "Archive : " << Filename << "\n";
649 if (ArchiveHeaders)
650 printArchiveHeaders(A, true, false);
544651 for (Archive::child_iterator I = A->child_begin(), E = A->child_end();
545652 I != E; ++I) {
546653 ErrorOr> ChildOrErr = I->getAsBinary();
586693 if (!ArchitectureName.empty())
587694 outs() << " (architecture " << ArchitectureName << ")";
588695 outs() << "\n";
696 if (ArchiveHeaders)
697 printArchiveHeaders(A.get(), true, false);
589698 for (Archive::child_iterator AI = A->child_begin(),
590699 AE = A->child_end();
591700 AI != AE; ++AI) {
626735 I->getAsArchive()) {
627736 std::unique_ptr &A = *AOrErr;
628737 outs() << "Archive : " << Filename << "\n";
738 if (ArchiveHeaders)
739 printArchiveHeaders(A.get(), true, false);
629740 for (Archive::child_iterator AI = A->child_begin(),
630741 AE = A->child_end();
631742 AI != AE; ++AI) {
661772 if (!ArchitectureName.empty())
662773 outs() << " (architecture " << ArchitectureName << ")";
663774 outs() << "\n";
775 if (ArchiveHeaders)
776 printArchiveHeaders(A.get(), true, false);
664777 for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end();
665778 AI != AE; ++AI) {
666779 ErrorOr> ChildOrErr = AI->getAsBinary();
891891 && !Bind
892892 && !LazyBind
893893 && !WeakBind
894 && !(UniversalHeaders && MachOOpt)) {
894 && !(UniversalHeaders && MachOOpt)
895 && !(ArchiveHeaders && MachOOpt)) {
895896 cl::PrintHelpMessage();
896897 return 2;
897898 }
3434 extern cl::opt LazyBind;
3535 extern cl::opt WeakBind;
3636 extern cl::opt UniversalHeaders;
37 extern cl::opt ArchiveHeaders;
3738
3839 // Various helper functions.
3940 bool error(std::error_code ec);