[llvm] r211117 - Add "-format darwin" to llvm-size to be like darwin's size(1) -m output, and
Kevin Enderby
enderby at apple.com
Tue Jun 17 10:54:13 PDT 2014
Author: enderby
Date: Tue Jun 17 12:54:13 2014
New Revision: 211117
URL: http://llvm.org/viewvc/llvm-project?rev=211117&view=rev
Log:
Add "-format darwin" to llvm-size to be like darwin's size(1) -m output, and
and the -l option for the long format. Also when the object is a Mach-O
file and the format is berkeley produce output like darwin’s default size(1)
summary berkeley derived output.
Like System V format, there are also some small changes in how and where
the file names and archive member names are printed for darwin and
Mach-O.
Like the changes to llvm-nm these are the first steps in seeing if it is
possible to make llvm-size produce the same output as darwin's size(1).
Added:
llvm/trunk/test/Object/Inputs/hello-world.macho-x86_64 (with props)
llvm/trunk/test/Object/Inputs/macho-archive-x86_64.a (with props)
Modified:
llvm/trunk/test/Object/size-trivial-macho.test
llvm/trunk/tools/llvm-size/llvm-size.cpp
Added: llvm/trunk/test/Object/Inputs/hello-world.macho-x86_64
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Inputs/hello-world.macho-x86_64?rev=211117&view=auto
==============================================================================
Binary file - no diff available.
Propchange: llvm/trunk/test/Object/Inputs/hello-world.macho-x86_64
------------------------------------------------------------------------------
svn:executable = *
Propchange: llvm/trunk/test/Object/Inputs/hello-world.macho-x86_64
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: llvm/trunk/test/Object/Inputs/macho-archive-x86_64.a
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Inputs/macho-archive-x86_64.a?rev=211117&view=auto
==============================================================================
Binary file - no diff available.
Propchange: llvm/trunk/test/Object/Inputs/macho-archive-x86_64.a
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: llvm/trunk/test/Object/size-trivial-macho.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/size-trivial-macho.test?rev=211117&r1=211116&r2=211117&view=diff
==============================================================================
--- llvm/trunk/test/Object/size-trivial-macho.test (original)
+++ llvm/trunk/test/Object/size-trivial-macho.test Tue Jun 17 12:54:13 2014
@@ -2,6 +2,14 @@ RUN: llvm-size -A %p/Inputs/macho-text-d
RUN: | FileCheck %s -check-prefix A
RUN: llvm-size -B %p/Inputs/macho-text-data-bss.macho-x86_64 \
RUN: | FileCheck %s -check-prefix B
+RUN: llvm-size -format darwin %p/Inputs/macho-text-data-bss.macho-x86_64 \
+RUN: | FileCheck %s -check-prefix m
+RUN: llvm-size %p/Inputs/macho-archive-x86_64.a \
+RUN: | FileCheck %s -check-prefix AR
+RUN: llvm-size -format darwin %p/Inputs/macho-archive-x86_64.a \
+RUN: | FileCheck %s -check-prefix mAR
+RUN: llvm-size -format darwin -x -l %p/Inputs/hello-world.macho-x86_64 \
+RUN: | FileCheck %s -check-prefix mxl
A: section size addr
A: __text 12 0
@@ -11,5 +19,49 @@ A: __compact_unwind 32 16
A: __eh_frame 64 48
A: Total 116
-B: text data bss dec hex filename
-B: 12 100 4 116 74
+B: __TEXT __DATA __OBJC others dec hex
+B: 76 8 0 32 116 74
+
+m: Segment : 116
+m: Section (__TEXT, __text): 12
+m: Section (__DATA, __data): 4
+m: Section (__DATA, __bss): 4
+m: Section (__LD, __compact_unwind): 32
+m: Section (__TEXT, __eh_frame): 64
+m: total 116
+m: total 116
+
+AR: __TEXT __DATA __OBJC others dec hex
+AR: 70 0 0 32 102 66 {{.*}}/macho-archive-x86_64.a(foo.o)
+AR: 0 4 0 0 4 4 {{.*}}/macho-archive-x86_64.a(bar.o)
+
+mAR: {{.*}}/macho-archive-x86_64.a(foo.o):
+mAR: Segment : 104
+mAR: Section (__TEXT, __text): 6
+mAR: Section (__LD, __compact_unwind): 32
+mAR: Section (__TEXT, __eh_frame): 64
+mAR: total 102
+mAR: total 104
+mAR: {{.*}}/macho-archive-x86_64.a(bar.o):
+mAR: Segment : 4
+mAR: Section (__TEXT, __text): 0
+mAR: Section (__DATA, __data): 4
+mAR: total 4
+mAR: total 4
+
+
+mxl: Segment __PAGEZERO: 0x100000000 (vmaddr 0x0 fileoff 0)
+mxl: Segment __TEXT: 0x1000 (vmaddr 0x100000000 fileoff 0)
+mxl: Section __text: 0x3b (addr 0x100000f30 offset 3888)
+mxl: Section __stubs: 0x6 (addr 0x100000f6c offset 3948)
+mxl: Section __stub_helper: 0x1a (addr 0x100000f74 offset 3956)
+mxl: Section __cstring: 0xd (addr 0x100000f8e offset 3982)
+mxl: Section __unwind_info: 0x48 (addr 0x100000f9b offset 3995)
+mxl: Section __eh_frame: 0x18 (addr 0x100000fe8 offset 4072)
+mxl: total 0xc8
+mxl: Segment __DATA: 0x1000 (vmaddr 0x100001000 fileoff 4096)
+mxl: Section __nl_symbol_ptr: 0x10 (addr 0x100001000 offset 4096)
+mxl: Section __la_symbol_ptr: 0x8 (addr 0x100001010 offset 4112)
+mxl: total 0x18
+mxl: Segment __LINKEDIT: 0x1000 (vmaddr 0x100002000 fileoff 8192)
+mxl: total 0x100003000
Modified: llvm/trunk/tools/llvm-size/llvm-size.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-size/llvm-size.cpp?rev=211117&r1=211116&r2=211117&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-size/llvm-size.cpp (original)
+++ llvm/trunk/tools/llvm-size/llvm-size.cpp Tue Jun 17 12:54:13 2014
@@ -16,6 +16,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/MachO.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
@@ -31,13 +32,13 @@
using namespace llvm;
using namespace object;
-enum OutputFormatTy {berkeley, sysv};
+enum OutputFormatTy {berkeley, sysv, darwin};
static cl::opt<OutputFormatTy>
OutputFormat("format",
cl::desc("Specify output format"),
cl::values(clEnumVal(sysv, "System V format"),
clEnumVal(berkeley, "Berkeley format"),
- clEnumValEnd),
+ clEnumVal(darwin, "Darwin -m format"), clEnumValEnd),
cl::init(berkeley));
static cl::opt<OutputFormatTy>
@@ -47,6 +48,13 @@ static cl::opt<OutputFormatTy>
clEnumValEnd),
cl::init(berkeley));
+static bool berkeleyHeaderPrinted = false;
+static bool moreThanOneFile = false;
+
+cl::opt<bool> DarwinLongFormat("l",
+ cl::desc("When format is darwin, use long format "
+ "to include addresses and offsets."));
+
enum RadixTy {octal = 8, decimal = 10, hexadecimal = 16};
static cl::opt<unsigned int>
Radix("-radix",
@@ -85,6 +93,182 @@ static size_t getNumLengthAsString(uint6
return result.size();
}
+/// @brief Return the the printing format for the Radix.
+static const char * getRadixFmt(void) {
+ switch (Radix) {
+ case octal:
+ return PRIo64;
+ case decimal:
+ return PRIu64;
+ case hexadecimal:
+ return PRIx64;
+ }
+ return nullptr;
+}
+
+/// @brief Print the size of each Mach-O segment and section in @p MachO.
+///
+/// This is when used when @c OutputFormat is darwin and produces the same
+/// output as darwin's size(1) -m output.
+static void PrintDarwinSectionSizes(MachOObjectFile *MachO) {
+ std::string fmtbuf;
+ raw_string_ostream fmt(fmtbuf);
+ const char *radix_fmt = getRadixFmt();
+ if (Radix == hexadecimal)
+ fmt << "0x";
+ fmt << "%" << radix_fmt;
+
+ uint32_t LoadCommandCount = MachO->getHeader().ncmds;
+ uint32_t Filetype = MachO->getHeader().filetype;
+ MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
+
+ uint64_t total = 0;
+ for (unsigned I = 0; ; ++I) {
+ if (Load.C.cmd == MachO::LC_SEGMENT_64) {
+ MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
+ outs() << "Segment " << Seg.segname << ": "
+ << format(fmt.str().c_str(), Seg.vmsize);
+ if (DarwinLongFormat)
+ outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr)
+ << " fileoff " << Seg.fileoff << ")";
+ outs() << "\n";
+ total += Seg.vmsize;
+ uint64_t sec_total = 0;
+ for (unsigned J = 0; J < Seg.nsects; ++J) {
+ MachO::section_64 Sec = MachO->getSection64(Load, J);
+ if (Filetype == MachO::MH_OBJECT)
+ outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
+ << format("%.16s", &Sec.sectname) << "): ";
+ else
+ outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
+ outs() << format(fmt.str().c_str(), Sec.size);
+ if (DarwinLongFormat)
+ outs() << " (addr 0x" << format("%" PRIx64, Sec.addr)
+ << " offset " << Sec.offset << ")";
+ outs() << "\n";
+ sec_total += Sec.size;
+ }
+ if (Seg.nsects != 0)
+ outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
+ }
+ else if (Load.C.cmd == MachO::LC_SEGMENT) {
+ MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
+ outs() << "Segment " << Seg.segname << ": "
+ << format(fmt.str().c_str(), Seg.vmsize);
+ if (DarwinLongFormat)
+ outs() << " (vmaddr 0x" << format("%" PRIx64, Seg.vmaddr)
+ << " fileoff " << Seg.fileoff << ")";
+ outs() << "\n";
+ total += Seg.vmsize;
+ uint64_t sec_total = 0;
+ for (unsigned J = 0; J < Seg.nsects; ++J) {
+ MachO::section Sec = MachO->getSection(Load, J);
+ if (Filetype == MachO::MH_OBJECT)
+ outs() << "\tSection (" << format("%.16s", &Sec.segname) << ", "
+ << format("%.16s", &Sec.sectname) << "): ";
+ else
+ outs() << "\tSection " << format("%.16s", &Sec.sectname) << ": ";
+ outs() << format(fmt.str().c_str(), Sec.size);
+ if (DarwinLongFormat)
+ outs() << " (addr 0x" << format("%" PRIx64, Sec.addr)
+ << " offset " << Sec.offset << ")";
+ outs() << "\n";
+ sec_total += Sec.size;
+ }
+ if (Seg.nsects != 0)
+ outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n";
+ }
+ if (I == LoadCommandCount - 1)
+ break;
+ else
+ Load = MachO->getNextLoadCommandInfo(Load);
+ }
+ outs() << "total " << format(fmt.str().c_str(), total) << "\n";
+}
+
+/// @brief Print the summary sizes of the standard Mach-O segments in @p MachO.
+///
+/// This is when used when @c OutputFormat is berkeley with a Mach-O file and
+/// produces the same output as darwin's size(1) default output.
+static void PrintDarwinSegmentSizes(MachOObjectFile *MachO) {
+ uint32_t LoadCommandCount = MachO->getHeader().ncmds;
+ MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo();
+
+ uint64_t total_text = 0;
+ uint64_t total_data = 0;
+ uint64_t total_objc = 0;
+ uint64_t total_others = 0;
+ for (unsigned I = 0; ; ++I) {
+ if (Load.C.cmd == MachO::LC_SEGMENT_64) {
+ MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load);
+ if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
+ for (unsigned J = 0; J < Seg.nsects; ++J) {
+ MachO::section_64 Sec = MachO->getSection64(Load, J);
+ StringRef SegmentName = StringRef(Sec.segname);
+ if (SegmentName == "__TEXT")
+ total_text += Sec.size;
+ else if (SegmentName == "__DATA")
+ total_data += Sec.size;
+ else if (SegmentName == "__OBJC")
+ total_objc += Sec.size;
+ else
+ total_others += Sec.size;
+ }
+ } else {
+ StringRef SegmentName = StringRef(Seg.segname);
+ if (SegmentName == "__TEXT")
+ total_text += Seg.vmsize;
+ else if (SegmentName == "__DATA")
+ total_data += Seg.vmsize;
+ else if (SegmentName == "__OBJC")
+ total_objc += Seg.vmsize;
+ else
+ total_others += Seg.vmsize;
+ }
+ }
+ else if (Load.C.cmd == MachO::LC_SEGMENT) {
+ MachO::segment_command Seg = MachO->getSegmentLoadCommand(Load);
+ if (MachO->getHeader().filetype == MachO::MH_OBJECT) {
+ for (unsigned J = 0; J < Seg.nsects; ++J) {
+ MachO::section Sec = MachO->getSection(Load, J);
+ StringRef SegmentName = StringRef(Sec.segname);
+ if (SegmentName == "__TEXT")
+ total_text += Sec.size;
+ else if (SegmentName == "__DATA")
+ total_data += Sec.size;
+ else if (SegmentName == "__OBJC")
+ total_objc += Sec.size;
+ else
+ total_others += Sec.size;
+ }
+ } else {
+ StringRef SegmentName = StringRef(Seg.segname);
+ if (SegmentName == "__TEXT")
+ total_text += Seg.vmsize;
+ else if (SegmentName == "__DATA")
+ total_data += Seg.vmsize;
+ else if (SegmentName == "__OBJC")
+ total_objc += Seg.vmsize;
+ else
+ total_others += Seg.vmsize;
+ }
+ }
+ if (I == LoadCommandCount - 1)
+ break;
+ else
+ Load = MachO->getNextLoadCommandInfo(Load);
+ }
+ uint64_t total = total_text + total_data + total_objc + total_others;
+
+ if (!berkeleyHeaderPrinted) {
+ outs() << "__TEXT\t__DATA\t__OBJC\tothers\tdec\thex\n";
+ berkeleyHeaderPrinted = true;
+ }
+ outs() << total_text << "\t" << total_data << "\t" << total_objc << "\t"
+ << total_others << "\t" << total << "\t" << format("%" PRIx64, total)
+ << "\t";
+}
+
/// @brief Print the size of each section in @p Obj.
///
/// The format used is determined by @c OutputFormat and @c Radix.
@@ -92,20 +276,19 @@ static void PrintObjectSectionSizes(Obje
uint64_t total = 0;
std::string fmtbuf;
raw_string_ostream fmt(fmtbuf);
+ const char *radix_fmt = getRadixFmt();
- const char *radix_fmt = nullptr;
- switch (Radix) {
- case octal:
- radix_fmt = PRIo64;
- break;
- case decimal:
- radix_fmt = PRIu64;
- break;
- case hexadecimal:
- radix_fmt = PRIx64;
- break;
- }
- if (OutputFormat == sysv) {
+ // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's
+ // size(1) -m output, else if OutputFormat is darwin and not a Mach-O object
+ // let it fall through to OutputFormat berkeley.
+ MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Obj);
+ if (OutputFormat == darwin && MachO)
+ PrintDarwinSectionSizes(MachO);
+ // If we have a MachOObjectFile and the OutputFormat is berkeley print as
+ // darwin's default berkeley format for Mach-O files.
+ else if (MachO && OutputFormat == berkeley)
+ PrintDarwinSegmentSizes(MachO);
+ else if (OutputFormat == sysv) {
// Run two passes over all sections. The first gets the lengths needed for
// formatting the output. The second actually does the output.
std::size_t max_name_len = strlen("section");
@@ -204,6 +387,13 @@ static void PrintObjectSectionSizes(Obje
total = total_text + total_data + total_bss;
+ if (!berkeleyHeaderPrinted) {
+ outs() << " text data bss "
+ << (Radix == octal ? "oct" : "dec")
+ << " hex filename\n";
+ berkeleyHeaderPrinted = true;
+ }
+
// Print result.
fmt << "%#7" << radix_fmt << " "
<< "%#7" << radix_fmt << " "
@@ -251,20 +441,31 @@ static void PrintFileSectionSizes(String
continue;
}
if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
+ MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
if (OutputFormat == sysv)
outs() << o->getFileName() << " (ex " << a->getFileName()
<< "):\n";
+ else if(MachO && OutputFormat == darwin)
+ outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
PrintObjectSectionSizes(o);
- if (OutputFormat == berkeley)
- outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
+ if (OutputFormat == berkeley) {
+ if (MachO)
+ outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
+ else
+ outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
+ }
}
}
} else if (ObjectFile *o = dyn_cast<ObjectFile>(binary.get())) {
if (OutputFormat == sysv)
outs() << o->getFileName() << " :\n";
PrintObjectSectionSizes(o);
- if (OutputFormat == berkeley)
- outs() << o->getFileName() << "\n";
+ if (OutputFormat == berkeley) {
+ MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
+ if (!MachO || moreThanOneFile)
+ outs() << o->getFileName();
+ outs() << "\n";
+ }
} else {
errs() << ToolName << ": " << file << ": " << "Unrecognized file type.\n";
}
@@ -290,11 +491,7 @@ int main(int argc, char **argv) {
if (InputFilenames.size() == 0)
InputFilenames.push_back("a.out");
- if (OutputFormat == berkeley)
- outs() << " text data bss "
- << (Radix == octal ? "oct" : "dec")
- << " hex filename\n";
-
+ moreThanOneFile = InputFilenames.size() > 1;
std::for_each(InputFilenames.begin(), InputFilenames.end(),
PrintFileSectionSizes);
More information about the llvm-commits
mailing list