Extend local PLT reference check

On x86, linker in binutils 2.26 and newer consolidates R_*_JUMP_SLOT with
R_*_GLOB_DAT relocation against the same symbol.  This patch extends
local PLT reference check to support alternate relocations.

	[BZ #18078]
	* scripts/check-localplt.awk: Support alternate relocations.
	* scripts/localplt.awk: Also check relocations in DT_RELA/DT_REL
	sections.
	* sysdeps/unix/sysv/linux/i386/localplt.data: Mark free and
	malloc entries with + REL R_386_GLOB_DAT.
	* sysdeps/x86_64/localplt.data: New file.
This commit is contained in:
H.J. Lu 2015-07-29 11:57:54 -07:00
parent febce2ac5f
commit 9637d8a253
6 changed files with 127 additions and 19 deletions

View File

@ -1,3 +1,13 @@
2015-07-29 H.J. Lu <hongjiu.lu@intel.com>
[BZ #18078]
* scripts/check-localplt.awk: Support alternate relocations.
* scripts/localplt.awk: Also check relocations in DT_RELA/DT_REL
sections.
* sysdeps/unix/sysv/linux/i386/localplt.data: Mark free and
malloc entries with + REL R_386_GLOB_DAT.
* sysdeps/x86_64/localplt.data: New file.
2015-07-29 Andrew Senkevich <andrew.senkevich@intel.com>
[BZ #18731]

22
NEWS
View File

@ -18,17 +18,17 @@ Version 2.22
17841, 17912, 17916, 17930, 17932, 17944, 17949, 17964, 17965, 17967,
17969, 17977, 17978, 17987, 17991, 17996, 17998, 17999, 18007, 18019,
18020, 18029, 18030, 18032, 18034, 18036, 18038, 18039, 18042, 18043,
18046, 18047, 18049, 18068, 18080, 18093, 18100, 18104, 18110, 18111,
18116, 18125, 18128, 18134, 18138, 18185, 18196, 18197, 18206, 18210,
18211, 18217, 18219, 18220, 18221, 18234, 18244, 18245, 18247, 18287,
18319, 18324, 18333, 18346, 18371, 18383, 18397, 18400, 18409, 18410,
18412, 18418, 18422, 18434, 18444, 18457, 18468, 18469, 18470, 18479,
18483, 18495, 18496, 18497, 18498, 18502, 18507, 18508, 18512, 18513,
18519, 18520, 18522, 18527, 18528, 18529, 18530, 18532, 18533, 18534,
18536, 18539, 18540, 18542, 18544, 18545, 18546, 18547, 18549, 18553,
18557, 18558, 18569, 18583, 18585, 18586, 18592, 18593, 18594, 18602,
18612, 18613, 18619, 18633, 18641, 18643, 18648, 18657, 18676, 18694,
18696.
18046, 18047, 18049, 18068, 18078, 18080, 18093, 18100, 18104, 18110,
18111, 18116, 18125, 18128, 18134, 18138, 18185, 18196, 18197, 18206,
18210, 18211, 18217, 18219, 18220, 18221, 18234, 18244, 18245, 18247,
18287, 18319, 18324, 18333, 18346, 18371, 18383, 18397, 18400, 18409,
18410, 18412, 18418, 18422, 18434, 18444, 18457, 18468, 18469, 18470,
18479, 18483, 18495, 18496, 18497, 18498, 18502, 18507, 18508, 18512,
18513, 18519, 18520, 18522, 18527, 18528, 18529, 18530, 18532, 18533,
18534, 18536, 18539, 18540, 18542, 18544, 18545, 18546, 18547, 18549,
18553, 18557, 18558, 18569, 18583, 18585, 18586, 18592, 18593, 18594,
18602, 18612, 18613, 18619, 18633, 18641, 18643, 18648, 18657, 18676,
18694, 18696.
* Cache information can be queried via sysconf() function on s390 e.g. with
_SC_LEVEL1_ICACHE_SIZE as argument.

View File

@ -3,9 +3,14 @@
# Each line is either a comment starting with # or it looks like:
# libfoo.so: function
# or
# libfoo.so: function + {RELA|REL} RELOC
# or
# libfoo.so: function ?
# The latter means that a PLT entry for function is optional in libfoo.so.
# The former means one is required.
# The first entry means that one is required.
# The second entry means that one is required and relocation may also be
# {RELA|REL} RELOC.
# The third entry means that a PLT entry for function is optional in
# libfoo.so.
# The second file argument is - and this (stdin) receives the output
# of the check-localplt program.
@ -14,7 +19,10 @@ BEGIN { result = 0 }
FILENAME != "-" && /^#/ { next }
FILENAME != "-" {
if (NF != 2 && !(NF == 3 && $3 == "?")) {
if (NF == 5 && $3 == "+" && ($4 == "RELA" || $4 == "REL")) {
accept_type[$1 " " $2] = $4;
accept_reloc[$1 " " $2] = $5;
} else if (NF != 2 && !(NF == 3 && $3 == "?")) {
printf "%s:%d: bad data line: %s\n", FILENAME, FNR, $0 > "/dev/stderr";
result = 2;
} else {
@ -23,7 +31,7 @@ FILENAME != "-" {
next;
}
NF != 2 {
NF != 2 && !(NF == 4 && ($3 == "RELA" || $3 == "REL")) {
print "Unexpected output from check-localplt:", $0 > "/dev/stderr";
result = 2;
next
@ -31,7 +39,23 @@ NF != 2 {
{
key = $1 " " $2
if (key in accept) {
if ($3 == "RELA" || $3 == "REL") {
# Entries like:
# libc.so: free + RELA R_X86_64_GLOB_DAT
# may be ignored.
if (key in accept_type && accept_type[key] == $3 && accept_reloc[key] == $4) {
# Match
# libc.so: free + RELA R_X86_64_GLOB_DAT
delete accept_type[key]
}
} else if (NF == 2 && key in accept_reloc) {
# Match
# libc.so: free
# against
# libc.so: free + RELA R_X86_64_GLOB_DAT
if (key in accept_type)
delete accept_type[key]
} else if (key in accept) {
delete accept[key]
} else {
print "Extra PLT reference:", $0;
@ -49,5 +73,11 @@ END {
}
}
for (key in accept_type) {
# It's mandatory.
print "Missing required PLT or " accept_reloc[key] " reference:", key;
result = 1;
}
exit(result);
}

View File

@ -13,6 +13,8 @@ FILENAME != lastfile {
}
lastfile = FILENAME;
jmprel_offset = 0;
rela_offset = 0;
rel_offset = 0;
delete section_offset_by_address;
}
@ -43,6 +45,30 @@ in_relocs && relocs_offset == jmprel_offset && NF >= 5 {
}
}
in_relocs && relocs_offset == rela_offset && NF >= 5 {
# Relocations against GNU_IFUNC symbols are not shown as an hexadecimal
# value, but rather as the resolver symbol followed by ().
if ($4 ~ /\(\)/) {
print whatfile, gensub(/@.*/, "", "g", $5), "RELA", $3
} else {
symval = strtonum("0x" $4);
if (symval != 0)
print whatfile, gensub(/@.*/, "", "g", $5), "RELA", $3
}
}
in_relocs && relocs_offset == rel_offset && NF >= 5 {
# Relocations against GNU_IFUNC symbols are not shown as an hexadecimal
# value, but rather as the resolver symbol followed by ().
if ($4 ~ /\(\)/) {
print whatfile, gensub(/@.*/, "", "g", $5), "REL", $3
} else {
symval = strtonum("0x" $4);
if (symval != 0)
print whatfile, gensub(/@.*/, "", "g", $5), "REL", $3
}
}
in_relocs { next }
$1 == "Relocation" && $2 == "section" && $5 == "offset" {
@ -62,4 +88,25 @@ $2 == "(JMPREL)" {
next
}
$2 == "(RELA)" {
rela_addr = strtonum($3);
if (rela_addr in section_offset_by_address) {
rela_offset = section_offset_by_address[rela_addr];
} else {
print FILENAME ": *** DT_RELA does not match any section's address";
result = 2;
}
next
}
$2 == "(REL)" {
rel_addr = strtonum($3);
if (rel_addr in section_offset_by_address) {
rel_offset = section_offset_by_address[rel_addr];
} else {
print FILENAME ": *** DT_REL does not match any section's address";
result = 2;
}
next
}
END { exit(result) }

View File

@ -1,7 +1,9 @@
# Linker in binutils 2.26 and newer consolidates R_X86_64_JUMP_SLOT
# relocation with R_386_GLOB_DAT relocation against the same symbol.
libc.so: _Unwind_Find_FDE
libc.so: calloc
libc.so: free
libc.so: malloc
libc.so: free + REL R_386_GLOB_DAT
libc.so: malloc + REL R_386_GLOB_DAT
libc.so: memalign
libc.so: realloc
libm.so: matherr
@ -12,4 +14,4 @@ ld.so: __libc_memalign
ld.so: malloc
ld.so: calloc
ld.so: realloc
ld.so: free
ld.so: free + REL R_386_GLOB_DAT

View File

@ -0,0 +1,19 @@
# See scripts/check-localplt.awk for how this file is processed.
# PLT use is required for the malloc family and for matherr because
# users can define their own functions and have library internals call them.
# Linker in binutils 2.26 and newer consolidates R_X86_64_JUMP_SLOT
# relocation with R_X86_64_GLOB_DAT relocation against the same symbol.
libc.so: calloc
libc.so: free + RELA R_X86_64_GLOB_DAT
libc.so: malloc + RELA R_X86_64_GLOB_DAT
libc.so: memalign
libc.so: realloc
libm.so: matherr
# The dynamic loader uses __libc_memalign internally to allocate aligned
# TLS storage. The other malloc family of functions are expected to allow
# user symbol interposition.
ld.so: __libc_memalign
ld.so: malloc
ld.so: calloc
ld.so: realloc
ld.so: free + RELA R_X86_64_GLOB_DAT