Add the option, -archive-headers, used with -macho to print the Mach-O archive headers to llvm-objdump.

llvm-svn: 226228
This commit is contained in:
Kevin Enderby 2015-01-15 23:19:11 +00:00
parent cb92c19fc4
commit 13023a1af6
6 changed files with 151 additions and 3 deletions

View File

@ -41,6 +41,9 @@ struct ArchiveMemberHeader {
sys::fs::perms getAccessMode() const;
sys::TimeValue getLastModified() const;
llvm::StringRef getRawLastModified() const {
return StringRef(LastModified, sizeof(LastModified)).rtrim(" ");
}
unsigned getUID() const;
unsigned getGID() const;
};
@ -78,6 +81,9 @@ public:
sys::TimeValue getLastModified() const {
return getHeader()->getLastModified();
}
StringRef getRawLastModified() const {
return getHeader()->getRawLastModified();
}
unsigned getUID() const { return getHeader()->getUID(); }
unsigned getGID() const { return getHeader()->getGID(); }
sys::fs::perms getAccessMode() const {
@ -85,10 +91,13 @@ public:
}
/// \return the size of the archive member without the header or padding.
uint64_t getSize() const;
/// \return the size of the archive member with the header and padding.
uint64_t getRawSize() const;
StringRef getBuffer() const {
return StringRef(Data.data() + StartOfFile, getSize());
}
uint64_t getChildOffset() const;
ErrorOr<MemoryBufferRef> getMemoryBufferRef() const;
@ -194,6 +203,7 @@ public:
child_iterator findSym(StringRef name) const;
bool hasSymbolTable() const;
child_iterator getSymbolTableChild() const { return SymbolTable; }
private:
child_iterator SymbolTable;

View File

