Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ test_relocate_dll: build_and_check_test_sample
mkdir tmp_lib
move test\calc.dll tmp_bin\calc.dll
move test\calc.lib tmp_lib\calc.lib
test\relocate.exe --pe tmp_bin\calc.dll --coff tmp_lib\calc.lib --export
test\relocate.exe --pe tmp_bin\calc.dll --coff tmp_lib\calc.lib
cd test
del tester.exe
link main.obj ..\tmp_lib\calc.lib /out:tester.exe
Expand Down Expand Up @@ -209,7 +209,7 @@ test_relocate_long_paths: test_long_paths
mkdir tmp_lib
move evenlongersubdirectoryname\verylongfilepathnamethatwilldefinitelybegreaterthanonehundredandfourtyfourcharacters.dll tmp_bin\verylongfilepathnamethatwilldefinitelybegreaterthanonehundredandfourtyfourcharacters.dll
move evenlongersubdirectoryname\verylongfilepathnamethatwilldefinitelybegreaterthanonehundredandfourtyfourcharacters.lib tmp_lib\verylongfilepathnamethatwilldefinitelybegreaterthanonehundredandfourtyfourcharacters.lib
evenlongersubdirectoryname\relocate.exe --pe tmp_bin\verylongfilepathnamethatwilldefinitelybegreaterthanonehundredandfourtyfourcharacters.dll --coff tmp_lib\verylongfilepathnamethatwilldefinitelybegreaterthanonehundredandfourtyfourcharacters.lib --export
evenlongersubdirectoryname\relocate.exe --pe tmp_bin\verylongfilepathnamethatwilldefinitelybegreaterthanonehundredandfourtyfourcharacters.dll --coff tmp_lib\verylongfilepathnamethatwilldefinitelybegreaterthanonehundredandfourtyfourcharacters.lib
cd evenlongersubdirectoryname
del tester.exe
link main.obj ..\tmp_lib\verylongfilepathnamethatwilldefinitelybegreaterthanonehundredandfourtyfourcharacters.lib /out:tester.exe
Expand Down
26 changes: 0 additions & 26 deletions src/commandline.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,6 @@ bool print_help() {
"said library is regenerated and the old imp lib\n";
std::cout << " "
"replaced.\n";
std::cout << " --export|--deploy = "
"Mutually exclusive command modifier.\n";
std::cout << " "
"Instructs relocate to either prepare the\n";
std::cout << " "
"dynamic library for exporting to build cache\n";
std::cout << " "
"or for extraction from bc onto new host system\n";
std::cout << " --report = "
"Report information about the parsed PE/Coff files\n";
std::cout << " --debug|-d = "
Expand Down Expand Up @@ -149,24 +141,6 @@ std::map<std::string, std::string> ParseRelocate(const char** args, int argc) {
return opts;
}
opts.insert(std::pair<std::string, std::string>("full", "full"));
} else if (!strcmp(args[i], "--export")) {
// export and deploy are mutually exclusive, if one is defined
// the other cannot be
if (redefinedArgCheck(opts, "export", "--export") ||
redefinedArgCheck(opts, "deploy", "--deploy")) {
opts.clear();
return opts;
}
opts.insert(std::pair<std::string, std::string>("cmd", "export"));
} else if (!strcmp(args[i], "--deploy")) {
// export and deploy are mutually exclusive, if one is defined
// the other cannot be
if (redefinedArgCheck(opts, "export", "--export") ||
redefinedArgCheck(opts, "deploy", "--deploy")) {
opts.clear();
return opts;
}
opts.insert(std::pair<std::string, std::string>("cmd", "deploy"));
} else if (!strcmp(args[i], "--debug") || !strcmp(args[i], "-d")) {
opts.insert(std::pair<std::string, std::string>("debug", "on"));
} else if (!strcmp(args[i], "--verify")) {
Expand Down
13 changes: 5 additions & 8 deletions src/main.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ int main(int argc, const char* argv[]) {
return -1;
}
bool const full = !(patch_args.find("full") == patch_args.end());
bool const deploy = !(patch_args.find("cmd") == patch_args.end()) &&
patch_args.at("cmd") == "deploy";
bool const report = !(patch_args.find("report") == patch_args.end());
bool const has_pe = !(patch_args.find("pe") == patch_args.end());
bool const debug = !(patch_args.find("debug") == patch_args.end());
Expand Down Expand Up @@ -77,12 +75,11 @@ int main(int argc, const char* argv[]) {
std::unique_ptr<LibRename> rpath_lib;
try {
if (has_coff) {
rpath_lib = std::make_unique<LibRename>(patch_args.at("pe"),
patch_args.at("coff"),
full, deploy, true);
rpath_lib = std::make_unique<LibRename>(
patch_args.at("pe"), patch_args.at("coff"), full, true);
} else {
rpath_lib = std::make_unique<LibRename>(patch_args.at("pe"),
full, deploy, true);
full, true);
}
} catch (const NameTooLongError& e) {
std::cerr << "Cannot Rename PE file " << patch_args.at("pe")
Expand All @@ -104,8 +101,8 @@ int main(int argc, const char* argv[]) {
}
if (report_args.find("pe") != report_args.end()) {
try {
LibRename portable_executable(
report_args.at("pe"), std::string(), false, false, true);
LibRename portable_executable(report_args.at("pe"),
std::string(), false, true);
portable_executable.ExecuteRename();
} catch (const NameTooLongError& e) {
std::cerr
Expand Down
142 changes: 49 additions & 93 deletions src/winrpath.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* SPDX-License-Identifier: (Apache-2.0 OR MIT)
*/
#include <cstdio>
#include <stdio.h>
#include <windows.h> // NOLINT
#include "winrpath.h"
#include <fileapi.h>
Expand All @@ -27,38 +26,22 @@
#include <regex>

/*
* Checks a DLL name for special characters, if we're deploying, a path character, if we're
* relocating a spack sigil
* Checks a DLL name for path characters
*
* Path characters are not typically found in DLLs outside of those produced by this compiler wrapper
* and as such are an indication this is a Spack produced binary
*
* Spack sigils will not be found anywhere but a Spack produced binary as well
*
* \param name The dll name to check for sigils or special path characters
* \param name The dll name to check for path characters
*
*/
bool LibRename::SpackCheckForDll(const std::string& dll_path) const {
if (this->deploy) {
return hasPathCharacters(dll_path);
}
// First check for the case we're relocating out of a buildcache
bool reloc_spack = false;
if (!(dll_path.find("<!spack>") == std::string::npos) ||
!(dll_path.find("<sp>") == std::string::npos)) {
reloc_spack = true;
}
// If not, maybe we're just relocating a binary on the same system
if (!reloc_spack) {
reloc_spack = hasPathCharacters(dll_path);
}
return reloc_spack;
return hasPathCharacters(dll_path);
}

/*
* Actually performs the DLL rename, given the DLL location in mapped memory view
* determines the required padding for a name, if deploying, the proper length of a sigil
* then either writes the sigil'd name back into the memory map, or gets the new path to a dll
* determines the required padding for a name, gets the new path to a dll
* re-pads it, and then writes that into the DLL name location.
*
* \param name_loc Raw offset to the imported DLL name
Expand All @@ -68,61 +51,45 @@ bool LibRename::SpackCheckForDll(const std::string& dll_path) const {
*
*/
bool LibRename::RenameDll(char* name_loc, const std::string& dll_path) const {
if (this->deploy) {
int const padding_len = get_padding_length(dll_path);
if (padding_len < MIN_PADDING_THRESHOLD) {
// path is too long to mark as a Spack path
// use shorter sigil
char short_sigil[] = "<sp>";
// use _snprintf as it does not null terminate and we're writing into the middle
// of a null terminated string we want to later read from properly
_snprintf(name_loc, sizeof(short_sigil) - 1, "%s", short_sigil);
} else {
char long_sigil[] = "<!spack>";
// See _snprintf comment above for use context
_snprintf(name_loc, sizeof(long_sigil) - 1, "%s", long_sigil);
}
} else {
if (SpackInstalledLib(dll_path)) {
return true;
}
std::string const file_name = basename(dll_path);
if (file_name.empty()) {
std::cerr << "Unable to extract filename from dll for relocation"
<< "\n";
if (SpackInstalledLib(dll_path)) {
return true;
}
std::string const file_name = basename(dll_path);
if (file_name.empty()) {
std::cerr << "Unable to extract filename from dll for relocation"
<< "\n";
return false;
}
LibraryFinder lib_finder;
std::string new_library_loc =
lib_finder.FindLibrary(file_name, dll_path);
if (new_library_loc.empty()) {
std::cerr << "Unable to find library " << file_name << " from "
<< dll_path << " for relocation" << "\n";
return false;
}
if (new_library_loc.length() > MAX_NAME_LEN) {
try {
new_library_loc = short_name(new_library_loc);
} catch (NameTooLongError& e) {
return false;
}
LibraryFinder lib_finder;
std::string new_library_loc =
lib_finder.FindLibrary(file_name, dll_path);
if (new_library_loc.empty()) {
std::cerr << "Unable to find library " << file_name << " from "
<< dll_path << " for relocation" << "\n";
} catch (FileNotExist &e) {
return false;
}
if (new_library_loc.length() > MAX_NAME_LEN) {
try {
new_library_loc = short_name(new_library_loc);
} catch (NameTooLongError& e) {
return false;
} catch (FileNotExist &e) {
return false;
} catch (SFNProcessingError &e) {
return false;
}
}
char* new_lib_pth =
pad_path(new_library_loc.c_str(),
static_cast<DWORD>(new_library_loc.size()));
if (!new_lib_pth) {
} catch (SFNProcessingError &e) {
return false;
}
replace_special_characters(new_lib_pth, MAX_NAME_LEN);

// c_str returns a proper (i.e. null terminated) value, so we dont need to worry about
// size differences w.r.t the path to the new library
snprintf(name_loc, MAX_NAME_LEN + 1, "%s", new_lib_pth);
}
char* new_lib_pth =
pad_path(new_library_loc.c_str(),
static_cast<DWORD>(new_library_loc.size()));
if (!new_lib_pth) {
return false;
}
replace_special_characters(new_lib_pth, MAX_NAME_LEN);

// c_str returns a proper (i.e. null terminated) value, so we dont need to worry about
// size differences w.r.t the path to the new library
snprintf(name_loc, MAX_NAME_LEN + 1, "%s", new_lib_pth);
return true;
}

Expand All @@ -134,12 +101,10 @@ bool LibRename::RenameDll(char* name_loc, const std::string& dll_path) const {
*
* Decompose the PE file into a series of structs to locate the IMPORT section
* Parse the IMPORT section for the names of all imported DLLS
* If a given DLL name is a Spack derived DLL name, identifiable via the
* spack sigil or the fact there are path characters in the DLL name, which is not
* normally the case without Spack, depending on the operation, the name is modified
* If we're performing a deployment to a buildcache, we mark the name with a spack sigil
* to identify it as one in need of relocation post builcache extraction
* On extraction, we find dll names with the Spack sigil and rename (and repad) them with
* If a given DLL name is a Spack derived DLL name, identifiable via fact there are
* path characters in the DLL name, which is not normally the case without Spack,
* depending on the operation, the name is modified.
* On extraction, we find dll names with path characters and rename (and repad) them with
* the correct absolute path to the requisite DLL on the new host system.
*
* This approach is heavily based on
Expand Down Expand Up @@ -229,13 +194,6 @@ bool LibRename::FindDllAndRename(HANDLE& pe_in) {
* LibRename is responsible for renaming and relocating DLLs and
* their corresponding import libraries
*
* Deploy - this flag determines whether or not this invocation is
* being used to prepare a binary for deployment into a
* build cache. If this is true, the import library is not
* re-written to create an absolute path, and the dll names
* in the dll are not made to be absolute paths, instead
* a spack sigil is injected into the names so we can identify
* them as Spack paths
* Full - this flag informs the process as to whether we're relocating a DLL or
* just its import library. If we're doing a "full" pass, we
* produce a new import library with the absolute path to its dll
Expand All @@ -249,15 +207,15 @@ bool LibRename::FindDllAndRename(HANDLE& pe_in) {
* \param replace a flag indicating if we're replacing the renamed import lib or making a copy with absolute dll names
* \param report a flag indicating if we should be reporting the contents of the PE/COFF file we're parsing to stdout
*/
LibRename::LibRename(std::string p_exe, bool full, bool deploy, bool replace)
: replace(replace), full(full), pe(std::move(p_exe)), deploy(deploy) {}
LibRename::LibRename(std::string p_exe, bool full, bool replace)
: replace(replace), full(full), pe(std::move(p_exe)) {
}

LibRename::LibRename(std::string p_exe, std::string coff, bool full,
bool deploy, bool replace)
bool replace)
: replace(replace),
full(full),
pe(std::move(p_exe)),
deploy(deploy),
coff(std::move(coff)) {
std::string const coff_path = stem(this->coff);
this->tmp_def_file = coff_path + "-tmp.def";
Expand Down Expand Up @@ -350,12 +308,10 @@ bool LibRename::ComputeDefFile() {
* On standard extraction, we want to regenerate the import library
* from our import library pointing to the new location of the dll/exe
* post buildcache extraction
*
* On a full deployment, we mark the spack based DLL names in the binary
* with a spack sigil <sp!>
*
*
* On a full extraction, in addition to the standard extraction operation
* we rename the Dll names marked with the spack sigil (<sp!>)
* we rename the Dll names that have paths
*
*/
bool LibRename::ExecuteRename() {
Expand All @@ -364,7 +320,7 @@ bool LibRename::ExecuteRename() {
// exes
// We do not bother with defs for things that don't have
// import libraries
if (!this->deploy && !this->coff.empty()) {
if (!this->coff.empty()) {
// Extract DLL
if (!this->ComputeDefFile()) {
debug("Failed to compute def file");
Expand Down
6 changes: 2 additions & 4 deletions src/winrpath.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@

class LibRename {
public:
LibRename(std::string p_exe, std::string coff, bool full, bool deploy,
bool replace);
LibRename(std::string p_exe, bool full, bool deploy, bool replace);
LibRename(std::string p_exe, std::string coff, bool full, bool replace);
LibRename(std::string p_exe, bool full, bool replace);
bool ExecuteRename();
bool ExecuteLibRename();
bool ExecutePERename();
Expand All @@ -53,6 +52,5 @@ class LibRename {
std::string def_file;
std::string tmp_def_file;
bool full;
bool deploy;
bool replace;
};
Loading