Skip to content
Open
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
5 changes: 2 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ name: ci

on: [pull_request, push]


concurrency:
group: ci-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
cancel-in-progress: true
Expand Down Expand Up @@ -35,5 +34,5 @@ jobs:
- uses: actions/upload-artifact@v4
if: always()
with:
name: tester
path: tmp/test/tester.exe
name: tests
path: tmp
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@
*.exp
*.hex
*.def
*.res
*.rc

# Vscode
/.vscode/

# ignore patch files
*.patch
*.patch

.clang-tidy
.clang-format
102 changes: 64 additions & 38 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ BUILD_LINK = /DEBUG
BASE_CFLAGS = /EHsc
CFLAGS = $(BASE_CFLAGS) $(BUILD_CFLAGS) $(CLFLAGS)
LFLAGS = $(BUILD_LINK) $(LINKFLAGS)
API_LIBS = Shlwapi.lib \
Pathcch.lib \
Advapi32.lib

SRCS = cl.obj \
execute.obj \
Expand All @@ -55,7 +58,7 @@ linker_invocation.obj
all : install test

cl.exe : $(SRCS)
link $(LFLAGS) $** Shlwapi.lib /out:cl.exe
link $(LFLAGS) $** $(API_LIBS) /out:cl.exe

install : cl.exe
mkdir $(PREFIX)
Expand All @@ -66,9 +69,10 @@ install : cl.exe
mklink $(PREFIX)\relocate.exe $(PREFIX)\cl.exe

setup_test: cl.exe
echo "-------------------"
echo "Running Test Setup"
echo "-------------------"
@echo \n
@echo -------------------
@echo Running Test Setup
@echo -------------------
-@ if NOT EXIST "tmp\test" mkdir "tmp\test"
cd tmp\test
copy ..\..\cl.exe cl.exe
Expand All @@ -80,9 +84,9 @@ setup_test: cl.exe
# * space in a path - preserved by quoted arguments
# * escaped quoted arguments
build_and_check_test_sample : setup_test
echo "--------------------"
echo "Building Test Sample"
echo "--------------------"
@echo --------------------
@echo Building Test Sample
@echo --------------------
cd tmp\test
cl /c /EHsc "..\..\test\src file\calc.cxx" /DCALC_EXPORTS /DCALC_HEADER="\"calc header/calc.h\"" /I ..\..\test\include
cl /c /EHsc ..\..\test\main.cxx /I ..\..\test\include
Expand All @@ -94,9 +98,10 @@ build_and_check_test_sample : setup_test
# Test basic wrapper behavior - did the absolute path to the DLL get injected
# into the executable
test_wrapper : build_and_check_test_sample
echo "--------------------"
echo "Running Wrapper Test"
echo "--------------------"
@echo \n
@echo --------------------
@echo Running Wrapper Test
@echo --------------------
cd tmp
move test\tester.exe .\tester.exe
.\tester.exe
Expand All @@ -110,62 +115,77 @@ test_wrapper : build_and_check_test_sample

# Test relocating an executable - re-write internal paths to dlls
test_relocate_exe: build_and_check_test_sample
echo "--------------------------"
echo "Running Relocate Exe Test"
echo "--------------------------"
@echo \n
@echo --------------------------
@echo Running Relocate Exe Test
@echo --------------------------
cd tmp\test
-@ if NOT EXIST "relocate.exe" mklink relocate.exe cl.exe
move calc.dll ..\calc.dll
relocate.exe --pe tester.exe --deploy --full
relocate.exe --pe tester.exe --export --full
SET SPACK_RELOCATE_PATH=$(MAKEDIR)\tmp\test\calc.dll|$(MAKEDIR)\tmp\calc.dll
relocate.exe --pe tester.exe --full
tester.exe
move ..\calc.dll calc.dll
cd ../..

# Test relocating a dll - re-write import library
test_relocate_dll: build_and_check_test_sample
echo "--------------------------"
echo "Running Relocate DLL test"
echo "--------------------------"
@echo \n
@echo --------------------------
@echo Running Relocate DLL test
@echo --------------------------
cd tmp/test
-@ if NOT EXIST "relocate.exe" mklink relocate.exe cl.exe
cd ..
mkdir tmp_bin
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
.\tester.exe
cd ../..

test_pipe_overflow: build_and_check_test_sample
echo "--------------------"
echo " Pipe overflow test"
echo "--------------------"
test_pipe_out_overflow: build_and_check_test_sample
@echo \n
@echo ---------------------------
@echo Pipe stdout overflow test
@echo ---------------------------
set SPACK_CC_TMP=%SPACK_CC%
set SPACK_CC=$(MAKEDIR)\test\lots-of-output.bat
cl /c /EHsc "test\src file\calc.cxx"
set SPACK_CC=%SPACK_CC_TMP%

test_pipe_error_overflow: build_and_check_test_sample
@echo \n
@echo ---------------------------
@echo Pipe stderr overflow test
@echo ---------------------------
set SPACK_CC_TMP=%SPACK_CC%
set SPACK_CC=$(MAKEDIR)\test\lots-of-error.bat
cl /c /EHsc "test\src file\calc.cxx"
set SPACK_CC=%SPACK_CC_TMP%

build_zerowrite_test: test\writezero.obj
link $(LFLAGS) $** Shlwapi.lib /out:writezero.exe
link $(LFLAGS) $** $(API_LIBS) /out:writezero.exe

test_zerowrite: build_zerowrite_test
echo "-----------------------"
echo "Running zerowrite test"
echo "-----------------------"
@echo \n
@echo -----------------------
@echo Running zerowrite test
@echo -----------------------
set SPACK_CC_TMP=%SPACK_CC%
set SPACK_CC=$(MAKEDIR)\writezero.exe
cl /c EHsc "test\src file\calc.cxx"
set SPACK_CC=%SPACK_CC_TMP%

