You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.2 KiB

#!/usr/bin/python
# This scripts check all the required stuff for proper support of GNU indirect
# functions (ifunc).
# To properly support ifunc, both the toolchain (gcc + binutils) and the runtime
# (glibc or bionic) must support it.
import os
import sys
import subprocess
import shlex
from subprocess import Popen, PIPE, STDOUT, call
import re
def lexical_greater_or_equals(a, b):
if (a[0] > b[0]):
return True;
if (a[0] < b[0]):
return False;
if (a[1] > b[1]):
return True;
if (a[1] < b[1]):
return False;
return (a[2] >= b[2])
if (len(sys.argv) < 3):
print("Usage: " + sys.argv[0] + " <GCC path> <arch>")
sys.exit(1)
gccpath = sys.argv[1]
if (sys.argv[2] == "intel64"):
arch = "-m64"
elif (sys.argv[2] == "ia32"):
arch = "-m32"
else:
print("Unsupported arch " + sys.argv[2] + " must be ia32 or intel64")
sys.exit(1)
p = subprocess.Popen([gccpath, arch, "-v"], stdout=PIPE, stderr=STDOUT)
gcc_out = p.communicate();
p.wait()
gcc_ver_re = re.compile(r'version (\d+)\.(\d+).(\d*)', re.MULTILINE)
gcc_ver = gcc_ver_re.search(gcc_out[0])
if (gcc_ver is None):
print("Unexpected output string from gcc:\n" + glibc_ver_out)
sys.exit(1)
gcc_major = int(gcc_ver.group(1))
gcc_middle = int(gcc_ver.group(2))
gcc_minor = 0
if (gcc_ver.group(3) != ""):
gcc_minor = int(gcc_ver.group(3))
if (not lexical_greater_or_equals([gcc_major, gcc_middle, gcc_minor], [4, 5, 0])):
print("gcc version doesn't support ifunc - must be at least 4.5.0")
sys.exit(1)
p = subprocess.Popen([gccpath, arch, "-Wl,--version"], stdout=PIPE, stderr=STDOUT)
binutils_out = p.communicate();
p.wait()
version_re = re.compile(r'(\d+)\.(\d+)\.(\d+)', re.MULTILINE)
version = version_re.search(binutils_out[0])
if version is None:
print("Unexpected output string from ld:\n" + binutils_out)
sys.exit(1)
binutils_major = int(version.group(1))
binutils_middle = int(version.group(2))
binutils_minor = int(version.group(3))
if (not lexical_greater_or_equals([binutils_major, binutils_middle, binutils_minor], [2, 20, 1])):
print("Binutils version doesn't support ifunc - must be at least 2.20.1")
sys.exit(1)
p = subprocess.Popen([gccpath, arch, "-print-file-name=libc.so.6"], stdout=PIPE, stderr=STDOUT)
glibc_path = p.communicate();
p.wait()
glibc_path_stripped = glibc_path[0].strip()
if (not os.path.isfile(glibc_path_stripped)):
print("glibc path not found: " + glibc_path)
sys.exit(1)
p = subprocess.Popen([glibc_path_stripped], stdout=PIPE, stderr=STDOUT)
glibc_ver_out = p.communicate();
p.wait()
glibc_ver_re = re.compile(r'version (\d+)\.(\d+).(\d*)', re.MULTILINE)
glibc_ver = glibc_ver_re.search(glibc_ver_out[0])
if (glibc_ver is None):
print("Unexpected output string from glibc:\n" + glibc_ver_out)
sys.exit(1)
glibc_major = int(glibc_ver.group(1))
glibc_middle = int(glibc_ver.group(2))
glibc_minor = 0
if (glibc_ver.group(3) != ""):
glibc_minor = int(glibc_ver.group(3))
if (not lexical_greater_or_equals([glibc_major, glibc_middle, glibc_minor], [2, 11, 1])):
print("glibc version doesn't support ifunc - must be at least 2.11.1")
sys.exit(1)
print("IFUNC_SUPPORTED")
sys.exit(0)