Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/libexec/ld.elf_so Handle program headers properly; fixes c++...



details:   https://anonhg.NetBSD.org/src/rev/a0411235a4f5
branches:  trunk
changeset: 373013:a0411235a4f5
user:      christos <christos%NetBSD.org@localhost>
date:      Thu Jan 12 18:52:47 2023 +0000

description:
Handle program headers properly; fixes c++ exceptions on arm32.

diffstat:

 libexec/ld.elf_so/map_object.c |  38 +++++++++++++++++++++++++++++++-------
 1 files changed, 31 insertions(+), 7 deletions(-)

diffs (100 lines):

diff -r 4413877d540b -r a0411235a4f5 libexec/ld.elf_so/map_object.c
--- a/libexec/ld.elf_so/map_object.c    Thu Jan 12 12:05:15 2023 +0000
+++ b/libexec/ld.elf_so/map_object.c    Thu Jan 12 18:52:47 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: map_object.c,v 1.63 2023/01/06 15:33:47 christos Exp $  */
+/*     $NetBSD: map_object.c,v 1.64 2023/01/12 18:52:47 christos Exp $  */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -34,7 +34,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: map_object.c,v 1.63 2023/01/06 15:33:47 christos Exp $");
+__RCSID("$NetBSD: map_object.c,v 1.64 2023/01/12 18:52:47 christos Exp $");
 #endif /* not lint */
 
 #include <errno.h>
@@ -95,12 +95,13 @@
        Elf_Addr         tls_vaddr = 0; /* Noise GCC */
 #endif
        Elf_Addr         phdr_vaddr;
+       size_t           phdr_memsz;
        int i;
 #ifdef RTLD_LOADER
        Elf_Addr         clear_vaddr;
        caddr_t          clear_page;
        caddr_t          clear_addr;
-       size_t           nclear;
+       size_t           nclear, phsize;
 #endif
 #ifdef GNU_RELRO
        Elf_Addr         relro_page;
@@ -177,12 +178,14 @@
 #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
        phtls = NULL;
 #endif
+       phsize = ehdr->e_phnum * sizeof(phdr[0]);
        obj->phdr = NULL;
 #ifdef GNU_RELRO
        relro_page = 0;
        relro_size = 0;
 #endif
        phdr_vaddr = EA_UNDEF;
+       phdr_memsz = 0;
        phlimit = phdr + ehdr->e_phnum;
        segs = xmalloc(sizeof(segs[0]) * ehdr->e_phnum);
        if (segs == NULL) {
@@ -221,6 +224,7 @@
 
                case PT_PHDR:
                        phdr_vaddr = phdr->p_vaddr;
+                       phdr_memsz = phdr->p_memsz;
                        dbg(("%s: %s %p phsize %" PRImemsz, obj->path,
                            "PT_PHDR",
                            (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz));
@@ -341,6 +345,7 @@
        }
 #endif
 
+       obj->phdr_loaded = false;
        for (i = 0; i <= nsegs; i++) {
                /* Overlay the segment onto the proper region. */
                data_offset = round_down(segs[i]->p_offset);
@@ -405,12 +410,31 @@
                        }
                }
 
-               if (phdr_vaddr == 0 && data_offset <= ehdr->e_phoff &&
-                   (data_vlimit - data_vaddr + data_offset) >=
-                   (ehdr->e_phoff + ehdr->e_phnum * sizeof (Elf_Phdr))) {
-                       phdr_vaddr = data_vaddr + ehdr->e_phoff - data_offset;
+               if (phdr_vaddr != EA_UNDEF &&
+                   segs[i]->p_vaddr <= phdr_vaddr &&
+                   segs[i]->p_memsz >= phdr_memsz) {
+                       obj->phdr_loaded = true;
+               }
+               if (segs[i]->p_offset <= ehdr->e_phoff &&
+                   segs[i]->p_memsz >= phsize) {
+                       phdr_vaddr = segs[i]->p_vaddr + ehdr->e_phoff;
+                       phdr_memsz = phsize;
+                       obj->phdr_loaded = true;
                }
        }
+       if (obj->phdr_loaded) {
+               obj->phdr = (void *)(uintptr_t)phdr_vaddr;
+               obj->phsize = phdr_memsz;
+       } else {
+               Elf_Phdr *buf = xmalloc(phsize);
+               if (buf == NULL) {
+                       _rtld_error("%s: cannot allocate program header", path);
+                       goto error;
+               }
+               memcpy(buf, phdr, phsize);
+               obj->phdr = buf;
+               obj->phsize = phsize;
+       }
 
 #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
        if (phtls != NULL)



Home | Main Index | Thread Index | Old Index