Skip to content

Commit

Permalink
[BOLT] Add initial bits for parsing MachO files
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
Alexander Shaposhnikov authored and maksfb committed Jan 30, 2020
1 parent 58a129a commit 36cf37c
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 45 deletions.
19 changes: 11 additions & 8 deletions bolt/src/BinarySection.h
Expand Up @@ -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;
}
Expand Down Expand Up @@ -152,10 +153,12 @@ class BinarySection {
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.
Expand Down
2 changes: 2 additions & 0 deletions bolt/src/CMakeLists.txt
Expand Up @@ -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
Expand Down
67 changes: 67 additions & 0 deletions bolt/src/MachORewriteInstance.cpp
@@ -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
43 changes: 43 additions & 0 deletions bolt/src/MachORewriteInstance.h
@@ -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
41 changes: 5 additions & 36 deletions bolt/src/RewriteInstance.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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);
}
extern const char *BoltRevision;

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 {

Expand Down
2 changes: 1 addition & 1 deletion bolt/src/RewriteInstance.h
@@ -1,4 +1,4 @@
//===--- RewriteInstance.h - Interface for machine-level function ---------===//
//===--- RewriteInstance.h - Instance of a rewriting process. -------------===//
//
// The LLVM Compiler Infrastructure
//
Expand Down
50 changes: 50 additions & 0 deletions bolt/src/Utils.cpp
@@ -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 changes: 35 additions & 0 deletions bolt/src/Utils.h
@@ -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
12 changes: 12 additions & 0 deletions bolt/src/llvm-bolt.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 36cf37c

Please sign in to comment.