#!/usr/bin/python3 ################################################################################ # Small python script to retrieve DLL dependencies with objdump ################################################################################ ################################################################################ # Usage example # # python3 2_bundle-gimp-uni_dep.py /path/to/run.exe /winenv/ /path/install # # In this case, the DLL dependencies for executable run.exe will be extracted # and copied into /path/install/bin folder. To copy the DLL, the root path to # Windows environnment should be passed, here /winenv/. import argparse import os import subprocess import re import shutil import sys import struct ################################################################################ # Global variables # Sets for executable and system DLL dlls = set() sys_dlls = set() # Previously done DLLs in previous runs done_dlls = set() # Common paths bindir = 'bin' ################################################################################ # Functions # Main function def main(binary, srcdirs, destdir, debug, dll_file): global done_dlls try: if dll_file is not None: with open(dll_file, 'r') as f: done_dlls = { line.strip() for line in f if len(line.strip()) != 0 } except FileNotFoundError: pass #sys.stdout.write("{} (INFO): searching for dependencies of {} in {}.\n".format(os.path.basename(__file__), # binary, ', '.join(srcdirs))) find_dependencies(os.path.abspath(binary), srcdirs) if debug in ['debug-only', 'debug-run']: if debug == 'debug-only': print("Running in debug-only mode (no DLL moved) for '{}'".format(binary)) else: print("Running with debug output for '{}'".format(binary)) if len(dlls) > 0: sys.stdout.write("Needed DLLs:\n\t- ") sys.stdout.write("\n\t- ".join(list(dlls))) print() if len(sys_dlls) > 0: sys.stdout.write('System DLLs:\n\t- ') sys.stdout.write("\n\t- ".join(sys_dlls)) print() removed_dlls = sys_dlls & dlls if len(removed_dlls) > 0: sys.stdout.write('Non installed DLLs:\n\t- ') sys.stdout.write("\n\t- ".join(removed_dlls)) print() installed_dlls = dlls - sys_dlls if len(installed_dlls) > 0: sys.stdout.write('Installed DLLs:\n\t- ') sys.stdout.write("\n\t- ".join(installed_dlls)) print() if debug == 'debug-run': copy_dlls(dlls - sys_dlls, srcdirs, destdir) else: copy_dlls(dlls - sys_dlls, srcdirs, destdir) if dll_file is not None: with open(dll_file, 'w') as f: f.write("\n".join(set.union(done_dlls, dlls, sys_dlls))) def find_dependencies(obj, srcdirs): ''' List DLLs of an object file in a recursive way. ''' if obj in set.union(done_dlls, sys_dlls): # Already processed, either in a previous run of the script # (done_dlls) or in this one. return True if not os.path.isabs(obj): for srcdir in srcdirs: abs_dll = os.path.join(srcdir, bindir, obj) abs_dll = os.path.abspath(abs_dll) if find_dependencies(abs_dll, srcdirs): return True else: # Found in none of the srcdirs: consider it a system DLL sys_dlls.add(os.path.basename(obj)) return False elif os.path.exists(obj): # If DLL exists, extract dependencies. objdump = None try: with open(obj, 'rb') as f: f.seek(0x3C) pe_offset = struct.unpack('