On 04/05/2011 11:03 PM, Bernhard Reutner-Fischer wrote:
> On Fri, Apr 01, 2011 at 03:06:55PM +0200, Bernd Schmidt wrote:
> 
>> +    char *piclib2map = 0;
> 
> = NULL

>> +#ifndef MIN
>> +# define MIN(a,b) ((a) < (b) ? (a) : (b))
> 
> MIN is always defined via sys/param.h

>> +            cant_map:
> 
> Please use uppercase labels (also for cant_map1 et al)

>> +#if defined (__SUPPORT_LD_DEBUG__)
>> +  {
>> +    extern char *_dl_debug;
>> +    extern int _dl_debug_file;
> 
> Why are these 2 externs needed?

I suspect they aren't. However, everything you pointed out already
existed in the code I was changing. Below is a new version, however I'd
like to ask you to reconsider the uppercase labels, which isn't
consistent with anything else in this file, or in fact most other code
in uClibc as shown by find|xargs grep goto. Nor is it done like this in
any popular coding style I'm aware of (e.g. Linux or GNU).


Bernd
diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h
index 7fbb373..e7203fd 100644
--- a/ldso/include/dl-elf.h
+++ b/ldso/include/dl-elf.h
@@ -184,7 +184,7 @@ unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, 
unsigned long dynamic_info
        ADJUST_DYN_INFO(DT_DSBT_BASE_IDX, load_off);
 
        /* Initialize loadmap dsbt info.  */
-       load_off.map->dsbt_table = dynamic_info[DT_DSBT_BASE_IDX];
+       load_off.map->dsbt_table = (void *)dynamic_info[DT_DSBT_BASE_IDX];
        load_off.map->dsbt_size = dynamic_info[DT_DSBT_SIZE_IDX];
        load_off.map->dsbt_index = dynamic_info[DT_DSBT_INDEX_IDX];
 #endif
diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h
index 69b5dd7..95bcd14 100644
--- a/ldso/include/ldso.h
+++ b/ldso/include/ldso.h
@@ -34,6 +34,8 @@
 #include <sys/types.h>
 /* Pull in the arch specific page size */
 #include <bits/uClibc_page.h>
+/* Pull in the MIN macro */
+#include <sys/param.h>
 /* Pull in the ldso syscalls and string functions */
 #ifndef __ARCH_HAS_NO_SHARED__
 #include <dl-syscall.h>
diff --git a/ldso/ldso/bfin/dl-inlines.h b/ldso/ldso/bfin/dl-inlines.h
index 6524f5e..9699862 100644
--- a/ldso/ldso/bfin/dl-inlines.h
+++ b/ldso/ldso/bfin/dl-inlines.h
@@ -88,14 +88,39 @@ __dl_init_loadaddr_hdr (struct elf32_fdpic_loadaddr 
loadaddr, void *addr,
   segdata->p_memsz = phdr->p_memsz;
 
 #if defined (__SUPPORT_LD_DEBUG__)
-  {
-    extern char *_dl_debug;
-    extern int _dl_debug_file;
-    if (_dl_debug)
-      _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
-                 loadaddr.map->nsegs-1,
-                 segdata->p_vaddr, segdata->addr, segdata->p_memsz);
-  }
+  if (_dl_debug)
+    _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
+               loadaddr.map->nsegs-1,
+               segdata->p_vaddr, segdata->addr, segdata->p_memsz);
+#endif
+}
+
+/* Replace an existing entry in the load map.  */
+static __always_inline void
+__dl_update_loadaddr_hdr (struct elf32_fdpic_loadaddr loadaddr, void *addr,
+                         Elf32_Phdr *phdr)
+{
+  struct elf32_fdpic_loadseg *segdata;
+  void *oldaddr;
+  int i;
+
+  for (i = 0; i < loadaddr.map->nsegs; i++)
+    if (loadaddr.map->segs[i].p_vaddr == phdr->p_vaddr
+       && loadaddr.map->segs[i].p_memsz == phdr->p_memsz)
+      break;
+  if (i == loadaddr.map->nsegs)
+    _dl_exit (-1);
+
+  segdata = loadaddr.map->segs + i;
+  oldaddr = (void *)segdata->addr;
+  _dl_munmap (oldaddr, segdata->p_memsz);
+  segdata->addr = (Elf32_Addr) addr;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+  if (_dl_debug)
+    _dl_dprintf(_dl_debug_file, "%i: changed mapping %x at %x (old %x), size 
%x\n",
+               loadaddr.map->nsegs-1,
+               segdata->p_vaddr, segdata->addr, oldaddr, segdata->p_memsz);
 #endif
 }
 