test_long_paths: build_and_check_test_sample
echo "------------------------"
echo "Running long paths test"
echo "------------------------"
@echo \n
@echo ------------------------
@echo Running long paths test
@echo ------------------------
mkdir tmp\tmp\verylongdirectoryname\evenlongersubdirectoryname
xcopy /E test\include tmp\tmp\verylongdirectoryname\evenlongersubdirectoryname
xcopy /E "test\src file" tmp\tmp\verylongdirectoryname\evenlongersubdirectoryname
Expand All @@ -182,27 +202,29 @@ test_long_paths: build_and_check_test_sample
cd ../../../..

test_relocate_long_paths: test_long_paths
echo "---------------------------------"
echo "Running relocate logn paths test"
echo "---------------------------------"
@echo \n
@echo ---------------------------------
@echo Running relocate logn paths test
@echo ---------------------------------
cd tmp\tmp\verylongdirectoryname\evenlongersubdirectoryname
-@ if NOT EXIST "relocate.exe" mklink relocate.exe cl.exe
cd ..
mkdir tmp_bin
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
.\tester.exe
cd ../../../..

test_exe_with_exports:
echo ------------------------------
echo Running exe with exports test
echo ------------------------------
@echo \n
@echo ------------------------------
@echo Running exe with exports test
@echo ------------------------------
mkdir tmp\test\exe_with_exports
xcopy /E test\include tmp\test\exe_with_exports
xcopy /E "test\src file" tmp\test\exe_with_exports
Expand All @@ -223,6 +245,10 @@ test_exe_with_exports:
cd ../../..

test_def_file_name_override:
@echo
@echo ------------------------------------
@echo Running Def file name override test
@echo ------------------------------------
mkdir tmp\test\def\def_override
xcopy /E test\include tmp\test\def\def_override
xcopy /E "test\src file" tmp\test\def\def_override
Expand All @@ -241,7 +267,7 @@ test_def_file_name_override:
test_and_cleanup: test clean-test


test: test_wrapper test_relocate_exe test_relocate_dll test_def_file_name_override test_exe_with_exports test_long_paths test_pipe_overflow
test: test_wrapper test_relocate_exe test_relocate_dll test_def_file_name_override test_exe_with_exports test_long_paths test_pipe_out_overflow test_pipe_error_overflow


clean : clean-test clean-cl
Expand Down
39 changes: 37 additions & 2 deletions src/coff_parser.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ CoffParser::CoffParser(CoffReaderWriter* coff_reader)
*/
bool CoffParser::Parse() {
if (!this->coffStream_->Open()) {
std::cerr << "Unable to open coff file for reading: "
<< reportLastError() << "\n";
std::cerr << "Unable to open coff file: "
<< this->coffStream_->get_file()
<< " for reading: " << reportLastError() << "\n";
return false;
}
int const invalid_valid_sig =
Expand Down Expand Up @@ -578,6 +579,40 @@ void CoffParser::ReportLongName(const char* data) {
std::cout << "DLL: " << data << "\n";
}

std::string CoffParser::GetLongName() const {
// TODO(johnwparent): I think we can access the
// 2nd index of the members vec to get the long
// name
for (auto mem : this->coff_.members) {
if (mem.member->is_longname) {
return std::string(mem.member->data);
}
}
return std::string();
}

std::string CoffParser::GetShortName() const {
for (auto mem : this->coff_.members) {
if (mem.header->Name[0] != '/') {
int i = 0;
while (mem.header->Name[i] != '/') {
++i;
}
return std::string(reinterpret_cast<const char*>(mem.header->Name),
i);
}
}
return std::string();
}

std::string CoffParser::GetName() const {
std::string maybe_name = this->GetLongName();
if (maybe_name.empty()) {
maybe_name = this->GetShortName();
}
return maybe_name;
}

void CoffParser::Report() {
for (auto mem : this->coff_.members) {
if (mem.member->is_longname) {
Expand Down
3 changes: 3 additions & 0 deletions src/coff_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ class CoffParser {
bool NormalizeName(std::string& name);
void Report();
int Verify();
std::string GetLongName() const;
std::string GetShortName() const;
std::string GetName() const;
static int Validate(std::string& coff);
};

Expand Down
22 changes: 19 additions & 3 deletions src/coff_reader_writer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,39 @@

#include "coff_reader_writer.h"
#include "coff.h"
#include "utils.h"

#include <winnt.h>
#include <cstdlib>
#include <cstring>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <stdexcept>
#include <string>
#include <system_error>
#include <utility>

CoffReaderWriter::CoffReaderWriter(std::string const& file)
: file_(std::move(file)) {}

bool CoffReaderWriter::Open() {
this->pe_stream_.open(this->file_,
std::ios::in | std::ios::out | std::ios::binary);
return this->pe_stream_.is_open();
std::wstring coff_file;
try {
coff_file = ConvertASCIIToWide(this->file_);
} catch (std::overflow_error& e) {
return false;
}
try {
ScopedFileAccess const obtain_write(coff_file, GENERIC_ALL);
this->pe_stream_.open(this->file_,
std::ios::in | std::ios::out | std::ios::binary);
return this->pe_stream_.is_open();
} catch (std::system_error& e) {
std::cerr << "Could not obtain write access: " << e.what()
<< " (Error Code: " << e.code().value() << ")" << '\n';
return false;
}
}

bool CoffReaderWriter::Close() {
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
Loading
Loading