diff --git a/macho/cmdline.cc b/macho/cmdline.cc new file mode 100644 index 00000000..e7fb848c --- /dev/null +++ b/macho/cmdline.cc @@ -0,0 +1,89 @@ +#include "mold.h" + +#include +#include +#include +#include +#include + +namespace mold::macho { + +static const char helpmsg[] = R"( +Options: + --help Report usage information + -v Report version information + -o FILE Set output filename +)"; + +bool read_arg(Context &ctx, std::span &args, + std::string_view &arg, std::string name) { + if (args[0] == name) { + if (args.size() == 1) + Fatal(ctx) << "option -" << name << ": argument missing"; + arg = args[1]; + args = args.subspan(2); + return true; + } + return false; +} + +bool read_flag(std::span &args, std::string name) { + if (args[0] == name) { + args = args.subspan(1); + return true; + } + return false; +} + +void parse_nonpositional_args(Context &ctx, + std::vector &remaining) { + std::span args = ctx.cmdline_args; + args = args.subspan(1); + + bool version_shown = false; + + while (!args.empty()) { + std::string_view arg; + + auto read_arg = [&](std::string name) { + if (args[0] == name) { + if (args.size() == 1) + Fatal(ctx) << "option -" << name << ": argument missing"; + arg = args[1]; + args = args.subspan(2); + return true; + } + return false; + }; + + auto read_flag = [&](std::string name) { + if (args[0] == name) { + args = args.subspan(1); + return true; + } + return false; + }; + + if (read_flag("-help") || read_flag("--help")) { + SyncOut(ctx) << "Usage: " << ctx.cmdline_args[0] + << " [options] file...\n" << helpmsg; + exit(0); + } + + if (read_flag("-v")) { + SyncOut(ctx) << mold_version; + } else if (read_arg("-o")) { + ctx.arg.output = arg; + } else { + if (args[0][0] == '-') + Fatal(ctx) << "unknown command line option: " << args[0]; + remaining.push_back(args[0]); + args = args.subspan(1); + } + } + + if (ctx.arg.output.empty()) + ctx.arg.output = "a.out"; +} + +} // namespace mold::macho diff --git a/macho/main.cc b/macho/main.cc index 7b4509ae..011a0094 100644 --- a/macho/main.cc +++ b/macho/main.cc @@ -69,12 +69,6 @@ static i64 assign_offsets(Context &ctx) { int main(int argc, char **argv) { Context ctx; - // Parse command line arguments - if (argc == 1) { - SyncOut(ctx) << "mold macho stub\n"; - exit(0); - } - if (std::string_view(argv[1]) == "-dump") { if (argc != 3) Fatal(ctx) << "usage: ld64.mold -dump \n"; @@ -82,29 +76,25 @@ int main(int argc, char **argv) { exit(0); } - if (std::string_view(argv[1]) == "-out") { - if (argc != 3) - Fatal(ctx) << "usage: ld64.mold -out \n"; - ctx.arg.output = argv[2]; + ctx.cmdline_args = expand_response_files(ctx, argv); + std::vector file_args; + parse_nonpositional_args(ctx, file_args); - create_synthetic_sections(ctx); - fill_symtab(ctx); - export_symbols(ctx); - ctx.load_cmd.compute_size(ctx); - i64 output_size = assign_offsets(ctx); + create_synthetic_sections(ctx); + fill_symtab(ctx); + export_symbols(ctx); + ctx.load_cmd.compute_size(ctx); + i64 output_size = assign_offsets(ctx); - ctx.output_file = - std::make_unique(ctx, ctx.arg.output, output_size, 0777); - ctx.buf = ctx.output_file->buf; + ctx.output_file = + std::make_unique(ctx, ctx.arg.output, output_size, 0777); + ctx.buf = ctx.output_file->buf; - for (OutputSegment *seg : ctx.segments) - seg->copy_buf(ctx); + for (OutputSegment *seg : ctx.segments) + seg->copy_buf(ctx); - ctx.output_file->close(ctx); - exit(0); - } - - Fatal(ctx) << "usage: ld64.mold\n"; + ctx.output_file->close(ctx); + return 0; } } diff --git a/macho/mold.h b/macho/mold.h index e7678bde..9309dff3 100644 --- a/macho/mold.h +++ b/macho/mold.h @@ -329,6 +329,13 @@ public: void dump_file(std::string path); +// +// cmdline.cc +// + +void parse_nonpositional_args(Context &ctx, + std::vector &remaining); + // // main.cc // @@ -348,14 +355,20 @@ struct Context { struct { bool demangle = false; bool fatal_warnings = false; + std::string chroot; std::string output; } arg; + std::vector cmdline_args; + bool has_error = false; std::unique_ptr output_file; u8 *buf; + tbb::concurrent_vector> string_pool; + tbb::concurrent_vector>> mf_pool; + OutputSegment text_seg{"__TEXT", VM_PROT_READ | VM_PROT_EXECUTE, 0}; OutputSegment data_const_seg{"__DATA_CONST", VM_PROT_READ | VM_PROT_WRITE, SG_READ_ONLY};