これをより自動化された方法で行うには、次のスクリプトを使用して、特定のバージョン(2行目に設定)よりもGLIBCで新しいすべてのシンボルのリストを作成できます。必要なすべての宣言glibc.h
を含むファイル(スクリプト引数によって設定されたファイル名)を作成します。.symver
次に、CFLAGSに追加-include glibc.h
して、コンパイルのあらゆる場所で確実に取得されるようにすることができます。
上記のインクルードなしでコンパイルされた静的ライブラリを使用しない場合は、これで十分です。再コンパイルしたくない場合は、を使用objcopy
して、シンボルの名前を古いバージョンに変更したライブラリのコピーを作成できます。スクリプトの2番目から最後の行はlibstdc++.a
、古いglibcシンボルに対してリンクするシステムのバージョンを作成します。-L.
(または)を追加-Lpath/to/libstdc++.a/
すると、プログラムは新しいシンボルの束にリンクすることなく、libstdc++を静的にリンクします。これが必要ない場合は、最後の2行とその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