Чтобы сделать это более автоматизированным способом, вы можете использовать следующий скрипт, чтобы создать список всех символов, которые являются более новыми в вашей GLIBC, чем в данной версии (установлено в строке 2). Он создает файл glibc.h
(имя файла задается аргументом script), который содержит все необходимые объявления .symver
. Затем вы можете добавить -include glibc.h
к своим CFLAGS, чтобы убедиться, что он будет использован везде в вашей компиляции.
Этого достаточно, если вы не используете статические библиотеки, которые были скомпилированы без включенного выше. Если вы это сделаете и не хотите перекомпилировать, вы можете использовать objcopy
для создания копии библиотеки с символами, переименованными в старые версии. Вторая в нижней строке сценария создает версию вашей системы libstdc++.a
, которая будет ссылаться на старые символы glibc. Добавление -L.
(или -Lpath/to/libstdc++.a/
) заставит вашу программу статически связывать libstdc ++ без связывания в кучу новых символов. Если вам это не нужно, удалите две последние строки и строку printf ... redeff
.
#!/bin/bash
maxver=2.9
headerf=${1:-glibc.h}
set -e
for lib in libc.so.6 libm.so.6 libpthread.so.0 libdl.so.2 libresolv.so.2 librt.so.1; do
objdump -T /usr/lib/$lib
done | awk -v maxver=${maxver} -vheaderf=${headerf} -vredeff=${headerf}.redef -f <(cat <<'EOF'
BEGIN {
split(maxver, ver, /\./)
limit_ver = ver[1] * 10000 + ver[2]*100 + ver[3]
}
/GLIBC_/ {
gsub(/\(|\)/, "",$(NF-1))
split($(NF-1), ver, /GLIBC_|\./)
vers = ver[2] * 10000 + ver[3]*100 + ver[4]
if (vers > 0) {
if (symvertext[$(NF)] != $(NF-1))
count[$(NF)]++
if (vers <= limit_ver && vers > symvers[$(NF)]) {
symvers[$(NF)] = vers
symvertext[$(NF)] = $(NF-1)
}
}
}
END {
for (s in symvers) {
if (count[s] > 1) {
printf("__asm__(\".symver %s,%s@%s\");\n", s, s, symvertext[s]) > headerf
printf("%s %s@%s\n", s, s, symvertext[s]) > redeff
}
}
}
EOF
)
sort ${headerf} -o ${headerf}
objcopy --redefine-syms=${headerf}.redef /usr/lib/libstdc++.a libstdc++.a
rm ${headerf}.redef