// MIT License // // Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MUTNAMELEN 1024 #define FUNCNAMELEN 32 * 1024 #define NO_ERROR -1 #define TIMEMORY_BIN_DIR "bin" #if !defined(PATH_MAX) # define PATH_MAX std::numeric_limits::max(); #endif struct function_signature; struct module_function; template using bpvector_t = BPatch_Vector; using string_t = std::string; using string_view_t = std::string_view; using stringstream_t = std::stringstream; using strvec_t = std::vector; using strset_t = std::set; using regexvec_t = std::vector; using fmodset_t = std::set; using fixed_modset_t = std::map; using exec_callback_t = BPatchExecCallback; using exit_callback_t = BPatchExitCallback; using fork_callback_t = BPatchForkCallback; using patch_t = BPatch; using process_t = BPatch_process; using thread_t = BPatch_thread; using binary_edit_t = BPatch_binaryEdit; using image_t = BPatch_image; using module_t = BPatch_module; using procedure_t = BPatch_function; using snippet_t = BPatch_snippet; using call_expr_t = BPatch_funcCallExpr; using address_space_t = BPatch_addressSpace; using flow_graph_t = BPatch_flowGraph; using basic_block_t = BPatch_basicBlock; using basic_loop_t = BPatch_basicBlockLoop; using procedure_loc_t = BPatch_procedureLocation; using point_t = BPatch_point; using local_var_t = BPatch_localVar; using const_expr_t = BPatch_constExpr; using error_level_t = BPatchErrorLevel; using patch_pointer_t = std::shared_ptr; using snippet_pointer_t = std::shared_ptr; using call_expr_pointer_t = std::shared_ptr; using snippet_vec_t = bpvector_t; using procedure_vec_t = bpvector_t; using basic_block_set_t = std::set; using basic_loop_vec_t = bpvector_t; using snippet_pointer_vec_t = std::vector; using instruction_t = Dyninst::InstructionAPI::Instruction; void omnitrace_prefork_callback(thread_t* parent, thread_t* child); //======================================================================================// // // Global Variables // //======================================================================================// // // label settings // extern bool use_return_info; extern bool use_args_info; extern bool use_file_info; extern bool use_line_info; // // heuristic settings // extern bool allow_overlapping; extern bool loop_level_instr; extern bool instr_dynamic_callsites; extern bool instr_traps; extern bool instr_loop_traps; extern size_t min_address_range; extern size_t min_loop_address_range; extern size_t min_instructions; // // debug settings // extern bool werror; extern bool debug_print; extern bool instr_print; extern int verbose_level; // // string settings // extern string_t main_fname; extern string_t argv0; extern string_t cmdv0; extern string_t default_components; extern string_t prefer_library; // // global variables // extern patch_pointer_t bpatch; extern call_expr_t* terminate_expr; extern snippet_vec_t init_names; extern snippet_vec_t fini_names; extern fmodset_t available_module_functions; extern fmodset_t instrumented_module_functions; extern fmodset_t overlapping_module_functions; extern fmodset_t excluded_module_functions; extern fixed_modset_t fixed_module_functions; extern regexvec_t func_include; extern regexvec_t func_exclude; extern regexvec_t file_include; extern regexvec_t file_exclude; extern regexvec_t file_restrict; extern regexvec_t func_restrict; // //======================================================================================// // control debug printf statements #define errprintf(LEVEL, ...) \ { \ if(werror || LEVEL < 0) \ { \ if(debug_print || verbose_level >= LEVEL) \ fprintf(stderr, "[omnitrace][exe] Error! " __VA_ARGS__); \ char _buff[FUNCNAMELEN]; \ sprintf(_buff, "[omnitrace][exe] Error! " __VA_ARGS__); \ throw std::runtime_error(std::string{ _buff }); \ } \ else \ { \ if(debug_print || verbose_level >= LEVEL) \ fprintf(stderr, "[omnitrace][exe] Warning! " __VA_ARGS__); \ } \ fflush(stderr); \ } // control verbose printf statements #define verbprintf(LEVEL, ...) \ { \ if(debug_print || verbose_level >= LEVEL) \ fprintf(stdout, "[omnitrace][exe] " __VA_ARGS__); \ fflush(stdout); \ } #define verbprintf_bare(LEVEL, ...) \ { \ if(debug_print || verbose_level >= LEVEL) fprintf(stdout, __VA_ARGS__); \ fflush(stdout); \ } //======================================================================================// template void consume_parameters(T&&...) {} //======================================================================================// extern "C" { bool are_file_include_exclude_lists_empty(); bool instrument_module(const string_t& file_name); bool instrument_entity(const string_t& function_name); bool module_constraint(string_view_t fname); bool routine_constraint(string_view_t fname); } //======================================================================================// strset_t get_whole_function_names(); function_signature get_func_file_line_info(module_t* mutatee_module, procedure_t* f); function_signature get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t* cfGraph, basic_loop_t* loopToInstrument); std::tuple query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc, flow_graph_t* cfGraph = nullptr, basic_loop_t* loopToInstrument = nullptr); bool query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc, flow_graph_t* cfGraph, basic_loop_t* loopToInstrument, bool allow_traps); template bool insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc, procedure_loc_t traceLoc, flow_graph_t* cfGraph = nullptr, basic_loop_t* loopToInstrument = nullptr, bool allow_traps = true); void errorFunc(error_level_t level, int num, const char** params); procedure_t* find_function(image_t* appImage, const string_t& functionName, const strset_t& = {}); void error_func_real(error_level_t level, int num, const char* const* params); void error_func_fake(error_level_t level, int num, const char* const* params);