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 }
|