# # File:: dumpbin.rb # Description:: Analyses COFF format executable # If the text segment is > 32MB it will error. # Author:: Derek Ward # Date:: 25th May 2012 # #----------------------------------------------------------------------------- # Uses / Requires #----------------------------------------------------------------------------- require 'pipeline/config/projects' require 'pipeline/os/getopt' include Pipeline require 'systemu' require 'fileutils' require 'dl' #----------------------------------------------------------------------------- # Constants #----------------------------------------------------------------------------- OPTIONS = [ [ "--help", "-h", OS::Getopt::BOOLEAN, "display usage information." ], [ "--section", "-s", OS::Getopt::OPTIONAL, "section name in executable." ], [ "--max_size", "-m", OS::Getopt::OPTIONAL, "max size of section" ], ] TRAILING_DESC = 'dumpbin command to run' DEFAULT_SIZE = (32*1024*1024) DEFAULT_SECTION = ".text" # Message box constants BUTTONS_OK = 0 BUTTONS_OKCANCEL = 1 BUTTONS_ABORTRETRYIGNORE = 2 BUTTONS_YESNO = 4 CLICKED_OK = 1 CLICKED_CANCEL = 2 CLICKED_ABORT = 3 CLICKED_RETRY = 4 CLICKED_IGNORE = 5 CLICKED_YES = 6 CLICKED_NO = 7 ICON_HAND = 16 ICON_QUESTION = 32 ICON_EXCLAMATION = 48 ICON_ASTERISK = 64 #----------------------------------------------------------------------------- # Monkey Patch string class #----------------------------------------------------------------------------- class String def convert_base(from, to) self.to_i(from).to_s(to) end end #----------------------------------------------------------------------------- # Message Box #----------------------------------------------------------------------------- def message_box(txt='', title='', buttons=0, icon=0) user32 = DL.dlopen('user32') msgbox = user32['MessageBoxA', 'ILSSI'] r, rs = msgbox.call(0, txt, title, buttons+icon) return r end #----------------------------------------------------------------------------- # Application entry point #----------------------------------------------------------------------------- if __FILE__ == $0 error_count = 0 begin g_AppName = File::basename( __FILE__, '.rb' ) g_ProjectName = '' g_BranchName = '' g_Project = nil #--------------------------------------------------------------------- # Parse Command Line. #--------------------------------------------------------------------- opts, trailing = OS::Getopt.getopts( OPTIONS ) if ( opts['help'] ) puts OS::Getopt.usage( OPTIONS ) puts ("Press Enter to continue...") $stdin.getc( ) Process.exit! 1 end if ( ( 0 == trailing.size ) ) then $stderr.puts 'No trailing file arguments specified. Exiting.' puts OS::Getopt.usage( OPTIONS, { 'files' => TRAILING_DESC } ) Process.exit( 2 ) end max_size = ( nil == opts['max_size'] ) ? DEFAULT_SIZE : opts['max_size'] section = ( nil == opts['section'] ) ? DEFAULT_SECTION : opts['section'] puts "Running #{trailing[0]}" status, stdout, stderr = systemu( trailing[0] ) #puts "returned #{status.exitstatus}" if ( status.exited? and ( 0 == status.exitstatus ) ) stdout.each do |line| #puts line regexp = Regexp.new("\\s*(\\S+)\\s+\\" + section) if ( line =~ regexp ) size = $1.convert_base(16,10).to_i puts ("Code size is #{size/1024}K") if (size >= max_size) error_str = "ERROR : .text segment is too big #{size} ( Max Size = #{max_size} ) \n*** DO NOT RUN THIS CODE IT CAN LEAD TO UNPREDICTABLE BEHAVIOUR ***" $stderr.puts error_str $stderr.puts stdout message_box( error_str, "POST BUILD ERROR", BUTTONS_OK, ICON_EXCLAMATION) Process.exit!(-1) end end end Process.exit!(0) else puts stdout.to_s Process.exit!(-1) end rescue Exception => ex $stderr.puts "Unhandled exception: #{ex.message}" $stderr.puts "Backtrace:" ex.backtrace.each { |m| $stderr.puts "\t#{m}" } Process.exit -1 end ret_code = ( error_count > 0 ) ? -1 : 0 Process.exit! ret_code end #if __FILE__ == $0