mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
Add the -arch flag support to llvm-size like what was done to llvm-nm
to select the slice out of a Mach-O universal file. This also includes support for -arch all, selecting the host architecture by default from a universal file and checking if -arch is used with a standard Mach-O it matches that architecture. llvm-svn: 212108
This commit is contained in:
parent
f03a637a3d
commit
a6fe7b39f8
@ -10,10 +10,14 @@ RUN: llvm-size -format darwin %p/Inputs/macho-archive-x86_64.a \
|
||||
RUN: | FileCheck %s -check-prefix mAR
|
||||
RUN: llvm-size -m -x -l %p/Inputs/hello-world.macho-x86_64 \
|
||||
RUN: | FileCheck %s -check-prefix mxl
|
||||
RUN: llvm-size %p/Inputs/macho-universal.x86_64.i386 \
|
||||
RUN: llvm-size -arch all %p/Inputs/macho-universal.x86_64.i386 \
|
||||
RUN: | FileCheck %s -check-prefix u
|
||||
RUN: llvm-size %p/Inputs/macho-universal-archive.x86_64.i386 \
|
||||
RUN: llvm-size -arch i386 %p/Inputs/macho-universal.x86_64.i386 \
|
||||
RUN: | FileCheck %s -check-prefix u-i386
|
||||
RUN: llvm-size -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \
|
||||
RUN: | FileCheck %s -check-prefix uAR
|
||||
RUN: llvm-size -arch x86_64 %p/Inputs/macho-universal-archive.x86_64.i386 \
|
||||
RUN: | FileCheck %s -check-prefix uAR-x86_64
|
||||
|
||||
A: section size addr
|
||||
A: __text 12 0
|
||||
@ -74,6 +78,12 @@ u: __TEXT __DATA __OBJC others dec hex
|
||||
u: 4096 0 0 4294971392 4294975488 100002000 {{.*}}/macho-universal.x86_64.i386 (for architecture x86_64)
|
||||
u: 4096 0 0 8192 12288 3000 {{.*}}/macho-universal.x86_64.i386 (for architecture i386)
|
||||
|
||||
u-i386: __TEXT __DATA __OBJC others dec hex
|
||||
u-i386: 4096 0 0 8192 12288 3000
|
||||
|
||||
uAR: __TEXT __DATA __OBJC others dec hex
|
||||
uAR: 136 0 0 32 168 a8 {{.*}}/macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64)
|
||||
uAR: 5 4 0 0 9 9 {{.*}}/macho-universal-archive.x86_64.i386(foo.o) (for architecture i386)
|
||||
|
||||
uAR-x86_64: __TEXT __DATA __OBJC others dec hex
|
||||
uAR-x86_64: 136 0 0 32 168 a8 {{.*}}/macho-universal-archive.x86_64.i386(hello.o)
|
||||
|
@ -57,6 +57,12 @@ cl::opt<bool> DarwinLongFormat("l",
|
||||
cl::desc("When format is darwin, use long format "
|
||||
"to include addresses and offsets."));
|
||||
|
||||
static cl::list<std::string>
|
||||
ArchFlags("arch",
|
||||
cl::desc("architecture(s) from a Mach-O file to dump"),
|
||||
cl::ZeroOrMore);
|
||||
bool ArchAll = false;
|
||||
|
||||
enum RadixTy {octal = 8, decimal = 10, hexadecimal = 16};
|
||||
static cl::opt<unsigned int>
|
||||
Radix("-radix",
|
||||
@ -413,6 +419,40 @@ static void PrintObjectSectionSizes(ObjectFile *Obj) {
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Checks to see if the @p o ObjectFile is a Mach-O file and if it is
|
||||
/// and there is a list of architecture flags specified then check to
|
||||
/// make sure this Mach-O file is one of those architectures or all
|
||||
/// architectures was specificed. If not then an error is generated and
|
||||
/// this routine returns false. Else it returns true.
|
||||
static bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) {
|
||||
if (isa<MachOObjectFile>(o) && !ArchAll && ArchFlags.size() != 0) {
|
||||
MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
|
||||
bool ArchFound = false;
|
||||
MachO::mach_header H;
|
||||
MachO::mach_header_64 H_64;
|
||||
Triple T;
|
||||
if (MachO->is64Bit()) {
|
||||
H_64 = MachO->MachOObjectFile::getHeader64();
|
||||
T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype);
|
||||
} else {
|
||||
H = MachO->MachOObjectFile::getHeader();
|
||||
T = MachOObjectFile::getArch(H.cputype, H.cpusubtype);
|
||||
}
|
||||
unsigned i;
|
||||
for (i = 0; i < ArchFlags.size(); ++i){
|
||||
if (ArchFlags[i] == T.getArchName())
|
||||
ArchFound = true;
|
||||
break;
|
||||
}
|
||||
if (!ArchFound) {
|
||||
errs() << ToolName << ": file: " << file
|
||||
<< " does not contain architecture: " << ArchFlags[i] << ".\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Print the section sizes for @p file. If @p file is an archive, print
|
||||
/// the section sizes for each archive member.
|
||||
static void PrintFileSectionSizes(StringRef file) {
|
||||
@ -444,6 +484,8 @@ static void PrintFileSectionSizes(StringRef file) {
|
||||
}
|
||||
if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
|
||||
MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
|
||||
if (!checkMachOAndArchFlags(o, file))
|
||||
return;
|
||||
if (OutputFormat == sysv)
|
||||
outs() << o->getFileName() << " (ex " << a->getFileName()
|
||||
<< "):\n";
|
||||
@ -460,8 +502,155 @@ static void PrintFileSectionSizes(StringRef file) {
|
||||
}
|
||||
} else if (MachOUniversalBinary *UB =
|
||||
dyn_cast<MachOUniversalBinary>(binary.get())) {
|
||||
// This is a Mach-O universal binary. Iterate over each object and
|
||||
// display its sizes.
|
||||
// If we have a list of architecture flags specified dump only those.
|
||||
if (!ArchAll && ArchFlags.size() != 0) {
|
||||
// Look for a slice in the universal binary that matches each ArchFlag.
|
||||
bool ArchFound;
|
||||
for (unsigned i = 0; i < ArchFlags.size(); ++i){
|
||||
ArchFound = false;
|
||||
for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
|
||||
E = UB->end_objects();
|
||||
I != E; ++I) {
|
||||
if (ArchFlags[i] == I->getArchTypeName()){
|
||||
ArchFound = true;
|
||||
ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
|
||||
std::unique_ptr<Archive> UA;
|
||||
if (UO) {
|
||||
if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
|
||||
MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
|
||||
if (OutputFormat == sysv)
|
||||
outs() << o->getFileName() << " :\n";
|
||||
else if(MachO && OutputFormat == darwin) {
|
||||
if (moreThanOneFile || ArchFlags.size() > 1)
|
||||
outs() << o->getFileName() << " (for architecture "
|
||||
<< I->getArchTypeName() << "): \n";
|
||||
}
|
||||
PrintObjectSectionSizes(o);
|
||||
if (OutputFormat == berkeley) {
|
||||
if (!MachO || moreThanOneFile || ArchFlags.size() > 1)
|
||||
outs() << o->getFileName() << " (for architecture "
|
||||
<< I->getArchTypeName() << ")";
|
||||
outs() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!I->getAsArchive(UA)) {
|
||||
// This is an archive. Iterate over each member and display its
|
||||
//sizes.
|
||||
for (object::Archive::child_iterator i = UA->child_begin(),
|
||||
e = UA->child_end();
|
||||
i != e; ++i) {
|
||||
ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
|
||||
if (std::error_code EC = ChildOrErr.getError()) {
|
||||
errs() << ToolName << ": " << file << ": " << EC.message()
|
||||
<< ".\n";
|
||||
continue;
|
||||
}
|
||||
if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
|
||||
MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
|
||||
if (OutputFormat == sysv)
|
||||
outs() << o->getFileName() << " (ex " << UA->getFileName()
|
||||
<< "):\n";
|
||||
else if(MachO && OutputFormat == darwin)
|
||||
outs() << UA->getFileName() << "(" << o->getFileName()
|
||||
<< ")" << " (for architecture "
|
||||
<< I->getArchTypeName() << "):\n";
|
||||
PrintObjectSectionSizes(o);
|
||||
if (OutputFormat == berkeley) {
|
||||
if (MachO) {
|
||||
outs() << UA->getFileName() << "(" << o->getFileName()
|
||||
<< ")";
|
||||
if (ArchFlags.size() > 1)
|
||||
outs() << " (for architecture "
|
||||
<< I->getArchTypeName() << ")";
|
||||
outs() << "\n";
|
||||
}
|
||||
else
|
||||
outs() << o->getFileName() << " (ex " << UA->getFileName()
|
||||
<< ")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ArchFound) {
|
||||
errs() << ToolName << ": file: " << file
|
||||
<< " does not contain architecture" << ArchFlags[i] << ".\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// No architecture flags were specified so if this contains a slice that
|
||||
// matches the host architecture dump only that.
|
||||
if (!ArchAll) {
|
||||
StringRef HostArchName =
|
||||
MachOObjectFile::getHostArch().getArchName();
|
||||
for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
|
||||
E = UB->end_objects();
|
||||
I != E; ++I) {
|
||||
if (HostArchName == I->getArchTypeName()){
|
||||
ErrorOr<std::unique_ptr<ObjectFile>> UO = I->getAsObjectFile();
|
||||
std::unique_ptr<Archive> UA;
|
||||
if (UO) {
|
||||
if (ObjectFile *o = dyn_cast<ObjectFile>(&*UO.get())) {
|
||||
MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
|
||||
if (OutputFormat == sysv)
|
||||
outs() << o->getFileName() << " :\n";
|
||||
else if(MachO && OutputFormat == darwin) {
|
||||
if (moreThanOneFile)
|
||||
outs() << o->getFileName() << " (for architecture "
|
||||
<< I->getArchTypeName() << "):\n";
|
||||
}
|
||||
PrintObjectSectionSizes(o);
|
||||
if (OutputFormat == berkeley) {
|
||||
if (!MachO || moreThanOneFile)
|
||||
outs() << o->getFileName() << " (for architecture "
|
||||
<< I->getArchTypeName() << ")";
|
||||
outs() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!I->getAsArchive(UA)) {
|
||||
// This is an archive. Iterate over each member and display its
|
||||
// sizes.
|
||||
for (object::Archive::child_iterator i = UA->child_begin(),
|
||||
e = UA->child_end();
|
||||
i != e; ++i) {
|
||||
ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
|
||||
if (std::error_code EC = ChildOrErr.getError()) {
|
||||
errs() << ToolName << ": " << file << ": " << EC.message()
|
||||
<< ".\n";
|
||||
continue;
|
||||
}
|
||||
if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
|
||||
MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o);
|
||||
if (OutputFormat == sysv)
|
||||
outs() << o->getFileName() << " (ex " << UA->getFileName()
|
||||
<< "):\n";
|
||||
else if(MachO && OutputFormat == darwin)
|
||||
outs() << UA->getFileName() << "(" << o->getFileName() << ")"
|
||||
<< " (for architecture " << I->getArchTypeName()
|
||||
<< "):\n";
|
||||
PrintObjectSectionSizes(o);
|
||||
if (OutputFormat == berkeley) {
|
||||
if (MachO)
|
||||
outs() << UA->getFileName() << "(" << o->getFileName()
|
||||
<< ")\n";
|
||||
else
|
||||
outs() << o->getFileName() << " (ex " << UA->getFileName()
|
||||
<< ")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Either all architectures have been specified or none have been specified
|
||||
// and this does not contain the host architecture so dump all the slices.
|
||||
bool moreThanOneArch = UB->getNumberOfObjects() > 1;
|
||||
for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
|
||||
E = UB->end_objects();
|
||||
@ -521,6 +710,8 @@ static void PrintFileSectionSizes(StringRef file) {
|
||||
}
|
||||
}
|
||||
} else if (ObjectFile *o = dyn_cast<ObjectFile>(binary.get())) {
|
||||
if (!checkMachOAndArchFlags(o, file))
|
||||
return;
|
||||
if (OutputFormat == sysv)
|
||||
outs() << o->getFileName() << " :\n";
|
||||
PrintObjectSectionSizes(o);
|
||||
@ -552,6 +743,20 @@ int main(int argc, char **argv) {
|
||||
if (RadixShort.getNumOccurrences())
|
||||
Radix = RadixShort;
|
||||
|
||||
for (unsigned i = 0; i < ArchFlags.size(); ++i){
|
||||
if (ArchFlags[i] == "all") {
|
||||
ArchAll = true;
|
||||
}
|
||||
else {
|
||||
Triple T = MachOObjectFile::getArch(ArchFlags[i]);
|
||||
if (T.getArch() == Triple::UnknownArch){
|
||||
outs() << ToolName << ": for the -arch option: Unknown architecture "
|
||||
<< "named '" << ArchFlags[i] << "'";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (InputFilenames.size() == 0)
|
||||
InputFilenames.push_back("a.out");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user