mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
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). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211117 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3f1f259c22
commit
acc5e810aa
BIN
test/Object/Inputs/hello-world.macho-x86_64
Executable file
BIN
test/Object/Inputs/hello-world.macho-x86_64
Executable file
Binary file not shown.
BIN
test/Object/Inputs/macho-archive-x86_64.a
Normal file
BIN
test/Object/Inputs/macho-archive-x86_64.a
Normal file
Binary file not shown.
@ -2,6 +2,14 @@ RUN: llvm-size -A %p/Inputs/macho-text-data-bss.macho-x86_64 \
|
||||
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
|
||||
|
@ -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(uint64_t num) {
|
||||
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(ObjectFile *Obj) {
|
||||
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(ObjectFile *Obj) {
|
||||
|
||||
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(StringRef file) {
|
||||
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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user