Extend local PLT reference check
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 29 Jul 2015 18:57:54 +0000 (11:57 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 29 Jul 2015 18:58:06 +0000 (11:58 -0700)
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.

ChangeLog
NEWS
scripts/check-localplt.awk
scripts/localplt.awk
sysdeps/unix/sysv/linux/i386/localplt.data
sysdeps/x86_64/localplt.data [new file with mode: 0644]

index 9a5e489..6f393fd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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]
diff --git a/NEWS b/NEWS
index 5698310..5be4917 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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.
index bb1b912..3965292 100644 (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);
 }
index 84c94d1..f75b3b4 100644 (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) }
index b25abf8..2e03821 100644 (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
diff --git a/sysdeps/x86_64/localplt.data b/sysdeps/x86_64/localplt.data
new file mode 100644 (file)
index 0000000..d140476
--- /dev/null
@@ -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