@ -110,6 +110,12 @@ uint64_t Archive::Child::getSize() const {
return Data.size() - StartOfFile;
}
uint64_t Archive::Child::getRawSize() const {
if (Parent->IsThin)
return getHeader()->getSize();
return Data.size();
}
Archive::Child Archive::Child::getNext() const {
size_t SpaceToSkip = Data.size();
// If it's odd, add 1 to make it even.
@ -125,6 +131,13 @@ Archive::Child Archive::Child::getNext() const {
return Child(Parent, NextLoc);
}
uint64_t Archive::Child::getChildOffset() const {
const char *a = Parent->Data.getBuffer().data();
const char *c = Data.data();
uint64_t offset = c - a;
return offset;
}
ErrorOr<StringRef> Archive::Child::getName() const {
StringRef name = getRawName();
// Check if it's a special name.

View File

@ -0,0 +1,10 @@
RUN: llvm-objdump %p/Inputs/macho-universal-archive.x86_64.i386 -macho -archive-headers -arch all \
RUN: | FileCheck %s
# Note the date as printed by ctime(3) is time zone dependent and not checked.
CHECK: Archive : {{.*}}/macho-universal-archive.x86_64.i386 (architecture x86_64)
CHECK: -rw-r--r--124/11 44 {{.*}} __.SYMDEF SORTED
CHECK: -rw-r--r--124/0 860 {{.*}} hello.o
CHECK: Archive : {{.*}}/macho-universal-archive.x86_64.i386 (architecture i386)
CHECK: -rw-r--r--124/11 60 {{.*}} __.SYMDEF SORTED
CHECK: -rw-r--r--124/0 388 {{.*}} foo.o

View File

@ -66,9 +66,14 @@ static cl::opt<bool>
PrintImmHex("print-imm-hex",
cl::desc("Use hex format for immediate values"));
cl::opt<bool> llvm::UniversalHeaders("universal-headers",
cl::desc("Print Mach-O universal headers "
"(requires -macho)"));
cl::opt<bool>
llvm::UniversalHeaders("universal-headers",
cl::desc("Print Mach-O universal headers"));
llvm::ArchiveHeaders("archive-headers",
cl::desc("Print archive headers for Mach-O archives "
"(requires -macho)"));
static cl::list<std::string>
ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
@ -514,6 +519,106 @@ static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
}
}
static void printArchiveChild(Archive::Child &C, bool verbose,
bool print_offset) {
if (print_offset)
outs() << C.getChildOffset() << "\t";
sys::fs::perms Mode = C.getAccessMode();
if (verbose) {
// FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
// But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
outs() << "-";
if (Mode & sys::fs::owner_read)
outs() << "r";
else
outs() << "-";
if (Mode & sys::fs::owner_write)
outs() << "w";
else
outs() << "-";
if (Mode & sys::fs::owner_exe)
outs() << "x";
else
outs() << "-";
if (Mode & sys::fs::group_read)
outs() << "r";
else
outs() << "-";
if (Mode & sys::fs::group_write)
outs() << "w";
else
outs() << "-";
if (Mode & sys::fs::group_exe)
outs() << "x";
else
outs() << "-";
if (Mode & sys::fs::others_read)
outs() << "r";
else
outs() << "-";
if (Mode & sys::fs::others_write)
outs() << "w";
else
outs() << "-";
if (Mode & sys::fs::others_exe)
outs() << "x";
else
outs() << "-";
} else {
outs() << format("0%o ", Mode);
}
unsigned UID = C.getUID();
outs() << format("%3d/", UID);
unsigned GID = C.getGID();
outs() << format("%-3d ", GID);
uint64_t Size = C.getRawSize() - sizeof(object::ArchiveMemberHeader);
outs() << format("%5d ", Size);
StringRef RawLastModified = C.getRawLastModified();
if (verbose) {
unsigned Seconds;
if (RawLastModified.getAsInteger(10, Seconds))
outs() << "(date: \"%s\" contains non-decimal chars) " << RawLastModified;
else {
// Since cime(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));
}
} else {
outs() << RawLastModified << " ";
}
if (verbose) {
ErrorOr<StringRef> NameOrErr = C.getName();
if (NameOrErr.getError()) {
StringRef RawName = C.getRawName();
outs() << RawName << "\n";
} else {
StringRef Name = NameOrErr.get();
outs() << Name << "\n";
}
} else {
StringRef RawName = C.getRawName();
outs() << RawName << "\n";
}
}
static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) {
if (A->hasSymbolTable()) {
Archive::child_iterator S = A->getSymbolTableChild();
Archive::Child C = *S;
printArchiveChild(C, verbose, print_offset);
}
for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E;
++I) {
Archive::Child C = *I;
printArchiveChild(C, verbose, print_offset);
}
}
// ParseInputMachO() parses the named Mach-O file in Filename and handles the
// -arch flags selecting just those slices as specified by them and also parses
// archive files. Then for each individual Mach-O file ProcessMachO() is
@ -542,6 +647,8 @@ void llvm::ParseInputMachO(StringRef Filename) {
if (Archive *A = dyn_cast<Archive>(&Bin)) {
outs() << "Archive : " << Filename << "\n";
if (ArchiveHeaders)
printArchiveHeaders(A, true, false);
for (Archive::child_iterator I = A->child_begin(), E = A->child_end();
I != E; ++I) {
ErrorOr<std::unique_ptr<Binary>> ChildOrErr = I->getAsBinary();
@ -587,6 +694,8 @@ void llvm::ParseInputMachO(StringRef Filename) {
if (!ArchitectureName.empty())
outs() << " (architecture " << ArchitectureName << ")";
outs() << "\n";
if (ArchiveHeaders)
printArchiveHeaders(A.get(), true, false);
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
@ -627,6 +736,8 @@ void llvm::ParseInputMachO(StringRef Filename) {
I->getAsArchive()) {
std::unique_ptr<Archive> &A = *AOrErr;
outs() << "Archive : " << Filename << "\n";
if (ArchiveHeaders)
printArchiveHeaders(A.get(), true, false);
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
@ -662,6 +773,8 @@ void llvm::ParseInputMachO(StringRef Filename) {
if (!ArchitectureName.empty())
outs() << " (architecture " << ArchitectureName << ")";
outs() << "\n";
if (ArchiveHeaders)
printArchiveHeaders(A.get(), true, false);
for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end();
AI != AE; ++AI) {
ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary();

View File

@ -892,7 +892,8 @@ int main(int argc, char **argv) {
&& !Bind
&& !LazyBind
&& !WeakBind
&& !(UniversalHeaders && MachOOpt)) {
&& !(UniversalHeaders && MachOOpt)
&& !(ArchiveHeaders && MachOOpt)) {
cl::PrintHelpMessage();
return 2;
}

View File

@ -35,6 +35,7 @@ extern cl::opt<bool> Bind;
extern cl::opt<bool> LazyBind;
extern cl::opt<bool> WeakBind;
extern cl::opt<bool> UniversalHeaders;
extern cl::opt<bool> ArchiveHeaders;
// Various helper functions.
bool error(std::error_code ec);