[BOLT] Add initial bits for parsing MachO files

Summary: Start adding initial bits for MachO, this diff contains some small preparations for finding functions inside a MachO binary, this will be done in the next diff. The concept of a section in the MachO world is quite different from ELF, nevertheless, for functions for now it more or less fits into the current picture (in BOLT), but things will diverge more significantly a bit later.

(cherry picked from FBD19648161)
This commit is contained in:
Alexander Shaposhnikov 2020-01-30 13:10:48 -08:00 committed by Maksim Panchenko
parent 58a129a602
commit 36cf37c4c1
9 changed files with 226 additions and 45 deletions

View File

@ -89,12 +89,13 @@ class BinarySection {
}
static StringRef getContents(SectionRef Section) {
StringRef Contents;
if (ELFSectionRef(Section).getType() != ELF::SHT_NOBITS) {
if (auto EC = Section.getContents(Contents)) {
errs() << "BOLT-ERROR: cannot get section contents for "
<< getName(Section) << ": " << EC.message() << ".\n";
exit(1);
}
if (Section.getObject()->isELF() && ELFSectionRef(Section).getType() == ELF::SHT_NOBITS)
return Contents;
if (auto EC = Section.getContents(Contents)) {
errs() << "BOLT-ERROR: cannot get section contents for "
<< getName(Section) << ": " << EC.message() << ".\n";
exit(1);
}
return Contents;
}
@ -152,10 +153,12 @@ public:
Address(Section.getAddress()),
Size(Section.getSize()),
Alignment(Section.getAlignment()),
ELFType(ELFSectionRef(Section).getType()),
ELFFlags(ELFSectionRef(Section).getFlags()),
IsLocal(IsLocal || StringRef(Name).startswith(".local.")),
OutputName(Name) {
if (Section.getObject()->isELF()) {
ELFType = ELFSectionRef(Section).getType();
ELFFlags = ELFSectionRef(Section).getFlags();
}
}
// TODO: pass Data as StringRef/ArrayRef? use StringRef::copy method.

View File

@ -92,12 +92,14 @@ add_llvm_tool(llvm-bolt
ExecutableFileMemoryManager.cpp
Heatmap.cpp
JumpTable.cpp
MachORewriteInstance.cpp
MCPlusBuilder.cpp
ParallelUtilities.cpp
ProfileReader.cpp
ProfileWriter.cpp
Relocation.cpp
RewriteInstance.cpp
Utils.cpp
DEPENDS
intrinsics_gen

View File

@ -0,0 +1,67 @@
//===--- MachORewriteInstance.cpp - Instance of a rewriting process. ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//
#include "MachORewriteInstance.h"
#include "BinaryContext.h"
#include "BinaryFunction.h"
#include "Utils.h"
#include "llvm/Support/Timer.h"
namespace opts {
using namespace llvm;
extern cl::opt<bool> PrintSections;
} // namespace opts
namespace llvm {
namespace bolt {
#undef DEBUG_TYPE
#define DEBUG_TYPE "bolt"
MachORewriteInstance::MachORewriteInstance(object::MachOObjectFile *InputFile,
DataReader &DR)
: InputFile(InputFile),
BC(BinaryContext::createBinaryContext(
InputFile, DR,
DWARFContext::create(*InputFile, nullptr,
DWARFContext::defaultErrorHandler, "", false))) {
}
void MachORewriteInstance::readSpecialSections() {
for (const auto &Section : InputFile->sections()) {
StringRef SectionName;
check_error(Section.getName(SectionName), "cannot get section name");
// Only register sections with names.
if (!SectionName.empty()) {
BC->registerSection(Section);
DEBUG(dbgs() << "BOLT-DEBUG: registering section " << SectionName
<< " @ 0x" << Twine::utohexstr(Section.getAddress()) << ":0x"
<< Twine::utohexstr(Section.getAddress() + Section.getSize())
<< "\n");
}
}
if (opts::PrintSections) {
outs() << "BOLT-INFO: Sections from original binary:\n";
BC->printSections(outs());
}
}
void MachORewriteInstance::run() {
readSpecialSections();
}
MachORewriteInstance::~MachORewriteInstance() {}
} // namespace bolt
} // namespace llvm

View File

@ -0,0 +1,43 @@
//===--- MachORewriteInstance.h - Instance of a rewriting process. --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Interface to control an instance of a macho binary rewriting process.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_BOLT_MACHO_REWRITE_INSTANCE_H
#define LLVM_TOOLS_LLVM_BOLT_MACHO_REWRITE_INSTANCE_H
#include "llvm/Object/MachO.h"
#include <memory>
namespace llvm {
namespace bolt {
class BinaryContext;
class DataReader;
class MachORewriteInstance {
object::MachOObjectFile *InputFile;
std::unique_ptr<BinaryContext> BC;
void readSpecialSections();
public:
MachORewriteInstance(object::MachOObjectFile *InputFile, DataReader &DR);
~MachORewriteInstance();
/// Run all the necessary steps to read, optimize and rewrite the binary.
void run();
};
} // namespace bolt
} // namespace llvm
#endif

View File

@ -27,6 +27,7 @@
#include "ProfileReader.h"
#include "ProfileWriter.h"
#include "Relocation.h"
#include "Utils.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/BinaryFormat/Dwarf.h"
@ -292,12 +293,7 @@ PrintGlobals("print-globals",
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<bool>
PrintSections("print-sections",
cl::desc("print all registered sections"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
extern cl::opt<bool> PrintSections;
static cl::opt<bool>
PrintLoopInfo("print-loops",
@ -539,38 +535,11 @@ const char RewriteInstance::TimerGroupDesc[] = "Rewrite passes";
namespace llvm {
namespace bolt {
extern const char *BoltRevision;
void report_error(StringRef Message, std::error_code EC) {
assert(EC);
errs() << "BOLT-ERROR: '" << Message << "': " << EC.message() << ".\n";
exit(1);
}
void report_error(StringRef Message, Error E) {
assert(E);
errs() << "BOLT-ERROR: '" << Message << "': " << toString(std::move(E))
<< ".\n";
exit(1);
}
void check_error(std::error_code EC, StringRef Message) {
if (!EC)
return;
report_error(Message, EC);
}
void check_error(Error E, Twine Message) {
if (!E)
return;
handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) {
llvm::errs() << "BOLT-ERROR: '" << Message << "': " << EIB.message()
<< '\n';
exit(1);
});
}
}
}
} // namespace bolt
} // namespace llvm
namespace {

View File

@ -1,4 +1,4 @@
//===--- RewriteInstance.h - Interface for machine-level function ---------===//
//===--- RewriteInstance.h - Instance of a rewriting process. -------------===//
//
// The LLVM Compiler Infrastructure
//

50
bolt/src/Utils.cpp Normal file
View File

@ -0,0 +1,50 @@
//===--- Utils.cpp - Common helper functions ------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Common helper functions.
//
//===----------------------------------------------------------------------===//
#include "Utils.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
namespace bolt {
void report_error(StringRef Message, std::error_code EC) {
assert(EC);
errs() << "BOLT-ERROR: '" << Message << "': " << EC.message() << ".\n";
exit(1);
}
void report_error(StringRef Message, Error E) {
assert(E);
errs() << "BOLT-ERROR: '" << Message << "': " << toString(std::move(E))
<< ".\n";
exit(1);
}
void check_error(std::error_code EC, StringRef Message) {
if (!EC)
return;
report_error(Message, EC);
}
void check_error(Error E, Twine Message) {
if (!E)
return;
handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) {
llvm::errs() << "BOLT-ERROR: '" << Message << "': " << EIB.message()
<< '\n';
exit(1);
});
}
} // namespace bolt
} // namespace llvm

