Print this page
4003 dldump() can't deal with extended sections

@@ -23,11 +23,10 @@
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
  * dldump(3c) creates a new file image from the specified input file.
  */
-#pragma ident   "%Z%%M% %I%     %E% SMI"
 
 #include        <sys/param.h>
 #include        <sys/procfs.h>
 #include        <fcntl.h>
 #include        <stdio.h>

@@ -156,11 +155,11 @@
         Elf_Scn         *scn;
         Shdr            *shdr;
         Elf_Data        *data;
         Half            endx = 1;
         int             fd = 0, err, num;
-        size_t          shstr_size = 1;
+        size_t          shstr_size = 1, shndx;
         Addr            edata;
         char            *shstr, *_shstr, *ipath = NAME(lmp);
         prstatus_t      *status = 0, _status;
         Lm_list         *lml = LIST(lmp);
         Alist           *nodirect = 0;

@@ -307,11 +306,17 @@
         }
 
         /*
          * Obtain the input files section header string table.
          */
-        if ((scn = elf_getscn(ielf, iehdr->e_shstrndx)) == NULL) {
+
+        if (elf_getshdrstrndx(ielf, &shndx) == -1) {
+                eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDRSTRNDX), ipath);
+                cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
+                return (1);
+        }
+        if ((scn = elf_getscn(ielf, shndx)) == NULL) {
                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSCN), ipath);
                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
                 return (1);
         }
         if ((data = elf_getdata(scn, NULL)) == NULL) {

@@ -325,11 +330,19 @@
          * Construct a cache to maintain the input files section information.
          * Obtain an extra cache element if a heap addition is required.  Also
          * add an additional entry (marked FLG_C_END) to make the processing of
          * this cache easier.
          */
-        num = iehdr->e_shnum;
+
+        if (elf_getshdrnum(ielf, &shndx) == -1) {
+                eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDRNUM), opath);
+                cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
+                return (1);
+        }
+
+        num = shndx;
+
         if (status)
                 num++;
         if ((icache = malloc((num + 1) * sizeof (Cache))) == 0) {
                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
                 return (1);

@@ -622,11 +635,31 @@
                         data->d_size = shstr_size;
 
                         _icache->c_info = shstr;
 
                         /* LINTED */
+                        if (elf_ndxscn(scn) >= SHN_LORESERVE) {
+                                Elf_Scn *_scn;
+                                Shdr    *shdr0;
+
+                                /*
+                                 * libelf deals with e_shnum for us, but we
+                                 * need to deal with e_shstrndx ourselves.
+                                 */
+                                oehdr->e_shstrndx = SHN_XINDEX;
+                                if ((_scn = elf_getscn(oelf, 0)) == NULL) {
+                                        eprintf(lml, ERR_ELF,
+                                            MSG_ORIG(MSG_ELF_GETSCN), opath);
+                                        cleanup(ielf, oelf, melf, icache,
+                                            mcache, fd, opath);
+                                        return (1);
+                                }
+                                shdr0 = elf_getshdr(_scn);
+                                shdr0->sh_link = elf_ndxscn(scn);
+                        } else {
                         oehdr->e_shstrndx = (Half)elf_ndxscn(scn);
+                        }
 
                 } else if (_icache->c_flags == FLG_C_HEAP) {
                         /*
                          * Assign the heap to the appropriate memory offset.
                          */

@@ -725,14 +758,20 @@
                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETEHDR), opath);
                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
                 return (1);
         }
 
+        if (elf_getshdrnum(melf, &shndx) == -1) {
+                eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDRNUM), opath);
+                cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
+                return (1);
+        }
+
         /*
          * Construct a cache to maintain the memory files section information.
          */
-        if ((mcache = malloc(mehdr->e_shnum * sizeof (Cache))) == 0) {
+        if ((mcache = malloc(shndx * sizeof (Cache))) == 0) {
                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
                 return (1);
         }
         _mcache = mcache;
         _mcache++;