From 3806830e72229d9585c2a38460cd965b03e42512 Mon Sep 17 00:00:00 2001 From: zawz Date: Thu, 16 Feb 2023 16:58:47 +0100 Subject: [PATCH] feat: initial profiling feature --- include/profiling.hpp | 8 ++++++++ run-tests.sh | 2 ++ shellcode/profile.sh | 7 +++++++ src/main.cpp | 10 ++++++++-- src/options.cpp | 1 + src/profiling.cpp | 27 +++++++++++++++++++++++++++ src/shellcode.cpp | 4 ++-- test/a.bash | 2 ++ 8 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 include/profiling.hpp create mode 100644 shellcode/profile.sh create mode 100644 src/profiling.cpp diff --git a/include/profiling.hpp b/include/profiling.hpp new file mode 100644 index 0000000..8b346cc --- /dev/null +++ b/include/profiling.hpp @@ -0,0 +1,8 @@ +#ifndef PROFILING_HPP +#define PROFILING_HPP + +#include "struc.hpp" + +void insert_profiling(_obj* o); + +#endif //PROFILING_HPP diff --git a/run-tests.sh b/run-tests.sh index ba92f72..da89c8d 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -1,5 +1,7 @@ #!/bin/bash +DEBUG= + bin=${1-./lxsh} echo_red() diff --git a/shellcode/profile.sh b/shellcode/profile.sh new file mode 100644 index 0000000..49e2ead --- /dev/null +++ b/shellcode/profile.sh @@ -0,0 +1,7 @@ +{ + > lxshprofile.dat + _lxsh_profile() { + export TIMEFORMAT="%R;%U;%S;$(printf "%s" "$*" | tr '%\n' '_')" + { time "$@" 2>/dev/null; } 2>> lxshprofile.dat + } +} diff --git a/src/main.cpp b/src/main.cpp index 324b743..98e7573 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,6 +19,7 @@ #include "debashify.hpp" #include "exec.hpp" #include "shellcode.hpp" +#include "profiling.hpp" #include "errcodes.h" @@ -101,7 +102,7 @@ int main(int argc, char* argv[]) binshebang = basename(shebang); shebang = "#!/usr/bin/env lxsh"; } - else if(options["bash"]) + else if(options["bash"] || options['p']) { parse_bash=true; shebang = "#!/usr/bin/env bash"; @@ -199,8 +200,13 @@ int main(int argc, char* argv[]) if(options["debashify"]) concat_sets(req_fcts, debashify(sh) ); - add_lxsh_fcts(sh, req_fcts); + if(options['p']) { + req_fcts.insert("_lxsh_profile"); + insert_profiling(sh); + sh->shebang = "#!/usr/bin/env bash"; + } + add_lxsh_fcts(sh, req_fcts); // processing before output // minify strmap_t varmap, fctmap; diff --git a/src/options.cpp b/src/options.cpp index 328399a..8d837c2 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -38,6 +38,7 @@ ztd::option_set options( { ztd::option("debashify", false, "Attempt to turn a bash-specific script into a POSIX shell script"), ztd::option("remove-unused", false, "Remove unused functions and variables"), ztd::option("list-cmd", false, "List all commands invoked in the script"), + ztd::option('p', "profiling", false, "Insert profiling function"), ztd::option("\r [Variable processing]"), ztd::option("exclude-var", true, "List of matching regex to ignore for variable processing, separated by spaces", "list"), ztd::option("no-exclude-reserved",false, "Don't exclude reserved variables"), diff --git a/src/profiling.cpp b/src/profiling.cpp new file mode 100644 index 0000000..f620384 --- /dev/null +++ b/src/profiling.cpp @@ -0,0 +1,27 @@ +#include "profiling.hpp" + +#include "struc.hpp" +#include "struc_helper.hpp" +#include "util.hpp" +#include "recursive.hpp" + +bool r_insert_profiling(_obj* o) { + switch(o->type) + { + case _obj::block_cmd: { + cmd_t* c = dynamic_cast(o); + if( ! c->is_cmdvar && !c->is_argvar() && + !is_in_vector( c->arg_string(0), std::vector({ "set", "shift", "echo", "printf", "[" }) ) && + c->args != nullptr + ) { + c->args->insert(0, make_arg("_lxsh_profile") ); + } + }; + default: break; + } + return true; +} + +void insert_profiling(_obj* o) { + recurse(r_insert_profiling, o); +} diff --git a/src/shellcode.cpp b/src/shellcode.cpp index d485fc0..5ef8e8c 100644 --- a/src/shellcode.cpp +++ b/src/shellcode.cpp @@ -7,8 +7,8 @@ const std::map lxsh_extend_fcts = { { "_lxsh_random", { "[K]", "Generate a random number between 0 and 2^(K*8). Default 2", RANDOM_SH} }, { "_lxsh_random_string", { "[N]", "Generate a random alphanumeric string of length N. Default 20", RANDOM_STRING_SH} }, - { "_lxsh_random_tmpfile", { "[PREFIX] [N]", "Get a random TMP filepath, with N random chars. Default 20", RANDOM_TMPFILE_SH, {"_lxsh_random_string"} } - } + { "_lxsh_random_tmpfile", { "[PREFIX] [N]", "Get a random TMP filepath, with N random chars. Default 20", RANDOM_TMPFILE_SH, {"_lxsh_random_string"} } }, + { "_lxsh_profile", { "COMMAND...", "Generate profiling data for command", PROFILE_SH } } }; const std::map lxsh_array_fcts = { diff --git a/test/a.bash b/test/a.bash index 497e16c..17d32f1 100644 --- a/test/a.bash +++ b/test/a.bash @@ -45,3 +45,5 @@ a=a for I in A B C ; do echo "$I" done > >(cat) + +{ time { true ; } ; } 2>&1