diff --git a/ldso/ldso/bfin/dl-sysdep.h b/ldso/ldso/bfin/dl-sysdep.h
index 50c7509..168e5c8 100644
--- a/ldso/ldso/bfin/dl-sysdep.h
+++ b/ldso/ldso/bfin/dl-sysdep.h
@@ -120,6 +120,8 @@ struct funcdesc_ht;
 #define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
   (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
                           dl_init_loadaddr_load_count))
+#define DL_UPDATE_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+  (__dl_update_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR)))
 #define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
   (__dl_loadaddr_unmap ((LOADADDR), (NULL)))
 #define DL_LIB_UNMAP(LIB, LEN) \
diff --git a/ldso/ldso/c6x/dl-inlines.h b/ldso/ldso/c6x/dl-inlines.h
index d8fb42c..62e1cc9 100644
--- a/ldso/ldso/c6x/dl-inlines.h
+++ b/ldso/ldso/c6x/dl-inlines.h
@@ -74,6 +74,35 @@ __dl_init_loadaddr_hdr (struct elf32_dsbt_loadaddr loadaddr, 
void *addr,
 #endif
 }
 
+/* Replace an existing entry in the load map.  */
+static __always_inline void
+__dl_update_loadaddr_hdr (struct elf32_dsbt_loadaddr loadaddr, void *addr,
+                       Elf32_Phdr *phdr)
+{
+       struct elf32_dsbt_loadseg *segdata;
+       void *oldaddr;
+       int i;
+
+       for (i = 0; i < loadaddr.map->nsegs; i++)
+               if (loadaddr.map->segs[i].p_vaddr == phdr->p_vaddr
+                   && loadaddr.map->segs[i].p_memsz == phdr->p_memsz)
+                       break;
+       if (i == loadaddr.map->nsegs)
+               _dl_exit (-1);
+
+       segdata = loadaddr.map->segs + i;
+       oldaddr = (void *)segdata->addr;
+       _dl_munmap (oldaddr, segdata->p_memsz);
+       segdata->addr = (Elf32_Addr) addr;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+       if (_dl_debug)
+               _dl_dprintf(_dl_debug_file, "%i: changed mapping %x at %x (old 
%x), size %x\n",
+                           loadaddr.map->nsegs-1,
+                           segdata->p_vaddr, segdata->addr, oldaddr, 
segdata->p_memsz);
+#endif
+}
+
 static __always_inline void
 __dl_loadaddr_unmap (struct elf32_dsbt_loadaddr loadaddr)
 {
diff --git a/ldso/ldso/c6x/dl-sysdep.h b/ldso/ldso/c6x/dl-sysdep.h
index 8f1b122..ff7accd 100644
--- a/ldso/ldso/c6x/dl-sysdep.h
+++ b/ldso/ldso/c6x/dl-sysdep.h
@@ -104,6 +104,9 @@ struct elf32_dsbt_loadaddr;
   (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
                           dl_init_loadaddr_load_count))
 
+#define DL_UPDATE_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+  (__dl_update_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR)))
+
 #define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
   (__dl_loadaddr_unmap ((LOADADDR)))
 
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index 505247e..70503bc 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -314,6 +314,121 @@ goof:
        return NULL;
 }
 
