Skip to content

Instantly share code, notes, and snippets.

@nickalcock
Forked from moyix/check_for_ffast_math.py
Last active October 28, 2022 14:36
Show Gist options
  • Save nickalcock/d6400b123b49462e15f6b9a3a5c1cbc7 to your computer and use it in GitHub Desktop.
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
#!/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