backends: check_special_symbol _GLOBAL_OFFSET_TABLE_ points inside .got

Message ID 20241230002521.981932-1-mark@klomp.org
State Committed
Headers
Series backends: check_special_symbol _GLOBAL_OFFSET_TABLE_ points inside .got |

Commit Message

Mark Wielaard Dec. 30, 2024, 12:25 a.m. UTC
  If desthdr is ".got.plt" search for the actual ".got" section and make
sure the _GLOBAL_OFFSET_TABLE_ points to it.

     * backends/riscv_symbol.c (riscv_check_special_symbol): Check
     sname is ".got.plt", find ".got" scn to check sym st_value.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 backends/riscv_symbol.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)
  

Comments

Mark Wielaard Dec. 31, 2024, 5:11 p.m. UTC | #1
Hi,

On Mon, 2024-12-30 at 01:25 +0100, Mark Wielaard wrote:
> If desthdr is ".got.plt" search for the actual ".got" section and make
> sure the _GLOBAL_OFFSET_TABLE_ points to it.
> 
>      * backends/riscv_symbol.c (riscv_check_special_symbol): Check
>      sname is ".got.plt", find ".got" scn to check sym st_value.

Pushed this to get the riscv ci buildbots green again.

Cheers,

Mark
  

Patch

diff --git a/backends/riscv_symbol.c b/backends/riscv_symbol.c
index c149b8ba27cf..3de8070be873 100644
--- a/backends/riscv_symbol.c
+++ b/backends/riscv_symbol.c
@@ -1,4 +1,5 @@ 
 /* RISC-V specific symbolic name handling.
+   Copyright (C) 2024 Mark J. Wielaard <mark@klomp.org>
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -104,9 +105,29 @@  riscv_check_special_symbol (Elf *elf, const GElf_Sym *sym,
   /* _GLOBAL_OFFSET_TABLE_ points to the start of the .got section, but it
      is preceded by the .got.plt section in the output .got section.  */
   if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
-    return (strcmp (sname, ".got") == 0
-	    && sym->st_value >= destshdr->sh_addr
-	    && sym->st_value < destshdr->sh_addr + destshdr->sh_size);
+    {
+      if (strcmp (sname, ".got") == 0
+	  && sym->st_value >= destshdr->sh_addr
+	  && sym->st_value < destshdr->sh_addr + destshdr->sh_size)
+	return true;
+      else if (strcmp (sname, ".got.plt") == 0)
+	{
+	  /* Find .got section and compare against that.  */
+	  Elf_Scn *scn = NULL;
+	  while ((scn = elf_nextscn (elf, scn)) != NULL)
+	    {
+	      GElf_Shdr shdr_mem;
+	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	      if (shdr != NULL)
+		{
+		  sname = elf_strptr (elf, shstrndx, shdr->sh_name);
+		  if (sname != NULL && strcmp (sname, ".got") == 0)
+		    return (sym->st_value >= shdr->sh_addr
+			    && sym->st_value < shdr->sh_addr + shdr->sh_size);
+		}
+	    }
+	}
+    }
 
   /* __global_pointer$ points to the .sdata section with an offset of
      0x800.  It might however fall in the .got section, in which case we