Fix localplt check for GNU_IFUNC

Message ID 531B63DE.5090803@linux.vnet.ibm.com
State Rejected
Delegated to: Adhemerval Zanella Netto
Headers

Commit Message

Adhemerval Zanella Netto March 8, 2014, 6:39 p.m. UTC
  While reviewing the strncat optimization for powerpc64 I noted in the
disassembled object that a call to strlen (bl strlen) generates a PLT
call to strlen (since now strlen is an IFUNC for powerpc64). Strangely
it was not being caught by check-localplt testcase.

GNU_IFUNC are shown by readelf in 'Relocation section' value as (symbol)
instead of expected hexadecimal value. This causes the check-localplt
script to igore potential PLT stub begin generated by wrong IFUNC usage.
This patch changes the localplt script to emit such PLT cases.

Checked on PPC64 and X86_64.

--

2014-03-03  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>

        * scripts/localplt.awk: Do not ignore IFUNC relocation while parsing
	relocation sections.

---
  

Comments

Carlos O'Donell March 19, 2014, 6:47 p.m. UTC | #1
On 03/08/2014 01:39 PM, Adhemerval Zanella wrote:
> While reviewing the strncat optimization for powerpc64 I noted in the
> disassembled object that a call to strlen (bl strlen) generates a PLT
> call to strlen (since now strlen is an IFUNC for powerpc64). Strangely
> it was not being caught by check-localplt testcase.
> 
> GNU_IFUNC are shown by readelf in 'Relocation section' value as (symbol)
> instead of expected hexadecimal value. This causes the check-localplt
> script to igore potential PLT stub begin generated by wrong IFUNC usage.
> This patch changes the localplt script to emit such PLT cases.
> 
> Checked on PPC64 and X86_64.
> 
> --
> 
> 2014-03-03  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
> 
>         * scripts/localplt.awk: Do not ignore IFUNC relocation while parsing
> 	relocation sections.

Can you show example output?

On x86-64 I see:
0000003000bba030  0000034400000007 R_X86_64_JUMP_SLOT     memset()         memset + 0
0000003000bba048  000007ba00000007 R_X86_64_JUMP_SLOT     memmove()        memmove + 0

Not (memset) or (memmove).

I'd like to see this fixed... and this is the first patch in patchtracker :-)

> ---
> 
> diff --git a/scripts/localplt.awk b/scripts/localplt.awk
> index 2265b02..5e38073 100644
> --- a/scripts/localplt.awk
> +++ b/scripts/localplt.awk
> @@ -32,9 +32,15 @@ $1 == "Offset" && $2 == "Info" { in_relocs = 1; next }
>  NF == 0 { in_relocs = 0 }
>  
>  in_relocs && relocs_offset == jmprel_offset && NF >= 5 {
> -  symval = strtonum("0x" $4);
> -  if (symval != 0)
> +  # Relocations against GNU_IFUNC symbols are not shown as an hexadecimal
> +  # value, but rather as the resolver symbol name between ().
> +  if ($4 ~ /\(.*\)/) {
>      print whatfile, $5
> +  } else {
> +    symval = strtonum("0x" $4);
> +    if (symval != 0)
> +      print whatfile, $5
> +  }
>  }
>  
>  in_relocs { next }
>
  

Patch

diff --git a/scripts/localplt.awk b/scripts/localplt.awk
index 2265b02..5e38073 100644
--- a/scripts/localplt.awk
+++ b/scripts/localplt.awk
@@ -32,9 +32,15 @@  $1 == "Offset" && $2 == "Info" { in_relocs = 1; next }
 NF == 0 { in_relocs = 0 }
 
 in_relocs && relocs_offset == jmprel_offset && NF >= 5 {
-  symval = strtonum("0x" $4);
-  if (symval != 0)
+  # Relocations against GNU_IFUNC symbols are not shown as an hexadecimal
+  # value, but rather as the resolver symbol name between ().
+  if ($4 ~ /\(.*\)/) {
     print whatfile, $5
+  } else {
+    symval = strtonum("0x" $4);
+    if (symval != 0)
+      print whatfile, $5
+  }
 }
 
 in_relocs { next }