35
bolt/src/Utils.h Normal file
View File

@ -0,0 +1,35 @@
//===--- Utils.h - Common helper functions --------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Common helper functions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_BOLT_UTILS_H
#define LLVM_TOOLS_LLVM_BOLT_UTILS_H
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace bolt {
void report_error(StringRef Message, std::error_code EC);
void report_error(StringRef Message, Error E);
void check_error(std::error_code EC, StringRef Message);
void check_error(Error E, Twine Message);
} // namespace bolt
} // namespace llvm
#endif

View File

@ -15,6 +15,7 @@
#include "DataAggregator.h"
#include "DataReader.h"
#include "MachORewriteInstance.h"
#include "RewriteInstance.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/CommandLine.h"
@ -106,7 +107,15 @@ PerfDataA("p",
cl::aliasopt(PerfData),
cl::cat(AggregatorCategory));
cl::opt<bool>
PrintSections("print-sections",
cl::desc("print all registered sections"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
} // namespace opts
static StringRef ToolName;
static void report_error(StringRef Message, std::error_code EC) {
@ -324,6 +333,9 @@ int main(int argc, char **argv) {
if (auto *e = dyn_cast<ELFObjectFileBase>(&Binary)) {
RewriteInstance RI(e, *DR.get(), *DA.get(), argc, argv, ToolPath);
RI.run();
} else if (auto *O = dyn_cast<MachOObjectFile>(&Binary)) {
MachORewriteInstance MachORI(O, *DR);
MachORI.run();
} else {
report_error(opts::InputFilename, object_error::invalid_file_type);
}