+/*
+ * Make a writeable mapping of a segment, regardless of whether PF_W is
+ * set or not.
+ */
+static void *
+map_writeable (int infile, ElfW(Phdr) *ppnt, int piclib, int flags,
+              unsigned long libaddr)
+{
+       int prot_flags = ppnt->p_flags | PF_W;
+       char *status, *retval;
+       char *tryaddr;
+       ssize_t size;
+       unsigned long map_size;
+       char *cpnt;
+       char *piclib2map = NULL;
+
+       if (piclib == 2 &&
+           /* We might be able to avoid this call if memsz doesn't
+              require an additional page, but this would require mmap
+              to always return page-aligned addresses and a whole
+              number of pages allocated.  Unfortunately on uClinux
+              may return misaligned addresses and may allocate
+              partial pages, so we may end up doing unnecessary mmap
+              calls.
+
+              This is what we could do if we knew mmap would always
+              return aligned pages:
+
+              ((ppnt->p_vaddr + ppnt->p_filesz + ADDR_ALIGN) &
+              PAGE_ALIGN) < ppnt->p_vaddr + ppnt->p_memsz)
+
+              Instead, we have to do this:  */
+           ppnt->p_filesz < ppnt->p_memsz)
+       {
+               piclib2map = (char *)
+                       _dl_mmap(0, (ppnt->p_vaddr & ADDR_ALIGN) + 
ppnt->p_memsz,
+                                LXFLAGS(prot_flags), flags | MAP_ANONYMOUS, 
-1, 0);
+               if (_dl_mmap_check_error(piclib2map))
+                       return 0;
+       }
+
+       tryaddr = piclib == 2 ? piclib2map
+               : ((char*) (piclib ? libaddr : 0) +
+                  (ppnt->p_vaddr & PAGE_ALIGN));
+
+       size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
+
+       /* For !MMU, mmap to fixed address will fail.
+          So instead of desperately call mmap and fail,
+          we set status to MAP_FAILED to save a call
+          to mmap ().  */
+#ifndef __ARCH_USE_MMU__
+       if (piclib2map == 0)
+#endif
+               status = (char *) _dl_mmap
+                       (tryaddr, size, LXFLAGS(prot_flags),
+                        flags | (piclib2map ? MAP_FIXED : 0),
+                        infile, ppnt->p_offset & OFFS_ALIGN);
+#ifndef __ARCH_USE_MMU__
+       else
+               status = MAP_FAILED;
+#endif
+#ifdef _DL_PREAD
+       if (_dl_mmap_check_error(status) && piclib2map
+           && (_DL_PREAD (infile, tryaddr, size,
+                          ppnt->p_offset & OFFS_ALIGN) == size))
+               status = tryaddr;
+#endif
+       if (_dl_mmap_check_error(status) || (tryaddr && tryaddr != status))
+               return 0;
+
+       if (piclib2map)
+               retval = piclib2map;
+       else
+               retval = status;
+
+       /* Now we want to allocate and zero-out any data from the end
+          of the region we mapped in from the file (filesz) to the
+          end of the loadable segment (memsz).  We may need
+          additional pages for memsz, that we map in below, and we
+          can count on the kernel to zero them out, but we have to
+          zero out stuff in the last page that we mapped in from the
+          file.  However, we can't assume to have actually obtained
+          full pages from the kernel, since we didn't ask for them,
+          and uClibc may not give us full pages for small
+          allocations.  So only zero out up to memsz or the end of
+          the page, whichever comes first.  */
+
+       /* CPNT is the beginning of the memsz portion not backed by
+          filesz.  */
+       cpnt = (char *) (status + size);
+
+       /* MAP_SIZE is the address of the
+          beginning of the next page.  */
+       map_size = (ppnt->p_vaddr + ppnt->p_filesz
+                   + ADDR_ALIGN) & PAGE_ALIGN;
+
+       _dl_memset (cpnt, 0,
+                   MIN (map_size
+                        - (ppnt->p_vaddr
+                           + ppnt->p_filesz),
+                        ppnt->p_memsz
+                        - ppnt->p_filesz));
+
+       if (map_size < ppnt->p_vaddr + ppnt->p_memsz && !piclib2map) {
+               tryaddr = map_size + (char*)(piclib ? libaddr : 0);
+               status = (char *) _dl_mmap(tryaddr,
+                                          ppnt->p_vaddr + ppnt->p_memsz - 
map_size,
+                                          LXFLAGS(prot_flags),
+                                          flags | MAP_ANONYMOUS | MAP_FIXED, 
-1, 0);
+               if (_dl_mmap_check_error(status) || tryaddr != status)
+                       return NULL;
+       }
+       return retval;
+}
 
 /*
  * Read one ELF library into memory, mmap it into the correct locations and
@@ -475,6 +590,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
                                maxvma - minvma, PROT_NONE, flags | 
MAP_ANONYMOUS, -1, 0);
                if (_dl_mmap_check_error(status)) {
+               CANT_MAP:
                        _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, 
__LINE__, libname);
                        _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
                        _dl_close(infile);
@@ -495,8 +611,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                        char *addr;
 
                        addr = DL_MAP_SEGMENT (epnt, ppnt, infile, flags);
-                       if (addr == NULL)
-                               goto cant_map;
+                       if (addr == NULL) {
+                       CANT_MAP1:
+                               DL_LOADADDR_UNMAP (lib_loadaddr, maxvma - 
minvma);
+                               goto CANT_MAP;
+                       }
 
                        DL_INIT_LOADADDR_HDR (lib_loadaddr, addr, ppnt);
                        ppnt++;
@@ -517,141 +636,9 @@ struct elf_resolve *_dl_load_elf_shared_library(int 
secure,
                        }
 
                        if (ppnt->p_flags & PF_W) {
-                               unsigned long map_size;
-                               char *cpnt;
-                               char *piclib2map = 0;
-
-                               if (piclib == 2 &&
-                                   /* We might be able to avoid this
-                                      call if memsz doesn't require
-                                      an additional page, but this
-                                      would require mmap to always
-                                      return page-aligned addresses
-                                      and a whole number of pages
-                                      allocated.  Unfortunately on
-                                      uClinux may return misaligned
-                                      addresses and may allocate
-                                      partial pages, so we may end up
-                                      doing unnecessary mmap calls.
-
-                                      This is what we could do if we
-                                      knew mmap would always return
-                                      aligned pages:
-
-                                   ((ppnt->p_vaddr + ppnt->p_filesz
-                                     + ADDR_ALIGN)
-                                    & PAGE_ALIGN)
-                                   < ppnt->p_vaddr + ppnt->p_memsz)
-
-                                      Instead, we have to do this:  */
-                                   ppnt->p_filesz < ppnt->p_memsz)
-                                 {
-                                   piclib2map = (char *)
-                                     _dl_mmap(0, (ppnt->p_vaddr & ADDR_ALIGN)
-                                              + ppnt->p_memsz,
-                                              LXFLAGS(ppnt->p_flags),
-                                              flags | MAP_ANONYMOUS, -1, 0);
-                                   if (_dl_mmap_check_error(piclib2map))
-                                     goto cant_map;
-                                   DL_INIT_LOADADDR_HDR
-                                     (lib_loadaddr, piclib2map
-                                      + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
-                                 }
-
-                               tryaddr = piclib == 2 ? piclib2map
-                                 : ((char*) (piclib ? libaddr : 0) +
-                                    (ppnt->p_vaddr & PAGE_ALIGN));
-
-                               size = (ppnt->p_vaddr & ADDR_ALIGN)
-                                 + ppnt->p_filesz;
-
-                               /* For !MMU, mmap to fixed address will fail.
-                                  So instead of desperately call mmap and fail,
-                                  we set status to MAP_FAILED to save a call
-                                  to mmap ().  */
-#ifndef __ARCH_USE_MMU__
-                               if (piclib2map == 0)
-#endif
-                                 status = (char *) _dl_mmap
-                                   (tryaddr, size, LXFLAGS(ppnt->p_flags),
-                                    flags | (piclib2map ? MAP_FIXED : 0),
-                                    infile, ppnt->p_offset & OFFS_ALIGN);
-#ifndef __ARCH_USE_MMU__
-                               else
-                                 status = MAP_FAILED;
-#endif
-#ifdef _DL_PREAD
-                               if (_dl_mmap_check_error(status) && piclib2map
-                                   && (_DL_PREAD (infile, tryaddr, size,
-                                                  ppnt->p_offset & OFFS_ALIGN)
-                                       == size))
-                                 status = tryaddr;
-#endif
-                               if (_dl_mmap_check_error(status)
-                                   || (tryaddr && tryaddr != status)) {
-                               cant_map:
-                                       _dl_dprintf(2, "%s:%i: can't map 
'%s'\n",
-                                                       _dl_progname, __LINE__, 
libname);
-                                       _dl_internal_error_number = 
LD_ERROR_MMAP_FAILED;
-                                       DL_LOADADDR_UNMAP (lib_loadaddr, maxvma 
- minvma);
-                                       _dl_close(infile);
-                                       _dl_munmap(header, _dl_pagesize);
-                                       return NULL;
-                               }
-
-                               if (! piclib2map) {
-                                 DL_INIT_LOADADDR_HDR
-                                   (lib_loadaddr, status
-                                    + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
-                               }
-                               /* Now we want to allocate and
-                                  zero-out any data from the end of
-                                  the region we mapped in from the
-                                  file (filesz) to the end of the
-                                  loadable segment (memsz).  We may
-                                  need additional pages for memsz,
-                                  that we map in below, and we can
-                                  count on the kernel to zero them
-                                  out, but we have to zero out stuff
-                                  in the last page that we mapped in
-                                  from the file.  However, we can't
-                                  assume to have actually obtained
-                                  full pages from the kernel, since
-                                  we didn't ask for them, and uClibc
-                                  may not give us full pages for
-                                  small allocations.  So only zero
-                                  out up to memsz or the end of the
-                                  page, whichever comes first.  */
-
-                               /* CPNT is the beginning of the memsz
-                                  portion not backed by filesz.  */
-                               cpnt = (char *) (status + size);
-
-                               /* MAP_SIZE is the address of the
-                                  beginning of the next page.  */
-                               map_size = (ppnt->p_vaddr + ppnt->p_filesz
-                                           + ADDR_ALIGN) & PAGE_ALIGN;
-
-#ifndef MIN
-# define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-                               _dl_memset (cpnt, 0,
-                                           MIN (map_size
-                                                - (ppnt->p_vaddr
-                                                   + ppnt->p_filesz),
-                                                ppnt->p_memsz
-                                                - ppnt->p_filesz));
-
-                               if (map_size < ppnt->p_vaddr + ppnt->p_memsz
-                                   && !piclib2map) {
-                                       tryaddr = map_size + (char*)(piclib ? 
libaddr : 0);
-                                       status = (char *) _dl_mmap(tryaddr,
-                                               ppnt->p_vaddr + ppnt->p_memsz - 
map_size,
-                                               LXFLAGS(ppnt->p_flags), flags | 
MAP_ANONYMOUS | MAP_FIXED, -1, 0);
-                                       if (_dl_mmap_check_error(status)
-                                           || tryaddr != status)
-                                               goto cant_map;
-                               }
+                               status = map_writeable (infile, ppnt, piclib, 
flags, libaddr);
+                               if (status == NULL)
+                                       goto CANT_MAP1;
                        } else {
                                tryaddr = (piclib == 2 ? 0
                                           : (char *) (ppnt->p_vaddr & 
PAGE_ALIGN)
@@ -664,11 +651,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int 
secure,
                                            infile, ppnt->p_offset & 
OFFS_ALIGN);
                                if (_dl_mmap_check_error(status)
                                    || (tryaddr && tryaddr != status))
-                                 goto cant_map;
-                               DL_INIT_LOADADDR_HDR
-                                 (lib_loadaddr, status
-                                  + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
+                                 goto CANT_MAP1;
                        }
+                       DL_INIT_LOADADDR_HDR(lib_loadaddr,
+                                            status + (ppnt->p_vaddr & 
ADDR_ALIGN),
+                                            ppnt);
 
                        /* if (libaddr == 0 && piclib) {
                           libaddr = (unsigned long) status;
@@ -677,7 +664,6 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                }
                ppnt++;
        }
-       _dl_close(infile);
 
        /* For a non-PIC library, the addresses are all absolute */
        if (piclib) {
@@ -696,6 +682,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                _dl_dprintf(2, "%s: '%s' is missing a dynamic section\n",
                                _dl_progname, libname);
                _dl_munmap(header, _dl_pagesize);
+               _dl_close(infile);
                return NULL;
        }
 
@@ -711,10 +698,23 @@ struct elf_resolve *_dl_load_elf_shared_library(int 
secure,
                ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
                for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
                        if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) 
{
+#ifdef __ARCH_USE_MMU__
                                _dl_mprotect((void *) ((piclib ? libaddr : 0) +
                                                        (ppnt->p_vaddr & 
PAGE_ALIGN)),
                                                (ppnt->p_vaddr & ADDR_ALIGN) + 
(unsigned long) ppnt->p_filesz,
                                                PROT_READ | PROT_WRITE | 
PROT_EXEC);
+#else
+                               void *new_addr;
+                               new_addr = map_writeable (infile, ppnt, piclib, 
flags, libaddr);
+                               if (!new_addr) {
+                                       _dl_dprintf(_dl_debug_file, "Can't 
modify %s's text section.",
+                                                   libname);
+                                       _dl_exit(1);
+                               }
+                               DL_UPDATE_LOADADDR_HDR(lib_loadaddr,
+                                                      new_addr + 
(ppnt->p_vaddr & ADDR_ALIGN),
+                                                      ppnt);
+#endif
                        }
                }
 #else
