Skip to content

Commit

Permalink
Move command line params to TableGen version like in the current vers…
Browse files Browse the repository at this point in the history
…ion of the llvm-objdump (#177)

* Move command line params to TableGen version like in the current version of the llvm-objdump

* add --include-files flag

* add doc/sysroot_flag.md

* hide repeated help messages for joined and separate flag versions

* correct include file visitor for scanning in depth
  • Loading branch information
sv99 authored Sep 12, 2022
1 parent 05a5d17 commit d32a1ba
Show file tree
Hide file tree
Showing 10 changed files with 455 additions and 257 deletions.
2 changes: 1 addition & 1 deletion ARM/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ add_llvm_library(mctollARMRaiser
Target
)

target_link_libraries(mctollARMRaiser PRIVATE mctollRaiser)
target_link_libraries(mctollARMRaiser PRIVATE mctollRaiser)
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ configure_file(
${LLVM_INCLUDE_DIR}/Raisers.def
)

set(LLVM_TARGET_DEFINITIONS Opts.td)
tablegen(LLVM Opts.inc -gen-opt-parser-defs)
add_public_tablegen_target(MctoolOptsTableGen)

add_subdirectory(test)

add_llvm_tool(llvm-mctoll
Expand All @@ -62,6 +66,8 @@ add_llvm_tool(llvm-mctoll
MachODump.cpp
EmitRaisedOutputPass.cpp
PeepholeOptimizationPass.cpp
DEPENDS
MctoolOptsTableGen
)

# Link against LLVM libraries and target-specific Raiser libraries
Expand Down
50 changes: 13 additions & 37 deletions MachODump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,43 +60,19 @@ using namespace llvm;
using namespace llvm::mctoll;
using namespace object;

extern cl::opt<std::string> MCPU;
extern cl::list<std::string> MAttrs;

static cl::opt<bool>
UseDbg("g",
cl::desc("Print line information from debug info if available"));

static cl::opt<std::string> DSYMFile("dsym",
cl::desc("Use .dSYM file for debug info"));

static cl::opt<bool> FullLeadingAddr("full-leading-addr",
cl::desc("Print full leading address"));

static cl::opt<bool> NoLeadingHeaders("no-leading-headers",
cl::desc("Print no leading headers"));
cl::opt<bool>
ArchiveMemberOffsets("archive-member-offsets",
cl::desc("Print the offset to each archive member for "
"Mach-O archives (requires -macho and "
"-archive-headers)"));

cl::opt<bool>
mctoll::NonVerbose("non-verbose",
cl::desc("Print the info for Mach-O objects in "
"non-verbose or numeric form (requires -macho)"));

cl::opt<std::string> mctoll::DisSymName(
"dis-symname",
cl::desc("disassemble just this symbol's instructions (requires -macho)"));

static cl::opt<bool> NoSymbolicOperands(
"no-symbolic-operands",
cl::desc("do not symbolic operands when disassembling (requires -macho)"));

static cl::list<std::string>
ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
cl::ZeroOrMore);
extern std::string MCPU;
extern std::vector<std::string> MAttrs;

static std::string DisSymName;
static bool PrintImmHex;
static bool UseDbg;
static std::string DSYMFile;
static bool FullLeadingAddr;
static bool NoLeadingHeaders;
// static bool ArchiveMemberOffsets;
static bool NonVerbose;
static bool NoSymbolicOperands;
static std::vector<std::string> ArchFlags;

bool ArchAll = false;

Expand Down
103 changes: 103 additions & 0 deletions Opts.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
include "llvm/Option/OptParser.td"

// Don't show this flags
def HelpSkipped : OptionFlag;

def help : Flag<["--"], "help">,
HelpText<"Display available options (--help-hidden for more)">;
def h : Flag<["-"], "h">, Alias<help>, HelpText<"Alias for --help">, Flags<[HelpHidden]>;

def help_hidden : Flag<["--"], "help-hidden">,
Flags<[HelpHidden]>,
HelpText<"Display all available options">;

def version : Flag<["--"], "version">,
HelpText<"Display the version of this program">;

def debug : Flag<["-"], "debug">, Flags<[HelpHidden]>;

def raise : Flag<["--"], "raise">,
HelpText<"Raise machine instruction">;
def : Flag<["-"], "d">, Alias<raise>, HelpText<"Alias for --raise">;

def include_file_EQ : Joined<["--"], "include-file=">,
HelpText<"Header file with function prototypes using standard C syntax.">;
def : Separate<["--"], "include-file">, Alias<include_file_EQ>, Flags<[HelpSkipped]>;
def : Separate<["-"], "I">, Alias<include_file_EQ>,
HelpText<"Alias for --include-file">;

def include_files_EQ : Joined<["--"], "include-files=">,
HelpText<"List of comma-seperated header files with function prototypes using standard C syntax.">;

def filter_functions_file_EQ : Joined<["--"], "filter-functions-file=">,
HelpText<"Specify which functions to raise via a configuration file.">;
def : Separate<["--"], "filter-functions-file">, Alias<filter_functions_file_EQ>, Flags<[HelpSkipped]>;
def : Separate<["-"], "f">, Alias<filter_functions_file_EQ>,
HelpText<"Alias for --filter-functions-file">;

def mcpu_EQ : Joined<["--"], "mcpu=">,
MetaVarName<"cpu-name">,
HelpText<"Target a specific cpu type (--mcpu=help for details)">,
Flags<[HelpHidden]>;

def mattr_EQ : Joined<["--"], "mattr=">,
MetaVarName<"a1,+a2,-a3,...">,
HelpText<"Target specific attributes (--mattr=help for details)">,
Flags<[HelpHidden]>;

def outfile_EQ : Joined<["--"], "outfile=">,
HelpText<"Output filename">;
def : Separate<["--"], "outfile">, Alias<outfile_EQ>, Flags<[HelpSkipped]>;
def : Separate<["-"], "o">, Alias<outfile_EQ>,
HelpText<"Alias for --outfile">;

class OutputFormatOpts<string base>
: KeyPathAndMacro<"OutputFormatOpts->", base, "OUTPUT_FORMAT_"> {}

def output_format_EQ : Joined<["--"], "output-format=">,
HelpText<"Output format: "
"'ll' (emit llvm text bitcode ('.ll') file) | "
"'bc' (emit llvm binary bitcode ('.bc') file) | "
"'null' (emit nothing, for performance testing). "
"Default is 'll'."
>,
Values<"ll,bc,null">,
NormalizedValuesScope<"OutputFormatTy">,
NormalizedValues<["LL", "BC", "Null"]>,
MarshallingInfoEnum<OutputFormatOpts<"OutputFormatTy">, "LL">,
Flags<[HelpHidden]>;

def run_pass_EQ : Joined<["--"], "run-pass=">,
MetaVarName<"pass-name">,
HelpText<"Run compiler only for specified passes (comma separated list)">,
Flags<[HelpHidden]>;
def : Separate<["--"], "run-pass">, Alias<run_pass_EQ>, Flags<[HelpSkipped]>;

def start_address_EQ : Joined<["--"], "start-address=">,
MetaVarName<"address">,
HelpText<"Disassemble beginning at address">,
Flags<[HelpHidden]>;
def : Separate<["--"], "start-address">, Alias<start_address_EQ>, Flags<[HelpSkipped]>;
def stop_address_EQ : Joined<["--"], "stop-address=">,
MetaVarName<"address">,
HelpText<"Stop disassembly at address">,
Flags<[HelpHidden]>;
def : Separate<["--"], "stop-address">, Alias<stop_address_EQ>, Flags<[HelpSkipped]>;

def section_EQ : Joined<["--"], "section=">,
HelpText<"Operate on the specified sections only. "
"With --macho dump segment,section">,
Flags<[HelpHidden]>;
def : Separate<["--"], "section">, Alias<section_EQ>, Flags<[HelpSkipped]>;
def : Separate<["-"], "j">, Alias<section_EQ>,
HelpText<"Alias for --section">,
Flags<[HelpHidden]>;

def sysyroot_EQ : Joined<["--"], "sysroot=">,
HelpText<"Toolchain sysroot">;
def : Separate<["--"], "sysroot">, Alias<sysyroot_EQ>, Flags<[HelpSkipped]>;

def target_EQ : Separate<["-"], "target">,
HelpText<"Target triple to disassemble for, "
"see --version for available targets">,
Flags<[HelpHidden]>;
61 changes: 26 additions & 35 deletions Raiser/IncludedFileInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class FuncDeclVisitor : public clang::RecursiveASTVisitor<FuncDeclVisitor> {
std::pair<std::string, IncludedFileInfo::FunctionRetAndArgs>(
FuncDecl->getQualifiedNameAsString(), Entry));
LLVM_DEBUG(dbgs() << FuncDecl->getQualifiedNameAsString()
<< " : Entry found at "
<< " : Added entry found at "
<< FuncDecl->getLocation().printToString(
Context.getSourceManager())
<< "\n");
Expand Down Expand Up @@ -151,16 +151,16 @@ class FuncDeclFinder : public clang::ASTConsumer {

void HandleTranslationUnit(clang::ASTContext &Context) final {
auto Decls = Context.getTranslationUnitDecl()->decls();
clang::SourceManager &SourceManager(Context.getSourceManager());
for (auto &Decl : Decls) {
if (Decl->isFunctionOrFunctionTemplate()) {
const auto &FileID = SourceManager.getFileID(Decl->getLocation());
if (FileID != SourceManager.getMainFileID())
continue;
if (Decl->isFunctionOrFunctionTemplate() && Decl->isFirstDecl()) {
clang::FunctionDecl *FuncDecl = Decl->getAsFunction();
LLVM_DEBUG(dbgs() << FuncDecl->getQualifiedNameAsString() << " : Visit "
<< FuncDecl->getLocation().printToString(
Context.getSourceManager())
<< "\n");
Visitor.TraverseFunctionDecl(FuncDecl);
} else if (Decl->getKind() == clang::Decl::Kind::Var) {
auto VarDecl = dyn_cast<clang::VarDecl>(Decl);
auto *VarDecl = dyn_cast<clang::VarDecl>(Decl);
IncludedFileInfo::ExternalVariables.insert(
VarDecl->getQualifiedNameAsString());
}
Expand Down Expand Up @@ -225,42 +225,33 @@ Function *IncludedFileInfo::CreateFunction(StringRef &CFuncName,
}

bool IncludedFileInfo::getExternalFunctionPrototype(
std::vector<std::string> &FileNames, std::string &CompDBDir) {
static llvm::cl::OptionCategory InclFileParseCategory(
"parse-header-files options");
std::vector<std::string> &FileNames, std::string &Target,
std::string &SysRoot) {
std::vector<const char *> ArgPtrVec;
ArgPtrVec.push_back("parse-header-files");
if (!CompDBDir.empty()) {
ArgPtrVec.push_back("-p");
ArgPtrVec.push_back(CompDBDir.c_str());
}
if (llvm::DebugFlag)
ArgPtrVec.push_back("-debug");
ArgPtrVec.push_back("--");

// Dummy positional arguments to satisfy the requirement of having at least
// two positional arguments.
ArgPtrVec.push_back("dummy-positional-arg-1");
ArgPtrVec.push_back("dummy-positional-arg-2");

if (CompDBDir.empty())
ArgPtrVec.push_back("--");
if (llvm::DebugFlag)
ArgPtrVec.push_back("-v");
if (!Target.empty()) {
ArgPtrVec.push_back("-target");
ArgPtrVec.push_back(Target.c_str());
}
if (!SysRoot.empty()) {
ArgPtrVec.push_back("--sysroot");
ArgPtrVec.push_back(SysRoot.c_str());
}

auto *ToolArgv = ArgPtrVec.data();
int ArgSz = ArgPtrVec.size();

// Construct a CommonOptionsParser object for the Compilations.
auto ExpParser = clang::tooling::CommonOptionsParser::create(
ArgSz, ToolArgv, InclFileParseCategory);

if (!ExpParser) {
llvm::errs() << ExpParser.takeError();
return 1;
}
clang::tooling::CommonOptionsParser &OptParser = ExpParser.get();
// Pass include FileNames vector and NOT OptParser.getSourcePathList() since
// only a dymmy-positional-arg was passed while constructing OptParser.
clang::tooling::ClangTool Tool(OptParser.getCompilations(), FileNames);
std::string ErrorMessage;
std::unique_ptr<clang::tooling::CompilationDatabase> Compilations =
clang::tooling::FixedCompilationDatabase::loadFromCommandLine(ArgSz, ToolArgv, ErrorMessage);
if (!ErrorMessage.empty())
llvm::errs() << ErrorMessage.append("\n");

clang::tooling::ClangTool Tool(*Compilations, FileNames);
int Success = Tool.run(
clang::tooling::newFrontendActionFactory<FuncDeclFindingAction>().get());
switch (Success) {
Expand Down
3 changes: 2 additions & 1 deletion Raiser/IncludedFileInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class IncludedFileInfo {
static std::set<std::string> ExternalVariables;

static bool getExternalFunctionPrototype(std::vector<string> &FileNames,
std::string &CompDBDir);
std::string &Target,
std::string &SysRoot);

static bool IsExternalVariable(std::string Name);
};
Expand Down
2 changes: 1 addition & 1 deletion X86/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ add_llvm_library(mctollX86Raiser
TransformUtils
)

target_link_libraries(mctollX86Raiser PRIVATE mctollRaiser)
target_link_libraries(mctollX86Raiser PRIVATE mctollRaiser)
68 changes: 68 additions & 0 deletions doc/sysroot_flag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
## Using --sysroot flag

--sysroot points to toolchain root. It is useful during development on a non-Linux machine to raise Linux binaries or on a Linux machine using a toolchain other than the one installed.

* On linux sysroot is "/"
* On MAC may show `xcrun --show-sdk-path`

### Cross-building Linux x86_64 and arm binaries

Instructions to build a minimal functional toolchain that may be used with `llvm-mctoll` are provided [here](https://github.com/sv99/llvm-mctoll-toolchains). These facilitate cross compilation of and raising of x86_64-linux-gnu and for arm-linux-gnueabihf targets. You may choose to create and use a toolchain of your choice.
```bash
# toolchain directory
# ~/toolchain/arm-linux-gnueabihf
# ~/toolchain/x86_64-linux-gnu
# clang must be built with ARM support!

# ELF 32-bit ARM Linux
clang --sysroot ~/toolchain/arm-linux-gnueabihf \
-target arm-linux-gnueabihf -fuse-ld=lld \
-o hello-arm -v hello.c
file helllo-arm

# ELF 64-bit x86_64 Linux
clang --sysroot ~/toolchain/x86_64-linux-gnu \
-target x86_64-linux-gnu -fuse-ld=lld \
-o hello-lin -v hello.c
file helllo-lin
```

The above has been tested to work on MacOS (and Linux).

### Raising Linux binary on a non-Linux host

Toolchains needs for successful parsing header file.

```c
# header-inc.h
#include <stdio.h>
```

```bash
# ELF 32-bit ARM Linux
llvm-mctoll --sysroot ~/toolchain/arm-linux-gnueabihf \
-target arm-linux-gnueabihf -I header-inc.h \
-debug -d hello-arm
# ELF 64-bit x86_64 Linux
lvm-mctoll --sysroot ~/toolchain/x86_64-linux-gnu \
-target x86_64-linux-gnu -I header-inc.h \
-debug -d hello-arm
```

### Running Linux ARM binary using docker on a non-Linux development host

[multiarch/qemu-user-static](https://github.com/multiarch/qemu-user-static) is to enable
an execution of different multi-architecture containers

```bash
# prepare docker
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
```

```bash
# run x86_64-linux-gnu binary
docker run --rm -it -v $(pwd):/work amd64/ubuntu:20.04 /work/hello-linux

# run arm-linux-gnueabihf binary
docker run --rm -it -v $(pwd):/work arm32v7/ubuntu:20.04 /work/hello-arm
```
Loading

0 comments on commit d32a1ba

Please sign in to comment.