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


   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  *
  26  * dldump(3c) creates a new file image from the specified input file.
  27  */
  28 #pragma ident   "%Z%%M% %I%     %E% SMI"
  29 
  30 #include        <sys/param.h>
  31 #include        <sys/procfs.h>
  32 #include        <fcntl.h>
  33 #include        <stdio.h>
  34 #include        <libelf.h>
  35 #include        <link.h>
  36 #include        <dlfcn.h>
  37 #include        <stdlib.h>
  38 #include        <string.h>
  39 #include        <unistd.h>
  40 #include        <errno.h>
  41 #include        "libld.h"
  42 #include        "msg.h"
  43 #include        "_librtld.h"
  44 
  45 /*
  46  * Generic clean up routine
  47  */
  48 static void


 141  *                      file, which will certainly provide for faster startup
 142  *                      of the new image, but at the loss of interposition
 143  *                      flexibility.
 144  */
 145 int
 146 rt_dldump(Rt_map *lmp, const char *opath, int flags, Addr addr)
 147 {
 148         Elf *           ielf = 0, *oelf = 0, *melf = 0;
 149         Ehdr            *iehdr, *oehdr, *mehdr;
 150         Phdr            *iphdr, *ophdr, *data_phdr = 0;
 151         Cache           *icache = 0, *_icache, *mcache = 0, *_mcache;
 152         Cache           *data_cache = 0, *dyn_cache = 0;
 153         Xword           rel_null_no = 0, rel_data_no = 0, rel_func_no = 0;
 154         Xword           rel_entsize;
 155         Rel             *rel_base = 0, *rel_null, *rel_data, *rel_func;
 156         Elf_Scn         *scn;
 157         Shdr            *shdr;
 158         Elf_Data        *data;
 159         Half            endx = 1;
 160         int             fd = 0, err, num;
 161         size_t          shstr_size = 1;
 162         Addr            edata;
 163         char            *shstr, *_shstr, *ipath = NAME(lmp);
 164         prstatus_t      *status = 0, _status;
 165         Lm_list         *lml = LIST(lmp);
 166         Alist           *nodirect = 0;
 167 
 168         if (lmp == lml_main.lm_head) {
 169                 char    proc[16];
 170                 int     pfd;
 171 
 172                 /*
 173                  * Get a /proc descriptor.
 174                  */
 175                 (void) snprintf(proc, 16, MSG_ORIG(MSG_FMT_PROC),
 176                     (int)getpid());
 177                 if ((pfd = open(proc, O_RDONLY)) == -1) {
 178                         err = errno;
 179                         eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), proc,
 180                             strerror(err));
 181                         return (1);


 292                                         data_phdr = ophdr;
 293                         } else
 294                                 data_phdr = ophdr;
 295                 }
 296         }
 297 
 298         /*
 299          * If there is no data segment, and a heap section is required,
 300          * warn the user and disable the heap addition (Note that you can't
 301          * simply append the heap to the last segment, as it might be a text
 302          * segment, and would therefore have the wrong permissions).
 303          */
 304         if (status && !data_phdr) {
 305                 eprintf(lml, ERR_WARNING, MSG_INTL(MSG_IMG_DATASEG), ipath);
 306                 status = 0;
 307         }
 308 
 309         /*
 310          * Obtain the input files section header string table.
 311          */
 312         if ((scn = elf_getscn(ielf, iehdr->e_shstrndx)) == NULL) {






 313                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSCN), ipath);
 314                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 315                 return (1);
 316         }
 317         if ((data = elf_getdata(scn, NULL)) == NULL) {
 318                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETDATA), ipath);
 319                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 320                 return (1);
 321         }
 322         shstr = (char *)data->d_buf;
 323 
 324         /*
 325          * Construct a cache to maintain the input files section information.
 326          * Obtain an extra cache element if a heap addition is required.  Also
 327          * add an additional entry (marked FLG_C_END) to make the processing of
 328          * this cache easier.
 329          */
 330         num = iehdr->e_shnum;








 331         if (status)
 332                 num++;
 333         if ((icache = malloc((num + 1) * sizeof (Cache))) == 0) {
 334                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 335                 return (1);
 336         }
 337         icache[num].c_flags = FLG_C_END;
 338 
 339         _icache = icache;
 340         _icache++;
 341 
 342         /*
 343          * Traverse each section from the input file collecting the appropriate
 344          * ELF information.  Indicate how the section will be processed to
 345          * generate the output image.
 346          */
 347         for (scn = 0; scn = elf_nextscn(ielf, scn); _icache++) {
 348 
 349                 if ((_icache->c_shdr = shdr = elf_getshdr(scn)) == NULL) {
 350                         eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDR), ipath);


 607                         return (1);
 608                 }
 609 
 610                 /*
 611                  * Determine what data will be used for this section.
 612                  */
 613                 if (_icache->c_flags == FLG_C_SHSTR) {
 614                         /*
 615                          * Reassign the shstrtab to the new data buffer we're
 616                          * creating.  Insure that the new elf header references
 617                          * this section header table.
 618                          */
 619                         *data = *_icache->c_data;
 620 
 621                         data->d_buf = (void *)shstr;
 622                         data->d_size = shstr_size;
 623 
 624                         _icache->c_info = shstr;
 625 
 626                         /* LINTED */



















 627                         oehdr->e_shstrndx = (Half)elf_ndxscn(scn);

 628 
 629                 } else if (_icache->c_flags == FLG_C_HEAP) {
 630                         /*
 631                          * Assign the heap to the appropriate memory offset.
 632                          */
 633                         data->d_buf = status->pr_brkbase;
 634                         data->d_type = ELF_T_BYTE;
 635                         data->d_size = (size_t)status->pr_brksize;
 636                         data->d_off = 0;
 637                         data->d_align = 1;
 638                         data->d_version = EV_CURRENT;
 639 
 640                         shdr->sh_addr = data_cache->c_shdr->sh_addr +
 641                             data_cache->c_shdr->sh_size;
 642 
 643                 } else if (_icache->c_flags == FLG_C_RELOC) {
 644                         /*
 645                          * If some relocations are to be saved in the new image
 646                          * then the relocation sections will be reorganized to
 647                          * localize their contents.  These relocation sections


 710         /*
 711          * Generate the new image, and obtain a new elf descriptor that will
 712          * allow us to write and update the new image.
 713          */
 714         if (elf_update(oelf, ELF_C_WRIMAGE) == -1) {
 715                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_UPDATE), opath);
 716                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 717                 return (1);
 718         }
 719         if ((melf = elf_begin(0, ELF_C_IMAGE, oelf)) == NULL) {
 720                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_BEGIN), opath);
 721                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 722                 return (1);
 723         }
 724         if ((mehdr = elf_getehdr(melf)) == NULL) {
 725                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETEHDR), opath);
 726                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 727                 return (1);
 728         }
 729 






 730         /*
 731          * Construct a cache to maintain the memory files section information.
 732          */
 733         if ((mcache = malloc(mehdr->e_shnum * sizeof (Cache))) == 0) {
 734                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 735                 return (1);
 736         }
 737         _mcache = mcache;
 738         _mcache++;
 739 
 740         for (scn = 0; scn = elf_nextscn(melf, scn); _mcache++) {
 741 
 742                 if ((_mcache->c_shdr = elf_getshdr(scn)) == NULL) {
 743                         eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDR), opath);
 744                         cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 745                         return (1);
 746                 }
 747 
 748                 if ((_mcache->c_data = elf_getdata(scn, NULL)) == NULL) {
 749                         eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETDATA), opath);
 750                         cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 751                         return (1);
 752                 }
 753         }




   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  *
  26  * dldump(3c) creates a new file image from the specified input file.
  27  */

  28 
  29 #include        <sys/param.h>
  30 #include        <sys/procfs.h>
  31 #include        <fcntl.h>
  32 #include        <stdio.h>
  33 #include        <libelf.h>
  34 #include        <link.h>
  35 #include        <dlfcn.h>
  36 #include        <stdlib.h>
  37 #include        <string.h>
  38 #include        <unistd.h>
  39 #include        <errno.h>
  40 #include        "libld.h"
  41 #include        "msg.h"
  42 #include        "_librtld.h"
  43 
  44 /*
  45  * Generic clean up routine
  46  */
  47 static void


 140  *                      file, which will certainly provide for faster startup
 141  *                      of the new image, but at the loss of interposition
 142  *                      flexibility.
 143  */
 144 int
 145 rt_dldump(Rt_map *lmp, const char *opath, int flags, Addr addr)
 146 {
 147         Elf *           ielf = 0, *oelf = 0, *melf = 0;
 148         Ehdr            *iehdr, *oehdr, *mehdr;
 149         Phdr            *iphdr, *ophdr, *data_phdr = 0;
 150         Cache           *icache = 0, *_icache, *mcache = 0, *_mcache;
 151         Cache           *data_cache = 0, *dyn_cache = 0;
 152         Xword           rel_null_no = 0, rel_data_no = 0, rel_func_no = 0;
 153         Xword           rel_entsize;
 154         Rel             *rel_base = 0, *rel_null, *rel_data, *rel_func;
 155         Elf_Scn         *scn;
 156         Shdr            *shdr;
 157         Elf_Data        *data;
 158         Half            endx = 1;
 159         int             fd = 0, err, num;
 160         size_t          shstr_size = 1, shndx;
 161         Addr            edata;
 162         char            *shstr, *_shstr, *ipath = NAME(lmp);
 163         prstatus_t      *status = 0, _status;
 164         Lm_list         *lml = LIST(lmp);
 165         Alist           *nodirect = 0;
 166 
 167         if (lmp == lml_main.lm_head) {
 168                 char    proc[16];
 169                 int     pfd;
 170 
 171                 /*
 172                  * Get a /proc descriptor.
 173                  */
 174                 (void) snprintf(proc, 16, MSG_ORIG(MSG_FMT_PROC),
 175                     (int)getpid());
 176                 if ((pfd = open(proc, O_RDONLY)) == -1) {
 177                         err = errno;
 178                         eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), proc,
 179                             strerror(err));
 180                         return (1);


 291                                         data_phdr = ophdr;
 292                         } else
 293                                 data_phdr = ophdr;
 294                 }
 295         }
 296 
 297         /*
 298          * If there is no data segment, and a heap section is required,
 299          * warn the user and disable the heap addition (Note that you can't
 300          * simply append the heap to the last segment, as it might be a text
 301          * segment, and would therefore have the wrong permissions).
 302          */
 303         if (status && !data_phdr) {
 304                 eprintf(lml, ERR_WARNING, MSG_INTL(MSG_IMG_DATASEG), ipath);
 305                 status = 0;
 306         }
 307 
 308         /*
 309          * Obtain the input files section header string table.
 310          */
 311 
 312         if (elf_getshdrstrndx(ielf, &shndx) == -1) {
 313                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDRSTRNDX), ipath);
 314                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 315                 return (1);
 316         }
 317         if ((scn = elf_getscn(ielf, shndx)) == NULL) {
 318                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSCN), ipath);
 319                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 320                 return (1);
 321         }
 322         if ((data = elf_getdata(scn, NULL)) == NULL) {
 323                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETDATA), ipath);
 324                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 325                 return (1);
 326         }
 327         shstr = (char *)data->d_buf;
 328 
 329         /*
 330          * Construct a cache to maintain the input files section information.
 331          * Obtain an extra cache element if a heap addition is required.  Also
 332          * add an additional entry (marked FLG_C_END) to make the processing of
 333          * this cache easier.
 334          */
 335 
 336         if (elf_getshdrnum(ielf, &shndx) == -1) {
 337                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDRNUM), opath);
 338                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 339                 return (1);
 340         }
 341 
 342         num = shndx;
 343 
 344         if (status)
 345                 num++;
 346         if ((icache = malloc((num + 1) * sizeof (Cache))) == 0) {
 347                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 348                 return (1);
 349         }
 350         icache[num].c_flags = FLG_C_END;
 351 
 352         _icache = icache;
 353         _icache++;
 354 
 355         /*
 356          * Traverse each section from the input file collecting the appropriate
 357          * ELF information.  Indicate how the section will be processed to
 358          * generate the output image.
 359          */
 360         for (scn = 0; scn = elf_nextscn(ielf, scn); _icache++) {
 361 
 362                 if ((_icache->c_shdr = shdr = elf_getshdr(scn)) == NULL) {
 363                         eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDR), ipath);


 620                         return (1);
 621                 }
 622 
 623                 /*
 624                  * Determine what data will be used for this section.
 625                  */
 626                 if (_icache->c_flags == FLG_C_SHSTR) {
 627                         /*
 628                          * Reassign the shstrtab to the new data buffer we're
 629                          * creating.  Insure that the new elf header references
 630                          * this section header table.
 631                          */
 632                         *data = *_icache->c_data;
 633 
 634                         data->d_buf = (void *)shstr;
 635                         data->d_size = shstr_size;
 636 
 637                         _icache->c_info = shstr;
 638 
 639                         /* LINTED */
 640                         if (elf_ndxscn(scn) >= SHN_LORESERVE) {
 641                                 Elf_Scn *_scn;
 642                                 Shdr    *shdr0;
 643 
 644                                 /*
 645                                  * libelf deals with e_shnum for us, but we
 646                                  * need to deal with e_shstrndx ourselves.
 647                                  */
 648                                 oehdr->e_shstrndx = SHN_XINDEX;
 649                                 if ((_scn = elf_getscn(oelf, 0)) == NULL) {
 650                                         eprintf(lml, ERR_ELF,
 651                                             MSG_ORIG(MSG_ELF_GETSCN), opath);
 652                                         cleanup(ielf, oelf, melf, icache,
 653                                             mcache, fd, opath);
 654                                         return (1);
 655                                 }
 656                                 shdr0 = elf_getshdr(_scn);
 657                                 shdr0->sh_link = elf_ndxscn(scn);
 658                         } else {
 659                                 oehdr->e_shstrndx = (Half)elf_ndxscn(scn);
 660                         }
 661 
 662                 } else if (_icache->c_flags == FLG_C_HEAP) {
 663                         /*
 664                          * Assign the heap to the appropriate memory offset.
 665                          */
 666                         data->d_buf = status->pr_brkbase;
 667                         data->d_type = ELF_T_BYTE;
 668                         data->d_size = (size_t)status->pr_brksize;
 669                         data->d_off = 0;
 670                         data->d_align = 1;
 671                         data->d_version = EV_CURRENT;
 672 
 673                         shdr->sh_addr = data_cache->c_shdr->sh_addr +
 674                             data_cache->c_shdr->sh_size;
 675 
 676                 } else if (_icache->c_flags == FLG_C_RELOC) {
 677                         /*
 678                          * If some relocations are to be saved in the new image
 679                          * then the relocation sections will be reorganized to
 680                          * localize their contents.  These relocation sections


 743         /*
 744          * Generate the new image, and obtain a new elf descriptor that will
 745          * allow us to write and update the new image.
 746          */
 747         if (elf_update(oelf, ELF_C_WRIMAGE) == -1) {
 748                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_UPDATE), opath);
 749                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 750                 return (1);
 751         }
 752         if ((melf = elf_begin(0, ELF_C_IMAGE, oelf)) == NULL) {
 753                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_BEGIN), opath);
 754                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 755                 return (1);
 756         }
 757         if ((mehdr = elf_getehdr(melf)) == NULL) {
 758                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETEHDR), opath);
 759                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 760                 return (1);
 761         }
 762 
 763         if (elf_getshdrnum(melf, &shndx) == -1) {
 764                 eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDRNUM), opath);
 765                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 766                 return (1);
 767         }
 768 
 769         /*
 770          * Construct a cache to maintain the memory files section information.
 771          */
 772         if ((mcache = malloc(shndx * sizeof (Cache))) == 0) {
 773                 cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 774                 return (1);
 775         }
 776         _mcache = mcache;
 777         _mcache++;
 778 
 779         for (scn = 0; scn = elf_nextscn(melf, scn); _mcache++) {
 780 
 781                 if ((_mcache->c_shdr = elf_getshdr(scn)) == NULL) {
 782                         eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDR), opath);
 783                         cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 784                         return (1);
 785                 }
 786 
 787                 if ((_mcache->c_data = elf_getdata(scn, NULL)) == NULL) {
 788                         eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETDATA), opath);
 789                         cleanup(ielf, oelf, melf, icache, mcache, fd, opath);
 790                         return (1);
 791                 }
 792         }