Files
2025-09-29 00:52:08 +02:00

148 lines
4.2 KiB
Ruby
Executable File

#
# File:: dumpbin.rb
# Description:: Analyses COFF format executable
# If the text segment is > 32MB it will error.
# Author:: Derek Ward <derek.ward@rockstarnorth.com>
# 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