# frozen_string_literal: true require 'pathname' require 'tmpdir' module Metasploit module Framework module Profiler class << self def start return unless record_global_cpu? || record_global_memory? raise 'Cannot profile memory and cpu at the same time' if record_global_cpu? && record_global_memory? if record_global_cpu? require 'ruby-prof' results_path = tmp_cpu_results_path profile = RubyProf::Profile.new profile.start at_exit do result = profile.stop save_cpu_result(result, path: results_path) end end if record_global_memory? require 'memory_profiler' results_path = tmp_memory_results_path profile = MemoryProfiler profile.start at_exit do puts "Generating memory dump #{results_path}" result = profile.stop save_memory_result(result, path: results_path) end end end def record_cpu require 'ruby-prof' results_path = tmp_cpu_results_path profile = RubyProf::Profile.new profile.start yield result = profile.stop save_cpu_result(result, path: results_path) end def record_memory raise 'Cannot mix global memory recording and localised memory recording' if record_global_memory? require 'memory_profiler' results_path = tmp_memory_results_path profile = MemoryProfiler profile.start yield result = profile.stop save_memory_result(result, path: results_path) end private def record_global_cpu? ENV['METASPLOIT_CPU_PROFILE'] end def record_global_memory? ENV['METASPLOIT_MEMORY_PROFILE'] end def tmp_path_for(name:) tmp_directory = Dir.mktmpdir("msf-profile-#{Time.now.strftime('%Y%m%d%H%M%S')}") Pathname.new(tmp_directory).join(name) end def tmp_cpu_results_path path = tmp_path_for(name: 'cpu') ::FileUtils.mkdir_p(path) path end def tmp_memory_results_path tmp_path_for(name: 'memory') end def save_cpu_result(result, path:) require 'rex/compat' puts "Generating CPU dump #{path}" printer = RubyProf::MultiPrinter.new(result, %i[flat graph_html tree stack]) printer.print(path: path) Rex::Compat.open_file(path) end def save_memory_result(result, path:) require 'rex/compat' result.pretty_print(to_file: path) Rex::Compat.open_file(path) end end end end end