2023-06-30 14:34:39 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
import difflib
|
|
|
|
import subprocess
|
|
|
|
import os
|
|
|
|
|
2023-12-16 05:59:17 -05:00
|
|
|
from isledecomp.lib import lib_path_join
|
2023-11-25 13:27:42 -05:00
|
|
|
from isledecomp.utils import print_diff
|
|
|
|
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
allow_abbrev=False,
|
|
|
|
description="Verify Exports: Compare the exports of two DLLs.",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"original", metavar="original-binary", help="The original binary"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"recompiled", metavar="recompiled-binary", help="The recompiled binary"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--no-color", "-n", action="store_true", help="Do not color the output"
|
|
|
|
)
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
args = parser.parse_args()
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
if not os.path.isfile(args.original):
|
|
|
|
parser.error(f"Original binary file {args.original} does not exist")
|
2023-11-25 13:27:42 -05:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
if not os.path.isfile(args.recompiled):
|
|
|
|
parser.error(f"Recompiled binary {args.recompiled} does not exist")
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
def get_exports(file):
|
2023-12-16 05:59:17 -05:00
|
|
|
call = [lib_path_join("DUMPBIN.EXE"), "/EXPORTS"]
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
if os.name != "nt":
|
|
|
|
call.insert(0, "wine")
|
|
|
|
file = (
|
|
|
|
subprocess.check_output(["winepath", "-w", file])
|
|
|
|
.decode("utf-8")
|
|
|
|
.strip()
|
|
|
|
)
|
2023-11-25 13:27:42 -05:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
call.append(file)
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
raw = subprocess.check_output(call).decode("utf-8").split("\r\n")
|
|
|
|
exports = []
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
start = False
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
for line in raw:
|
|
|
|
if not start:
|
|
|
|
if line == " ordinal hint name":
|
|
|
|
start = True
|
|
|
|
else:
|
|
|
|
if line:
|
|
|
|
exports.append(line[27 : line.rindex(" (")])
|
|
|
|
elif exports:
|
|
|
|
break
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
return exports
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
og_exp = get_exports(args.original)
|
|
|
|
re_exp = get_exports(args.recompiled)
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
udiff = difflib.unified_diff(og_exp, re_exp)
|
|
|
|
has_diff = print_diff(udiff, args.no_color)
|
2023-06-30 14:34:39 -04:00
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
return 1 if has_diff else 0
|
2023-06-30 14:34:39 -04:00
|
|
|
|
|
|
|
|
2023-12-08 06:37:44 -05:00
|
|
|
if __name__ == "__main__":
|
|
|
|
raise SystemExit(main())
|