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
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)
|