diff --git a/Makefile b/Makefile index 38a71c8..975b8ad 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ cl.exe : $(SRCS) link $(LFLAGS) $** $(API_LIBS) /out:cl.exe install : cl.exe - @if not exist "$(PREFIX)" mkdir "$(PREFIX)"" + @if not exist "$(PREFIX)" mkdir "$(PREFIX)" @if not exist "$(PREFIX)\cl.exe" move cl.exe "$(PREFIX)" @if not exist "$(PREFIX)\link.exe" mklink "$(PREFIX)\link.exe" "$(PREFIX)\cl.exe" @if not exist "$(PREFIX)\ifx.exe" mklink "$(PREFIX)\ifx.exe" "$(PREFIX)\cl.exe" diff --git a/src/coff_reader_writer.cxx b/src/coff_reader_writer.cxx index 6e34736..abddb60 100644 --- a/src/coff_reader_writer.cxx +++ b/src/coff_reader_writer.cxx @@ -30,7 +30,8 @@ bool CoffReaderWriter::Open() { return false; } try { - ScopedFileAccess const obtain_write(coff_file, GENERIC_ALL); + ScopedFileAccess obtain_write(coff_file, GENERIC_ALL); + obtain_write.Access(); this->pe_stream_.open(this->file_, std::ios::in | std::ios::out | std::ios::binary); return this->pe_stream_.is_open(); diff --git a/src/commandline.cxx b/src/commandline.cxx index df2bff1..9d977e0 100644 --- a/src/commandline.cxx +++ b/src/commandline.cxx @@ -178,11 +178,11 @@ std::map ParseReport(int argc, const char** args) { return opts; } -bool CheckAndPrintHelp(const char** arg, int argc) { - if (argc < 2) { +bool CheckAndPrintHelp(const char** arg, bool no_args, bool is_report, bool is_relocate) { + if (no_args && (is_relocate || is_report)) { return print_help(); } - if (strcmp(arg[1], "--help") == 0 || strcmp(arg[1], "-h") == 0) { + if (!no_args && (strcmp(arg[1], "--help") == 0 || strcmp(arg[1], "-h") == 0)) { return print_help(); } return false; diff --git a/src/commandline.h b/src/commandline.h index 28c93e2..d0e1cd5 100644 --- a/src/commandline.h +++ b/src/commandline.h @@ -19,4 +19,4 @@ std::map ParseRelocate(const char** args, int argc); std::map ParseReport(int argc, const char** args); // Writes CLI help message to stdout -bool CheckAndPrintHelp(const char** arg, int argc); \ No newline at end of file +bool CheckAndPrintHelp(const char** arg, bool no_args, bool is_report, bool is_relocate); \ No newline at end of file diff --git a/src/ld.cxx b/src/ld.cxx index c3fbc76..b6472ac 100644 --- a/src/ld.cxx +++ b/src/ld.cxx @@ -47,6 +47,11 @@ DWORD LdInvocation::InvokeToolchain() { } catch (const FileIOError& e) { return ExitConditions::FILE_IO_FAILURE; } + // If there are no arguments (or the argument is just "/?") + // just print help and return + if(this->inputs.empty() || link_run.isHelp()) { + return ToolChainInvocation::InvokeToolchain(); + } try { link_run.makeRsp(); diff --git a/src/linker_invocation.cxx b/src/linker_invocation.cxx index e7b7b4f..07fe2e7 100644 --- a/src/linker_invocation.cxx +++ b/src/linker_invocation.cxx @@ -78,6 +78,9 @@ void LinkerInvocation::ProcessTokens(const std::string &normal_token, const std: this->piped_args_.end()) { this->piped_args_.at(normal_token).emplace_back(token); } + else if (normal_token == "?") { + this->is_help_ = true; + } } @@ -113,7 +116,9 @@ void LinkerInvocation::Parse() { // /NAME // if no /NAME // first input file (post rc expansion) - + if (this->is_help_ || this->input_files_.empty()) { + return; + } this->processDefFile(); std::string const ext = this->is_exe_ ? ".exe" : ".dll"; if (this->output_.empty()) { @@ -318,3 +323,7 @@ std::string LinkerInvocation::get_mangled_out() const { bool LinkerInvocation::IsExeLink() const { return this->is_exe_ || endswith(this->get_out(), ".exe"); } + +bool LinkerInvocation::isHelp() const { + return this->is_help_; +} diff --git a/src/linker_invocation.h b/src/linker_invocation.h index 2a41639..7429351 100644 --- a/src/linker_invocation.h +++ b/src/linker_invocation.h @@ -24,6 +24,7 @@ class LinkerInvocation { StrList get_input_files() const; std::string get_lib_link_args() const; bool makeRsp(); + bool isHelp() const; private: void ProcessTokens(const std::string &normal_token, const std::string& token); @@ -39,7 +40,8 @@ class LinkerInvocation { StrList command_files_; StrList input_files_; StrList tokens_; - bool is_exe_; + bool is_exe_ = true; + bool is_help_ = false; std::map piped_args_ = { {"export", {}}, {"include", {}}, {"libpath", {}}, {"ltcg", {}}, {"machine", {}}, {"nodefaultlib", {}}, diff --git a/src/main.cxx b/src/main.cxx index 7fa7708..9b704be 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -19,11 +19,13 @@ #include int main(int argc, const char* argv[]) { - - if (CheckAndPrintHelp(argv, argc)) { + const bool is_relocate = IsRelocate(argv[0]); + const bool is_report = IsReport(argv[0]); + const bool no_args = argc < 2; + if (CheckAndPrintHelp(argv, no_args, is_report, is_relocate)) { return 0; } - if (IsRelocate(argv[0])) { + if (is_relocate) { std::map patch_args = ParseRelocate(argv + 1, argc - 1); if (patch_args.empty()) { @@ -90,7 +92,7 @@ int main(int argc, const char* argv[]) { std::cerr << "Library rename failed\n"; return ExitConditions::RENAME_FAILURE; } - } else if (IsReport(argv[0])) { + } else if (is_report) { std::map report_args = ParseReport(argc - 1, argv + 1); if (report_args.empty()) { diff --git a/src/utils.cxx b/src/utils.cxx index 3d8ef6b..582d174 100644 --- a/src/utils.cxx +++ b/src/utils.cxx @@ -428,7 +428,7 @@ std::string stem(const std::string& file) { } std::string basename(const std::string& file) { - size_t const last_path = file.find_last_of('\\') + 1; + size_t const last_path = file.find_last_of("/\\") + 1; if (last_path == std::string::npos) { return file; } diff --git a/src/winrpath.cxx b/src/winrpath.cxx index 7953501..8128265 100644 --- a/src/winrpath.cxx +++ b/src/winrpath.cxx @@ -248,7 +248,7 @@ LibRename::LibRename(std::string p_exe, std::string coff, bool full, /** * Creates the line to be provided to dumpbin.exe to produce the exports of a given * dll in the case where we do not have access to the original link line - * + * * Produces something like `/EXPORTS ` */ std::string LibRename::ComputeDefLine() { @@ -258,7 +258,7 @@ std::string LibRename::ComputeDefLine() { /** * Drives the process of running dumpbin.exe on a PE file to determine its exports * and produce a `.def` file - * + * * Returns the return code of the Def file computation operation */ bool LibRename::ComputeDefFile() { @@ -267,44 +267,28 @@ bool LibRename::ComputeDefFile() { if (def_res) { return false; } - // Need to process the produced def file because it's wrong - // Open input file std::ifstream input_file(this->tmp_def_file); if (!input_file.is_open()) { std::cerr << "Error: Could not open input file " << tmp_def_file << '\n'; return false; } - - // Open output file std::ofstream output_file(this->def_file); if (!output_file.is_open()) { std::cerr << "Error: Could not open output file " << this->def_file << '\n'; return false; } - - // Write the standard .def file header - // You might want to get the DLL name dynamically from the input filename or dumpbin output output_file << "EXPORTS\n"; - std::string line; - // Read until the output column titles while (std::getline(input_file, line)) { - std::smatch search_res = regexSearch(line, R"(ordinal\s+name)"); - if (!search_res.empty()) break; - std::string const res = search_res.str(); - if (!res.empty()) { - break; - } + if (!regexSearch(line, R"(ordinal\s+(?:hint\s+RVA\s+)?name)").empty()) break; } while (std::getline(input_file, line)) { if (line.empty()) { continue; } - if (line.find("Summary") != - std::string:: - npos) { // Skip header in export block if still present + if (line.find("Summary") != std::string::npos) { break; } output_file << " "