@@ -725,6 +725,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 #endif
        }
 
+       _dl_close(infile);
+
        tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,
                        dynamic_addr, 0);
        tpnt->relro_addr = relro_addr;
diff --git a/ldso/ldso/frv/dl-inlines.h b/ldso/ldso/frv/dl-inlines.h
index 95233a7..0395a7e 100644
--- a/ldso/ldso/frv/dl-inlines.h
+++ b/ldso/ldso/frv/dl-inlines.h
@@ -72,14 +72,39 @@ __dl_init_loadaddr_hdr (struct elf32_fdpic_loadaddr 
loadaddr, void *addr,
   segdata->p_memsz = phdr->p_memsz;
 
 #if defined (__SUPPORT_LD_DEBUG__)
-  {
-    extern char *_dl_debug;
-    extern int _dl_debug_file;
-    if (_dl_debug)
-      _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
-                 loadaddr.map->nsegs-1,
-                 segdata->p_vaddr, segdata->addr, segdata->p_memsz);
-  }
+  if (_dl_debug)
+    _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
+               loadaddr.map->nsegs-1,
+               segdata->p_vaddr, segdata->addr, segdata->p_memsz);
+#endif
+}
+
+/* Replace an existing entry in the load map.  */
+static __always_inline void
+__dl_update_loadaddr_hdr (struct elf32_fdpic_loadaddr loadaddr, void *addr,
+                         Elf32_Phdr *phdr)
+{
+  struct elf32_fdpic_loadseg *segdata;
+  void *oldaddr;
+  int i;
+
+  for (i = 0; i < loadaddr.map->nsegs; i++)
+    if (loadaddr.map->segs[i].p_vaddr == phdr->p_vaddr
+       && loadaddr.map->segs[i].p_memsz == phdr->p_memsz)
+      break;
+  if (i == loadaddr.map->nsegs)
+    _dl_exit (-1);
+
+  segdata = loadaddr.map->segs + i;
+  oldaddr = (void *)segdata->addr;
+  _dl_munmap (oldaddr, segdata->p_memsz);
+  segdata->addr = (Elf32_Addr) addr;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+  if (_dl_debug)
+    _dl_dprintf(_dl_debug_file, "%i: changed mapping %x at %x (old %x), size 
%x\n",
+               loadaddr.map->nsegs-1,
+               segdata->p_vaddr, segdata->addr, oldaddr, segdata->p_memsz);
 #endif
 }
 
diff --git a/ldso/ldso/frv/dl-sysdep.h b/ldso/ldso/frv/dl-sysdep.h
index e9c847a..206a662 100644
--- a/ldso/ldso/frv/dl-sysdep.h
+++ b/ldso/ldso/frv/dl-sysdep.h
@@ -95,6 +95,8 @@ struct funcdesc_ht;
 #define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
   (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
                           dl_init_loadaddr_load_count))
+#define DL_UPDATE_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+  (__dl_update_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR)))
 #define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
   (__dl_loadaddr_unmap ((LOADADDR), (NULL)))
 #define DL_LIB_UNMAP(LIB, LEN) \
_______________________________________________
uClibc mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to