-
-
Save nickalcock/d6400b123b49462e15f6b9a3a5c1cbc7 to your computer and use it in GitHub Desktop.
Hacky script to check for the set_fast_math constructor in an executable/shared library using objdump
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import subprocess | |
import multiprocessing | |
import re | |
import sys | |
def get_init_array(filename): | |
# Call objdump -s -j .init_array <filename> to get the contents of the .init_array section | |
try: | |
objdump_output = subprocess.check_output(['objdump', '-s', '-j', '.init_array', filename], stderr=subprocess.STDOUT) | |
except subprocess.CalledProcessError as e: | |
return [] | |
objdump_output = objdump_output.decode('utf-8') | |
objdump_output = objdump_output.split('\n') | |
found_contents = False | |
constructors = [] | |
for line in objdump_output: | |
if line.startswith("Contents of section .init_array:"): | |
found_contents = True | |
continue | |
if found_contents: | |
if not line.strip(): | |
break | |
line_re = re.compile(r'^ *[0-9a-f]+ (([0-9a-f]+) ([0-9a-f]+)) ?(([0-9a-f]+) ([0-9a-f]+))?') | |
m = line_re.match(line) | |
if not m: continue | |
addr = m.group(1).replace(' ', '') | |
addr = int.from_bytes(bytes.fromhex(addr), 'little') | |
constructors.append((filename,addr)) | |
try: | |
addr = m.group(4) | |
if not addr: continue | |
addr = addr.replace(' ', '') | |
addr = int.from_bytes(bytes.fromhex(addr), 'little') | |
constructors.append((filename,addr)) | |
except IndexError: | |
pass | |
return constructors | |
def check_for_ffast_math(filename, addr): | |
# Call objdump to disassemble filename at addr | |
objdump_process = subprocess.Popen( | |
['objdump', f'--start-address={hex(addr)}', f'--stop-address={hex(addr+4096)}', '-d', filename], | |
stdout=subprocess.PIPE | |
) | |
found_stmxcsr, found_8040, found_rdmxcsr = False, False, False | |
for line in iter(lambda: objdump_process.stdout.readline(), b""): | |
line = line.decode('utf-8') | |
if "stmxcsr" in line: | |
found_stmxcsr = True | |
if "0x8040" in line: | |
found_8040 = True | |
if "ldmxcsr" in line: | |
found_rdmxcsr = True | |
if "retq" in line: | |
objdump_process.kill() | |
break | |
return found_stmxcsr and found_8040 and found_rdmxcsr | |
def one_check(arg): | |
filename, addr = arg | |
if check_for_ffast_math(filename, addr): | |
return f"{filename} contains ffast-math constructor" | |
for filename in sys.argv[1:]: | |
constructors = get_init_array(filename) | |
i = len(constructors) | |
with multiprocessing.Pool() as pool: | |
old = '' | |
for arg in sorted([arg for arg in pool.map(one_check, constructors) if arg is not None]): | |
if arg != old: | |
print(arg) | |
old = arg |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment