From 3f1cf080f23a99359a8a00a7b65399ea76145941 Mon Sep 17 00:00:00 2001 From: Ludwig Lehnert Date: Tue, 4 Mar 2025 19:08:59 +0100 Subject: [PATCH] working buildsystem; still cannot open PE32+ binaries with zipr --- .gitignore | 7 +- SConscript | 36 ------ SConstruct | 33 ------ build/SConscript | 36 ------ build/transforms/SConscript | 23 ---- build/transforms/initialize_stack.exe | Bin 45200 -> 0 bytes container | 6 +- do-build | 145 +++++++++++++++++++++++ programs/compiled/JustOpen.exe | Bin 0 -> 130334 bytes programs/source/JustOpen.c | 22 ++++ set_env_vars | 2 +- transforms/SConscript | 23 ---- transforms/forward_file_open/.libs | 1 + transforms/forward_file_open/driver.cpp | 23 ++++ transforms/forward_file_open/logic.cpp | 17 +++ transforms/forward_file_open/logic.hpp | 19 +++ transforms/initialize_stack.cpp | 147 ----------------------- transforms/initialize_stack.hpp | 61 ---------- transforms/initialize_stack_driver.cpp | 149 ------------------------ 19 files changed, 239 insertions(+), 511 deletions(-) delete mode 100755 SConscript delete mode 100755 SConstruct delete mode 100755 build/SConscript delete mode 100755 build/transforms/SConscript delete mode 100755 build/transforms/initialize_stack.exe create mode 100755 do-build create mode 100644 programs/compiled/JustOpen.exe create mode 100644 programs/source/JustOpen.c delete mode 100755 transforms/SConscript create mode 100755 transforms/forward_file_open/.libs create mode 100755 transforms/forward_file_open/driver.cpp create mode 100755 transforms/forward_file_open/logic.cpp create mode 100755 transforms/forward_file_open/logic.hpp delete mode 100755 transforms/initialize_stack.cpp delete mode 100755 transforms/initialize_stack.hpp delete mode 100755 transforms/initialize_stack_driver.cpp diff --git a/.gitignore b/.gitignore index 0b113c1..d274b9e 100755 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,11 @@ *.o *.so *.a +*.test +build/ plugins_install/ -.sconsign.dblite \ No newline at end of file + +.sconsign.dblite + +peasoup_executable*/ diff --git a/SConscript b/SConscript deleted file mode 100755 index 21dc388..0000000 --- a/SConscript +++ /dev/null @@ -1,36 +0,0 @@ -import os - -# -# import the environment and clone it so we can make changes. -# -Import('env') -irdb_env = env.Clone() - -# -# These settings are recommended, but you can choose what you like -# -# be strict about syntax/warnings -irdb_env.Append(CXXFLAGS=" -Wall -Werror -fmax-errors=2 ") -# link against core and transform libraries -irdb_env.Append(LIBS=Split("irdb-core irdb-transform")) -# be able to include the SDK files -irdb_env.Append(CPPPATH=" $IRDB_SDK/include ") -# this is where the libraries are. -irdb_env.Append(LIBPATH=Split(" $IRDB_LIBS ")) -# this is where to place plugins. -irdb_env.Replace(INSTALL_PATH=os.environ['PWD']+"/plugins_install") - -# -# export the new environment for children sub-conscripts -# -Export('irdb_env') - -# -# include the children sconscript files. -# -libs = irdb_env.SConscript("./transforms/SConscript") - -# -# And we are done -# -Return('libs') diff --git a/SConstruct b/SConstruct deleted file mode 100755 index a4ff8be..0000000 --- a/SConstruct +++ /dev/null @@ -1,33 +0,0 @@ -import os - - -env = Environment() - -pwd = os.getcwd() - - -env.Replace(TRANSFORMS_HOME=os.path.join(pwd, "transforms")) -env.Replace(IRDB_SDK=os.path.join(pwd, "irdb-sdk")) -env.Replace(IRDB_LIBS=os.environ['IRDB_LIBS']) - - -env.Replace(debug=ARGUMENTS.get("debug", 0)) - -env.Append(CXXFLAGS=" -std=c++11 ") -env.Append(LINKFLAGS=" -Wl,-unresolved-symbols=ignore-in-shared-libs ") - - -if int(env['debug']) == 1: - env.Append(CFLAGS=" -g ") - env.Append(CXXFLAGS=" -g ") - env.Append(LINKFLAGS=" -g ") - env.Append(SHLINKFLAGS=" -g ") -else: - env.Append(CFLAGS=" -O ") - env.Append(CXXFLAGS=" -O ") - env.Append(LINKFLAGS=" -O ") - env.Append(SHLINKFLAGS=" -O ") - - -Export('env') -SConscript("SConscript", variant_dir='build') diff --git a/build/SConscript b/build/SConscript deleted file mode 100755 index 21dc388..0000000 --- a/build/SConscript +++ /dev/null @@ -1,36 +0,0 @@ -import os - -# -# import the environment and clone it so we can make changes. -# -Import('env') -irdb_env = env.Clone() - -# -# These settings are recommended, but you can choose what you like -# -# be strict about syntax/warnings -irdb_env.Append(CXXFLAGS=" -Wall -Werror -fmax-errors=2 ") -# link against core and transform libraries -irdb_env.Append(LIBS=Split("irdb-core irdb-transform")) -# be able to include the SDK files -irdb_env.Append(CPPPATH=" $IRDB_SDK/include ") -# this is where the libraries are. -irdb_env.Append(LIBPATH=Split(" $IRDB_LIBS ")) -# this is where to place plugins. -irdb_env.Replace(INSTALL_PATH=os.environ['PWD']+"/plugins_install") - -# -# export the new environment for children sub-conscripts -# -Export('irdb_env') - -# -# include the children sconscript files. -# -libs = irdb_env.SConscript("./transforms/SConscript") - -# -# And we are done -# -Return('libs') diff --git a/build/transforms/SConscript b/build/transforms/SConscript deleted file mode 100755 index 6ed2177..0000000 --- a/build/transforms/SConscript +++ /dev/null @@ -1,23 +0,0 @@ -# import and create a copy of the environment so we don't change -# anyone else's env. -Import('irdb_env') -myenv = irdb_env.Clone() - -# -# set input files and output program name -# -files = Glob(Dir('.').srcnode().abspath+"/*.cpp") -pgm_name = "initialize_stack.exe" - -# -# build, install and return the program by default. -# -pgm = irdb_env.Program(pgm_name, files) -install = myenv.Install("$INSTALL_PATH/", pgm) -Default(install) - - -# -# and we're done -# -Return('install') diff --git a/build/transforms/initialize_stack.exe b/build/transforms/initialize_stack.exe deleted file mode 100755 index a4e8cb62b065a10d51711fc77a2d2ddeea1d0d30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45200 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 O1_dTu)s_qvRQW%_7AF({ diff --git a/container b/container index 779b732..0de1380 100755 --- a/container +++ b/container @@ -1,3 +1,7 @@ #!/bin/bash -podman run --rm -it -v $(pwd):/work:z -w /work git.zephyr-software.com:4567/opensrc/zipr/zipr-bin iagree +sudo chmod -R 777 transforms/ +podman run --rm -it -v $(pwd):/work:Z -w /work git.zephyr-software.com:4567/opensrc/zipr/zipr-bin iagree + +# ./do-build +# pszr programs/compiled/JustOpen.exe JustOpen.test diff --git a/do-build b/do-build new file mode 100755 index 0000000..92d659c --- /dev/null +++ b/do-build @@ -0,0 +1,145 @@ +#!/bin/env python3 + +import os +import hashlib +import base64 +import argparse + +DIR = os.path.dirname(os.path.realpath(__file__)) + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument('--force', action='store_true') + return parser.parse_args() + + +args = parse_args() + + +CXX = "g++" +LDFLAGS = "-Wl,-unresolved-symbols=ignore-in-shared-libs -L/opt/ps_zipr/irdb-libs/lib" +CXXFLAGS = f"-g -I{DIR}/irdb-sdk/include -std=c++11 -Wall -Werror -fmax-errors=2 -fPIC" + + +def list_hash(list: list[str]): + md5 = hashlib.md5() + for item in list: + md5.update(item.encode()) + + return md5.hexdigest() + + +def file_hash(file: str): + BUFSIZE = 65536 + + md5 = hashlib.md5() + + with open(file, 'rb') as f: + data = f.read(BUFSIZE) + while data: + md5.update(data) + data = f.read(BUFSIZE) + + return md5.hexdigest() + + +def needs_rebuild(file: str, libs: list[str] = []) -> bool: + return True + global args + + hash = file_hash(file) + hash += list_hash(libs) + + abspath = os.path.abspath(file) + b64path = os.path.join('/tmp', base64.b64encode(abspath.encode()).decode()) + + if not os.path.exists(b64path) or args.force: + return True + + with open(b64path, 'r') as f: + return f.read() != hash + + +def signal_built(file: str, libs: list[str] = []) -> bool: + return + hash = file_hash(file) + hash += list_hash(libs) + + abspath = os.path.abspath(file) + b64path = os.path.join('/tmp', base64.b64encode(abspath.encode()).decode()) + + with open(b64path, 'w') as f: + f.write(hash) + + +def build(targetObject: str, cppFile: str): + if not needs_rebuild(cppFile): + return + + global CXXFLAGS + + cmd = f'{CXX} -c "{cppFile}" -o "{targetObject}" {CXXFLAGS}' + print(cmd) + status = os.system(cmd) + + if status == 0: + signal_built(cppFile) + return True + + return False + + +def link(target: str, objects: list[str], libs: list[str]): + global LDFLAGS + + cmd = f'{CXX} -shared -o {target}' + for object in objects: + cmd += f' {object}' + for lib in libs: + cmd += f' -l{lib}' + cmd += f' {LDFLAGS}' + + print(cmd) + return os.system(cmd) == 0 + + +def main(): + for dir in os.listdir(f'{DIR}/transforms'): + path = os.path.join(f'{DIR}/transforms', dir) + if not os.path.isdir(path): + continue + + libs: list[str] = [] + if os.path.exists(os.path.join(path, '.libs')): + with open(os.path.join(path, '.libs'), 'r') as f: + libs = f.read().split() + + libs = filter(lambda l: len(l.strip()) > 0, libs) + libs = list(libs) + + hadError = False + objects: list[str] = [] + for file in os.listdir(path): + if not file.endswith('.cpp'): + continue + + filePath = os.path.join(path, file) + + objectPath = os.path.splitext(filePath)[0] + '.o' + newError = not build(objectPath, filePath) + hadError = hadError or newError + objects += [objectPath] + + if hadError: + continue + + targetDir = os.path.join(DIR, 'plugins_install') + os.makedirs(targetDir, exist_ok=True) + + target = os.path.join(targetDir, f'lib{dir}.so') + link(target, objects, libs) + + +if __name__ == '__main__': + main() diff --git a/programs/compiled/JustOpen.exe b/programs/compiled/JustOpen.exe new file mode 100644 index 0000000000000000000000000000000000000000..4556c0adb7388d3b28f18ce8abcb70450a8b2b95 GIT binary patch literal 130334 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 I>?!j90$skm<^TWy literal 0 HcmV?d00001 diff --git a/programs/source/JustOpen.c b/programs/source/JustOpen.c new file mode 100644 index 0000000..6c74823 --- /dev/null +++ b/programs/source/JustOpen.c @@ -0,0 +1,22 @@ +#include +#include +#include + +int main() { + char file[MAX_PATH] = {0}; + + OPENFILENAME ofn = { + .lStructSize = sizeof(ofn), + .lpstrFilter = "All Files\0*.*\0", + .lpstrFile = file, + .nMaxFile = MAX_PATH, + .lpstrTitle = "Select File", + .Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST + }; + + int res = GetOpenFileName(&ofn); + + if (res) printf("%s\n", file); + + return res != 0; +} diff --git a/set_env_vars b/set_env_vars index 636f5f2..be1f27c 100755 --- a/set_env_vars +++ b/set_env_vars @@ -1 +1 @@ -export PSPATH=$PSPATH:$TRANSFORMS_HOME/plugins_install +export PSPATH=$PSPATH:$(pwd)/plugins_install diff --git a/transforms/SConscript b/transforms/SConscript deleted file mode 100755 index 6ed2177..0000000 --- a/transforms/SConscript +++ /dev/null @@ -1,23 +0,0 @@ -# import and create a copy of the environment so we don't change -# anyone else's env. -Import('irdb_env') -myenv = irdb_env.Clone() - -# -# set input files and output program name -# -files = Glob(Dir('.').srcnode().abspath+"/*.cpp") -pgm_name = "initialize_stack.exe" - -# -# build, install and return the program by default. -# -pgm = irdb_env.Program(pgm_name, files) -install = myenv.Install("$INSTALL_PATH/", pgm) -Default(install) - - -# -# and we're done -# -Return('install') diff --git a/transforms/forward_file_open/.libs b/transforms/forward_file_open/.libs new file mode 100755 index 0000000..98daea4 --- /dev/null +++ b/transforms/forward_file_open/.libs @@ -0,0 +1 @@ +irdb-core irdb-transform diff --git a/transforms/forward_file_open/driver.cpp b/transforms/forward_file_open/driver.cpp new file mode 100755 index 0000000..db1e030 --- /dev/null +++ b/transforms/forward_file_open/driver.cpp @@ -0,0 +1,23 @@ +#include "irdb-core" +#include "logic.hpp" +#include +#include + +class ForwardFileOpenDriver : public TransformStep_t { +public: + int parseArgs(const vector args) override { return 0; } + + int executeStep() override { + auto firp = getMainFileIR(); + auto success = ForwardFileOpen(firp).execute(); + return success ? 0 : 2; + } + + string getStepName() const override { return "forward_file_open"; } + +private: +}; + +extern "C" shared_ptr getTransformStep(void) { + return shared_ptr(new ForwardFileOpenDriver()); +} diff --git a/transforms/forward_file_open/logic.cpp b/transforms/forward_file_open/logic.cpp new file mode 100755 index 0000000..430f2a0 --- /dev/null +++ b/transforms/forward_file_open/logic.cpp @@ -0,0 +1,17 @@ +#include "logic.hpp" +#include "irdb-transform" + +ForwardFileOpen::ForwardFileOpen(FileIR_t *p_variantIR) + : Transform_t(p_variantIR) {} + +bool ForwardFileOpen::execute() { + const auto insts = getFileIR()->getInstructions(); + + cout << "Hello World!" << std::endl; + + for (auto &inst : insts) { + cout << inst->getDisassembly() << std::endl; + } + + return true; +} \ No newline at end of file diff --git a/transforms/forward_file_open/logic.hpp b/transforms/forward_file_open/logic.hpp new file mode 100755 index 0000000..101b50e --- /dev/null +++ b/transforms/forward_file_open/logic.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include + +#include +#include + +using namespace std; +using namespace IRDB_SDK; + +class ForwardFileOpen : protected Transform_t { +public: + ForwardFileOpen(FileIR_t *p_variantIR); + bool execute(); + +private: +}; diff --git a/transforms/initialize_stack.cpp b/transforms/initialize_stack.cpp deleted file mode 100755 index 34da995..0000000 --- a/transforms/initialize_stack.cpp +++ /dev/null @@ -1,147 +0,0 @@ -#include "initialize_stack.hpp" -#include -#include -#include - -#define ALLOF(a) begin(a), end(a) - -using namespace std; -using namespace IRDB_SDK; -using namespace InitStack; - -// -// constructor -// -InitStack_t::InitStack_t(FileIR_t *p_variantIR, - const string &p_functions_filename, int p_init_value, - bool p_verbose) - : Transform_t(p_variantIR), // initialize the Transform class so things like - // insertAssembly and getFileIR() can be used - m_init_value(p_init_value), // member variable inits, these will vary - // depending on your transform's objectives - m_verbose(p_verbose), m_num_transformed(0) { - // check whether to read in a list of functions to transform - if (p_functions_filename == "") { - cout << "Auto-initialize all functions" << endl; - m_funcs_to_init = - getFileIR()->getFunctions(); // use all functions from the IR - } else { - cout << "Auto-initialize functions specified in: " << p_functions_filename - << endl; - readFunctionsFromFile(p_functions_filename); // read functions from file - } -} - -// -// read list of functions to auto-initialize -// -// post conditions: set of functions to auto-initialize -// -void InitStack_t::readFunctionsFromFile(const string &p_filename) { - // get all functions for readability of the rest of the code - const auto &all_funcs = getFileIR()->getFunctions(); - - // open input file and check for successful open - ifstream functionsFile( - p_filename); // can't use auto decl here because of lack of copy - // constructor in ifstream class - if (!functionsFile.is_open()) - throw runtime_error("Cannot open " + p_filename); - - // read each line of the input file. - auto line = string(); - while (functionsFile >> line) { - // locate a function with the name read from the file. - const auto func_it = find_if(ALLOF(all_funcs), [&](const Function_t *f) { - return f->getName() == line; - }); - - // if found, log and insert it into the set to transform - if (func_it != end(all_funcs)) { - auto f = *func_it; - cout << "Adding " << f->getName() << " to function list" << endl; - m_funcs_to_init.insert(f); - } - } -} - -// -// Execute the transform by transforming all to-transform functions -// -// preconditions: the FileIR is read as from the IRDB. valid file listing -// functions to auto-initialize postcondition: instructions added to -// auto-initialize stack for each specified function -// -// -bool InitStack_t::execute() { - // transform all functions - for (auto f : m_funcs_to_init) - initStack(f); - - // #ATTRIBUTE is a convention used to help find useful information in log - // files - cout << "#ATTRIBUTE InitStack::num_transformed=" << m_num_transformed << endl; - - return m_num_transformed > 0; // true means success -} - -// -// preconditions : f is not NULL -// postconditions: stack auto-initialized if stack frame size > 0 -// -void InitStack_t::initStack(Function_t *f) { - // preconditions - assert(f != nullptr); - - // check that the frame size is in the area we care about - const auto frame_size = f->getStackFrameSize(); - - // nothing to init. - if (frame_size == 0) - return; - - const auto num_locs = static_cast(ceil(frame_size / 4.0)); - - // debug output - cout << "Function: " << f->getName() - << " frame size: " << f->getStackFrameSize() << endl; - - // not all functions have an entry point - const auto entry = f->getEntryPoint(); - if (!entry) - return; - - // log what we are doing - cout << "Function: " << f->getName() << " auto-initialize " << dec << num_locs - << " stack memory locations (4 bytes at a time) with value = " << hex - << m_init_value << endl; - - // determine the registers to use on x86-32 or x86-64 - const auto sp_reg = - getFileIR()->getArchitectureBitWidth() == 64 ? "rsp" : "esp"; - const auto scratch_reg = - getFileIR()->getArchitectureBitWidth() == 64 ? "r11" : "ecx"; - - // Now, do the dirty work of inserting new assembly to initialize the stack. - // Insert these instructions at the start of the function (to initialize the - // stack frame before the function runs) Assume: flags are dead at function - // entry. Future work: Verify this is true using dead register list. Note: we - // spill a scratch register into the red zone at 120 bytes passed the end of - // the frame - - const auto newInsns = insertAssemblyInstructionsBefore( - entry, - string() + " mov [%%1 + %%2], %%3\n" - " mov %%3, -%%4\n" - "L1: mov dword [%%1 + %%3 * 4 - 4], %%5\n" - " inc %%3\n" - " jnz 0\n" - " mov %%3, [%%1 + %%2]\n", - {sp_reg, to_string(-f->getStackFrameSize() - 120), scratch_reg, - to_string(num_locs), to_string(m_init_value)}); - - newInsns[4]->setTarget(newInsns[2]); // Link jnz to L1. - - // bump stats - m_num_transformed++; -} diff --git a/transforms/initialize_stack.hpp b/transforms/initialize_stack.hpp deleted file mode 100755 index 03f0628..0000000 --- a/transforms/initialize_stack.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include -#include - -// -// Put the transform in its own namespace -// just to keep the header files easy to read. -// This is not an IRDB transform requirement, just good coding practice. -// -namespace InitStack { -using namespace std; -using namespace IRDB_SDK; - -// -// This class handles initializing stack frames to a constant value -// -// Note: Using private inheritence here for "principle of minimum access", -// but you can choose what's best for your needs. -// -class InitStack_t : private Transform_t { -public: - // construct an object - InitStack_t( - FileIR_t *p_variantIR, // the FileIR object to transform - const string &p_function_filename, // the name of a file with functions to - // transform. "" -> no file and - // transform all functions - int init_value = 0, // the value to write when initializing the stack - bool p_verbose = false // use verbose logging? - ); - - // execute the transform - // input: m_funcs_to_init the set of functions to transform, the fileIR to - // transform output: the transformed fileIR, with extra instructions to init - // stack frames return value: true -> success, false -> fail - bool execute(); - -private: - // methods - - // read in the given file full of function names to transform (called from - // constructor) input: the filename and FileIR to transform output: - // m_funcs_to_init with the functions listed in the file - void readFunctionsFromFile(const string &p_filename); - - // initialize the stack for a given function - // input: the fileIR to transform - // output: the transformed fileIR - void initStack(Function_t *f); - - // data - set m_funcs_to_init; // the functions whose stacks this object - // should initialize - int m_init_value; // the value with which to init the stack. - bool m_verbose; // do verbose logging - int m_num_transformed; // stats about how many functions that this object has - // transformed -}; - -} // namespace InitStack diff --git a/transforms/initialize_stack_driver.cpp b/transforms/initialize_stack_driver.cpp deleted file mode 100755 index 5cbe0d2..0000000 --- a/transforms/initialize_stack_driver.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include "initialize_stack.hpp" -#include - -using namespace std; -using namespace IRDB_SDK; -using namespace InitStack; - -// -// Print usage info -// -void usage(char *p_name) { - cerr << "Usage: " << p_name << " \n"; - cerr << "\t[--functions | -f ] Read in the functions to " - "auto-initialize " - << endl; - cerr << "\t[--initvalue | -i ] Specify stack " - "initialization value (default=0)" - << endl; - cerr << "\t[--verbose | -v] Verbose mode " - " " - << endl; - cerr << "\t[--help,--usage,-?,-h] Display this message " - " " - << endl; -} - -// -// The entry point for a stand-alone executable transform. -// Note: Thanos-enabled transforms are easier to write, faster to execute, and -// generally preferred. Stand-alone transforms may be useful if the transform -// has issues with memory leaks and/or memory errors. Memory issues in a stand -// alone transform cannot affect correctness of other transforms. -// -int main(int argc, char **argv) { - // - // Sanity check that the command line has at least a variant ID, otherwise we - // won't know what variant to operate on. - // - if (argc < 2) { - usage(argv[0]); - exit(1); - } - - // constant parameters read from argv - const auto program_name = string(argv[0]); - const auto variantID = atoi(argv[1]); - - // initial values of parameters to parse - auto verbose = false; - auto funcs_filename = string(); - auto init_value = 0; - - // declare some options for the transform - const char *short_opts = "f:i:v?h"; - struct option long_options[] = {{"functions", required_argument, 0, 'f'}, - {"initvalue", required_argument, 0, 'i'}, - {"verbose", no_argument, 0, 'v'}, - {"help", no_argument, 0, 'h'}, - {"usage", no_argument, 0, '?'}, - {0, 0, 0, 0}}; - - // parse the options in a standard getopts_long loop - while (true) { - int c = getopt_long(argc, argv, short_opts, long_options, nullptr); - if (c == -1) - break; - switch (c) { - case 'f': - funcs_filename = optarg; - cout << "Reading file with function specifiers: " << funcs_filename - << endl; - break; - case 'i': - init_value = strtoll(optarg, NULL, 0); - cout << " Stack initialization value: " << hex << init_value << endl; - break; - case 'v': - verbose = true; - break; - case '?': - case 'h': - usage(argv[0]); - exit(1); - break; - default: - break; - } - } - - // stand alone transforms must setup the interface to the sql server - auto pqxx_interface = pqxxDB_t::factory(); - BaseObj_t::setInterface(pqxx_interface.get()); - - // stand alone transforms must create and read a variant ID from the database - auto pidp = VariantID_t::factory(variantID); - assert(pidp->isRegistered() == true); - - // stand alone transforms must create and read the main file's IR from the - // datatbase - auto this_file = pidp->getMainFile(); - auto url = this_file->getURL(); - - // declare for later so we can return the right value - auto success = false; - - // now try to load the IR and execute a transform - try { - // Create and download the file's IR. - // Note: this is achieved differently with thanos-enabled plugins - auto firp = FileIR_t::factory(pidp.get(), this_file); - - // sanity - assert(firp && pidp); - - // log - cout << "Transforming " << this_file->getURL() << endl; - - // create and invoke the transform - InitStack_t is(firp.get(), funcs_filename, init_value, verbose); - success = is.execute(); - - // conditionally write the IR back to the database on success - if (success) { - cout << "Writing changes for " << url << endl; - - // Stand alone trnasforms must manually write the IR back to the IRDB and - // commit the transactions - firp->writeToDB(); - - // and commit the the transaction to postgres - pqxx_interface->commit(); - } else { - cout << "Skipping write back on failure. " << url << endl; - } - } catch (const DatabaseError_t &db_error) { - // log any databse errors that might come up in the transform process - cerr << program_name << ": Unexpected database error: " << db_error - << "file url: " << url << endl; - } catch (...) { - // log any other errors - cerr << program_name << ": Unexpected error file url: " << url << endl; - } - - // - // return success code to driver (as a shell-style return value). 0=success, - // 1=warnings, 2=errors - // - return success ? 0 : 2; -}