10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1618Srie * Common Development and Distribution License (the "License"). 6*1618Srie * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 21*1618Srie 220Sstevel@tonic-gate /* 23*1618Srie * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate * 260Sstevel@tonic-gate * dldump(3c) creates a new file image from the specified input file. 270Sstevel@tonic-gate */ 280Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <sys/param.h> 310Sstevel@tonic-gate #include <sys/procfs.h> 320Sstevel@tonic-gate #include <fcntl.h> 330Sstevel@tonic-gate #include <stdio.h> 340Sstevel@tonic-gate #include <libelf.h> 350Sstevel@tonic-gate #include <link.h> 360Sstevel@tonic-gate #include <dlfcn.h> 370Sstevel@tonic-gate #include <stdlib.h> 380Sstevel@tonic-gate #include <string.h> 390Sstevel@tonic-gate #include <unistd.h> 400Sstevel@tonic-gate #include <errno.h> 410Sstevel@tonic-gate #include "libld.h" 420Sstevel@tonic-gate #include "msg.h" 430Sstevel@tonic-gate #include "_librtld.h" 440Sstevel@tonic-gate 450Sstevel@tonic-gate /* 460Sstevel@tonic-gate * Generic clean up routine 470Sstevel@tonic-gate */ 480Sstevel@tonic-gate static void 490Sstevel@tonic-gate cleanup(Elf *ielf, Elf *oelf, Elf *melf, Cache *icache, Cache *mcache, 500Sstevel@tonic-gate int fd, const char *opath) 510Sstevel@tonic-gate { 520Sstevel@tonic-gate if (icache) { 530Sstevel@tonic-gate Cache * _icache = icache; 540Sstevel@tonic-gate 550Sstevel@tonic-gate for (++_icache; _icache->c_flags != FLG_C_END; _icache++) { 560Sstevel@tonic-gate if (_icache->c_info) 570Sstevel@tonic-gate (void) free(_icache->c_info); 580Sstevel@tonic-gate } 590Sstevel@tonic-gate (void) free((void *)icache); 600Sstevel@tonic-gate } 610Sstevel@tonic-gate if (mcache) 620Sstevel@tonic-gate (void) free((void *)mcache); 630Sstevel@tonic-gate 640Sstevel@tonic-gate if (ielf) 650Sstevel@tonic-gate (void) elf_end(ielf); 660Sstevel@tonic-gate if (oelf) 670Sstevel@tonic-gate (void) elf_end(oelf); 680Sstevel@tonic-gate if (melf) 690Sstevel@tonic-gate (void) elf_end(melf); 700Sstevel@tonic-gate if (fd) 710Sstevel@tonic-gate (void) close(fd); 720Sstevel@tonic-gate if (opath) 730Sstevel@tonic-gate (void) unlink(opath); 740Sstevel@tonic-gate } 750Sstevel@tonic-gate 760Sstevel@tonic-gate /* 770Sstevel@tonic-gate * The dldump(3x) interface directs control to the runtime linker. The runtime 780Sstevel@tonic-gate * linker brings in librtld.so.1 to provide the underlying support for this 790Sstevel@tonic-gate * call (this is because librtld.so.1 requires libelf.so.1, and the whole wad 800Sstevel@tonic-gate * is rather expensive to drag around with ld.so.1). 810Sstevel@tonic-gate * 820Sstevel@tonic-gate * rt_dldump(Rt_map * lmp, const char * opath, int flags, Addr addr) 830Sstevel@tonic-gate * 840Sstevel@tonic-gate * lmp provides the link-map of the ipath (the input file). 850Sstevel@tonic-gate * 860Sstevel@tonic-gate * opath specifies the output file. 870Sstevel@tonic-gate * 880Sstevel@tonic-gate * flags provides a variety of options that control how the new image will be 890Sstevel@tonic-gate * relocated (if required). 900Sstevel@tonic-gate * 910Sstevel@tonic-gate * addr indicates the base address at which the associated input image is mapped 920Sstevel@tonic-gate * within the process. 930Sstevel@tonic-gate * 940Sstevel@tonic-gate * The modes of operation and the various flags provide a number of combinations 950Sstevel@tonic-gate * of images that can be created, some are useful, some maybe not. The 960Sstevel@tonic-gate * following provide a couple of basic models for dldump(3x) use: 970Sstevel@tonic-gate * 980Sstevel@tonic-gate * new executable - dldump(0, outfile, RTLD_MEMORY) 990Sstevel@tonic-gate * 1000Sstevel@tonic-gate * A dynamic executable may undergo some initialization 1010Sstevel@tonic-gate * and the results of this saved in a new file for later 1020Sstevel@tonic-gate * execution. The executable will presumable update 1030Sstevel@tonic-gate * parts of its data segment and heap (note that the heap 1040Sstevel@tonic-gate * should be acquired using malloc() so that it follows 1050Sstevel@tonic-gate * the end of the data segment for this technique to be 1060Sstevel@tonic-gate * useful). These updated memory elements are saved to the 1070Sstevel@tonic-gate * new file, including a new .SUNW_heap section if 1080Sstevel@tonic-gate * required. 1090Sstevel@tonic-gate * 1100Sstevel@tonic-gate * For greatest flexibility, no relocated information 1110Sstevel@tonic-gate * should be saved (by default any relocated information is 1120Sstevel@tonic-gate * returned to the value it had in its original file). 1130Sstevel@tonic-gate * This allows the new image to bind to new dynamic objects 1140Sstevel@tonic-gate * when executed on the same or newer upgrades of the OS. 1150Sstevel@tonic-gate * 1160Sstevel@tonic-gate * Fixing relocations by applying RTLD_REL_ALL will bind 1170Sstevel@tonic-gate * the image to the dependencies presently mapped as part 1180Sstevel@tonic-gate * of the process. Thus the new executable will only work 1190Sstevel@tonic-gate * correctly when these same dependencies map to exactly 1200Sstevel@tonic-gate * to the same locations. (note that RTLD_REL_RELATIVE will 1210Sstevel@tonic-gate * have no effect as dynamic executables commonly don't 1220Sstevel@tonic-gate * contain any relative relocations). 1230Sstevel@tonic-gate * 1240Sstevel@tonic-gate * new shared object - dldump(infile, outfile, RTLD_REL_RELATIVE) 1250Sstevel@tonic-gate * 1260Sstevel@tonic-gate * A shared object can be fixed to a known address so as 1270Sstevel@tonic-gate * to reduce its relocation overhead on startup. Because 1280Sstevel@tonic-gate * the new file is fixed to a new base address (which is 1290Sstevel@tonic-gate * the address at which the object was found mapped to the 1300Sstevel@tonic-gate * process) it is now a dynamic executable. 1310Sstevel@tonic-gate * 1320Sstevel@tonic-gate * Data changes that have occurred due to the object 1330Sstevel@tonic-gate * gaining control (at the least this would be .init 1340Sstevel@tonic-gate * processing) will not be carried over to the new image. 1350Sstevel@tonic-gate * 1360Sstevel@tonic-gate * By only performing relative relocations all global 1370Sstevel@tonic-gate * relocations are available for unique binding to each 1380Sstevel@tonic-gate * process - thus interposition etc. is still available. 1390Sstevel@tonic-gate * 1400Sstevel@tonic-gate * Using RTLD_REL_ALL will fix all relocations in the new 1410Sstevel@tonic-gate * file, which will certainly provide for faster startup 1420Sstevel@tonic-gate * of the new image, but at the loss of interposition 1430Sstevel@tonic-gate * flexibility. 1440Sstevel@tonic-gate */ 1450Sstevel@tonic-gate int 1460Sstevel@tonic-gate rt_dldump(Rt_map *lmp, const char *opath, int flags, Addr addr) 1470Sstevel@tonic-gate { 1480Sstevel@tonic-gate Elf * ielf = 0, *oelf = 0, *melf = 0; 1490Sstevel@tonic-gate Ehdr *iehdr, *oehdr, *mehdr; 1500Sstevel@tonic-gate Phdr *iphdr, *ophdr, *data_phdr = 0; 1510Sstevel@tonic-gate Cache *icache = 0, *_icache, *mcache = 0, *_mcache; 1520Sstevel@tonic-gate Cache *data_cache = 0, *dyn_cache = 0; 1530Sstevel@tonic-gate Xword rel_null_no = 0, rel_data_no = 0, rel_func_no = 0; 1540Sstevel@tonic-gate Xword rel_entsize; 1550Sstevel@tonic-gate Rel *rel_base = 0, *rel_null, *rel_data, *rel_func; 1560Sstevel@tonic-gate Elf_Scn *scn; 1570Sstevel@tonic-gate Shdr *shdr; 1580Sstevel@tonic-gate Elf_Data *data; 1590Sstevel@tonic-gate Half endx = 1; 1600Sstevel@tonic-gate int fd = 0, err, num; 1610Sstevel@tonic-gate size_t shstr_size = 1; 1620Sstevel@tonic-gate Addr edata; 1630Sstevel@tonic-gate char *shstr, *_shstr, *ipath = NAME(lmp); 1640Sstevel@tonic-gate prstatus_t *status = 0, _status; 165*1618Srie Lm_list *lml = LIST(lmp); 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate if (lmp == lml_main.lm_head) { 1680Sstevel@tonic-gate char proc[16]; 1690Sstevel@tonic-gate int pfd; 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate /* 1720Sstevel@tonic-gate * Get a /proc descriptor. 1730Sstevel@tonic-gate */ 1740Sstevel@tonic-gate (void) snprintf(proc, 16, MSG_ORIG(MSG_FMT_PROC), 1750Sstevel@tonic-gate (int)getpid()); 1760Sstevel@tonic-gate if ((pfd = open(proc, O_RDONLY)) == -1) { 1770Sstevel@tonic-gate err = errno; 178*1618Srie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), proc, 1790Sstevel@tonic-gate strerror(err)); 1800Sstevel@tonic-gate return (1); 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate /* 1840Sstevel@tonic-gate * If we've been asked to process the dynamic executable we 1850Sstevel@tonic-gate * might not know its full path (this is prior to realpath() 1860Sstevel@tonic-gate * processing becoming default), and thus use /proc to obtain a 1870Sstevel@tonic-gate * file descriptor of the input file. 1880Sstevel@tonic-gate */ 1890Sstevel@tonic-gate if ((fd = ioctl(pfd, PIOCOPENM, (void *)0)) == -1) { 1900Sstevel@tonic-gate err = errno; 191*1618Srie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_PROC), ipath, 1920Sstevel@tonic-gate strerror(err)); 1930Sstevel@tonic-gate (void) close(pfd); 1940Sstevel@tonic-gate return (1); 1950Sstevel@tonic-gate } 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate /* 1980Sstevel@tonic-gate * Obtain the process's status structure from which we can 1990Sstevel@tonic-gate * determine the size of the process's heap. Note, if the 2000Sstevel@tonic-gate * application is using mapmalloc then the heap size is going 2010Sstevel@tonic-gate * to be zero, and if we're dumping a data section that makes 2020Sstevel@tonic-gate * reference to the malloc'ed area we're not going to get a 2030Sstevel@tonic-gate * useful image. 2040Sstevel@tonic-gate */ 2050Sstevel@tonic-gate if (!(flags & RTLD_NOHEAP)) { 2060Sstevel@tonic-gate if (ioctl(pfd, PIOCSTATUS, (void *)&_status) == -1) { 2070Sstevel@tonic-gate err = errno; 208*1618Srie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_PROC), 2090Sstevel@tonic-gate ipath, strerror(err)); 2100Sstevel@tonic-gate (void) close(fd); 2110Sstevel@tonic-gate (void) close(pfd); 2120Sstevel@tonic-gate return (1); 2130Sstevel@tonic-gate } 2140Sstevel@tonic-gate if ((flags & RTLD_MEMORY) && _status.pr_brksize) 2150Sstevel@tonic-gate status = &_status; 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate (void) close(pfd); 2180Sstevel@tonic-gate } else { 2190Sstevel@tonic-gate /* 2200Sstevel@tonic-gate * Open the specified file. 2210Sstevel@tonic-gate */ 2220Sstevel@tonic-gate if ((fd = open(ipath, O_RDONLY, 0)) == -1) { 2230Sstevel@tonic-gate err = errno; 224*1618Srie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), ipath, 2250Sstevel@tonic-gate strerror(err)); 2260Sstevel@tonic-gate return (1); 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate /* 2310Sstevel@tonic-gate * Initialize with the ELF library and make sure this is a suitable 2320Sstevel@tonic-gate * ELF file we're dealing with. 2330Sstevel@tonic-gate */ 2340Sstevel@tonic-gate (void) elf_version(EV_CURRENT); 2350Sstevel@tonic-gate if ((ielf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 236*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_BEGIN), ipath); 2370Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, 0); 2380Sstevel@tonic-gate return (1); 2390Sstevel@tonic-gate } 2400Sstevel@tonic-gate (void) close(fd); 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate if ((elf_kind(ielf) != ELF_K_ELF) || 2430Sstevel@tonic-gate ((iehdr = elf_getehdr(ielf)) == NULL) || 2440Sstevel@tonic-gate ((iehdr->e_type != ET_EXEC) && (iehdr->e_type != ET_DYN))) { 245*1618Srie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_IMG_ELF), ipath); 2460Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, 0, 0); 2470Sstevel@tonic-gate return (1); 2480Sstevel@tonic-gate } 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate /* 2510Sstevel@tonic-gate * Make sure we can create the new output file. 2520Sstevel@tonic-gate */ 2530Sstevel@tonic-gate if ((fd = open(opath, (O_RDWR | O_CREAT | O_TRUNC), 0777)) == -1) { 2540Sstevel@tonic-gate err = errno; 255*1618Srie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), opath, 2560Sstevel@tonic-gate strerror(err)); 2570Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, 0, 0); 2580Sstevel@tonic-gate return (1); 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate if ((oelf = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) { 261*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_BEGIN), opath); 2620Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 2630Sstevel@tonic-gate return (1); 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate /* 2670Sstevel@tonic-gate * Obtain the input program headers. Remember the last data segments 2680Sstevel@tonic-gate * program header entry as this will be updated later to reflect any new 2690Sstevel@tonic-gate * heap section size. 2700Sstevel@tonic-gate */ 2710Sstevel@tonic-gate if ((iphdr = elf_getphdr(ielf)) == NULL) { 272*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETPHDR), ipath); 2730Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 2740Sstevel@tonic-gate return (1); 2750Sstevel@tonic-gate } 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate for (num = 0, ophdr = iphdr; num != iehdr->e_phnum; num++, ophdr++) { 2780Sstevel@tonic-gate /* 2790Sstevel@tonic-gate * Save the program header that contains the NOBITS section, or 2800Sstevel@tonic-gate * the last loadable program header if no NOBITS exists. A 2810Sstevel@tonic-gate * NOBITS section translates to a memory size requirement that 2820Sstevel@tonic-gate * is greater than the file data it is mapped from. Note that 2830Sstevel@tonic-gate * we inspect all headers just incase there only exist text 2840Sstevel@tonic-gate * segments. 2850Sstevel@tonic-gate */ 2860Sstevel@tonic-gate if (ophdr->p_type == PT_LOAD) { 2870Sstevel@tonic-gate if (ophdr->p_filesz != ophdr->p_memsz) 2880Sstevel@tonic-gate data_phdr = ophdr; 2890Sstevel@tonic-gate else if (data_phdr) { 2900Sstevel@tonic-gate if (data_phdr->p_vaddr < ophdr->p_vaddr) 2910Sstevel@tonic-gate data_phdr = ophdr; 2920Sstevel@tonic-gate } else 2930Sstevel@tonic-gate data_phdr = ophdr; 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate /* 2980Sstevel@tonic-gate * If there is no data segment, and a heap section is required, 2990Sstevel@tonic-gate * warn the user and disable the heap addition (Note that you can't 3000Sstevel@tonic-gate * simply append the heap to the last segment, as it might be a text 3010Sstevel@tonic-gate * segment, and would therefore have the wrong permissions). 3020Sstevel@tonic-gate */ 3030Sstevel@tonic-gate if (status && !data_phdr) { 304*1618Srie eprintf(lml, ERR_WARNING, MSG_INTL(MSG_IMG_DATASEG), ipath); 3050Sstevel@tonic-gate status = 0; 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /* 3090Sstevel@tonic-gate * Obtain the input files section header string table. 3100Sstevel@tonic-gate */ 3110Sstevel@tonic-gate if ((scn = elf_getscn(ielf, iehdr->e_shstrndx)) == NULL) { 312*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSCN), ipath); 3130Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 3140Sstevel@tonic-gate return (1); 3150Sstevel@tonic-gate } 3160Sstevel@tonic-gate if ((data = elf_getdata(scn, NULL)) == NULL) { 317*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETDATA), ipath); 3180Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 3190Sstevel@tonic-gate return (1); 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate shstr = (char *)data->d_buf; 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate /* 3240Sstevel@tonic-gate * Construct a cache to maintain the input files section information. 3250Sstevel@tonic-gate * Obtain an extra cache element if a heap addition is required. Also 3260Sstevel@tonic-gate * add an additional entry (marked FLG_C_END) to make the processing of 3270Sstevel@tonic-gate * this cache easier. 3280Sstevel@tonic-gate */ 3290Sstevel@tonic-gate num = iehdr->e_shnum; 3300Sstevel@tonic-gate if (status) 3310Sstevel@tonic-gate num++; 3320Sstevel@tonic-gate if ((icache = malloc((num + 1) * sizeof (Cache))) == 0) { 3330Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 3340Sstevel@tonic-gate return (1); 3350Sstevel@tonic-gate } 3360Sstevel@tonic-gate icache[num].c_flags = FLG_C_END; 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate _icache = icache; 3390Sstevel@tonic-gate _icache++; 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate /* 3420Sstevel@tonic-gate * Traverse each section from the input file collecting the appropriate 3430Sstevel@tonic-gate * ELF information. Indicate how the section will be processed to 3440Sstevel@tonic-gate * generate the output image. 3450Sstevel@tonic-gate */ 3460Sstevel@tonic-gate for (scn = 0; scn = elf_nextscn(ielf, scn); _icache++) { 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate if ((_icache->c_shdr = shdr = elf_getshdr(scn)) == NULL) { 349*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDR), ipath); 3500Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 3510Sstevel@tonic-gate return (1); 3520Sstevel@tonic-gate } 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate if ((_icache->c_data = elf_getdata(scn, NULL)) == NULL) { 355*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETDATA), ipath); 3560Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 3570Sstevel@tonic-gate return (1); 3580Sstevel@tonic-gate } 3590Sstevel@tonic-gate _icache->c_name = shstr + (size_t)(shdr->sh_name); 3600Sstevel@tonic-gate _icache->c_scn = scn; 3610Sstevel@tonic-gate _icache->c_flags = 0; 3620Sstevel@tonic-gate _icache->c_info = 0; 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate /* 3650Sstevel@tonic-gate * If the section has no address it is not part of the mapped 3660Sstevel@tonic-gate * image, and is unlikely to require any further processing. 3670Sstevel@tonic-gate * The section header string table will be rewritten (this isn't 3680Sstevel@tonic-gate * always necessary, it's only really required when relocation 3690Sstevel@tonic-gate * sections are renamed or sections are stripped, but we do 3700Sstevel@tonic-gate * things the same way regardless). 3710Sstevel@tonic-gate */ 3720Sstevel@tonic-gate if (shdr->sh_addr == 0) { 3730Sstevel@tonic-gate if ((shdr->sh_type == SHT_STRTAB) && 3740Sstevel@tonic-gate ((strcmp(_icache->c_name, 3750Sstevel@tonic-gate MSG_ORIG(MSG_SCN_SHSTR))) == 0)) 3760Sstevel@tonic-gate _icache->c_flags = FLG_C_SHSTR; 3770Sstevel@tonic-gate else if (flags & RTLD_STRIP) { 3780Sstevel@tonic-gate _icache->c_flags = FLG_C_EXCLUDE; 3790Sstevel@tonic-gate continue; 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate /* 3840Sstevel@tonic-gate * Skip relocation sections for the time being, they'll be 3850Sstevel@tonic-gate * analyzed after all sections have been processed. 3860Sstevel@tonic-gate */ 3870Sstevel@tonic-gate if ((shdr->sh_type == M_REL_SHT_TYPE) && shdr->sh_addr) 3880Sstevel@tonic-gate continue; 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate /* 3910Sstevel@tonic-gate * Sections at this point will simply be passed through to the 3920Sstevel@tonic-gate * output file. Keep track of the section header string table 3930Sstevel@tonic-gate * size. 3940Sstevel@tonic-gate */ 3950Sstevel@tonic-gate shstr_size += strlen(_icache->c_name) + 1; 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate /* 3980Sstevel@tonic-gate * If a heap section is to be added to the output image, 3990Sstevel@tonic-gate * indicate that it will be added following the last data 4000Sstevel@tonic-gate * section. 4010Sstevel@tonic-gate */ 4020Sstevel@tonic-gate if (shdr->sh_addr && ((shdr->sh_addr + shdr->sh_size) == 4030Sstevel@tonic-gate (data_phdr->p_vaddr + data_phdr->p_memsz))) { 4040Sstevel@tonic-gate data_cache = _icache; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate if (status) { 4070Sstevel@tonic-gate _icache++; 4080Sstevel@tonic-gate _icache->c_name = 4090Sstevel@tonic-gate (char *)MSG_ORIG(MSG_SCN_HEAP); 4100Sstevel@tonic-gate _icache->c_flags = FLG_C_HEAP; 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate _icache->c_scn = 0; 4130Sstevel@tonic-gate _icache->c_shdr = 0; 4140Sstevel@tonic-gate _icache->c_data = 0; 4150Sstevel@tonic-gate _icache->c_info = 0; 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate shstr_size += strlen(_icache->c_name) + 1; 4180Sstevel@tonic-gate } 4190Sstevel@tonic-gate } 4200Sstevel@tonic-gate } 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate /* 4230Sstevel@tonic-gate * Now that we've processed all input sections count the relocation 4240Sstevel@tonic-gate * entries (relocation sections need to reference their symbol tables). 4250Sstevel@tonic-gate */ 4260Sstevel@tonic-gate _icache = icache; 4270Sstevel@tonic-gate for (_icache++; _icache->c_flags != FLG_C_END; _icache++) { 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate if ((shdr = _icache->c_shdr) == 0) 4300Sstevel@tonic-gate continue; 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate /* 4330Sstevel@tonic-gate * If any form of relocations are to be applied to the output 4340Sstevel@tonic-gate * image determine what relocation counts exist. These will be 4350Sstevel@tonic-gate * used to reorganize (localize) the relocation records. 4360Sstevel@tonic-gate */ 4370Sstevel@tonic-gate if ((shdr->sh_type == M_REL_SHT_TYPE) && shdr->sh_addr) { 4380Sstevel@tonic-gate rel_entsize = shdr->sh_entsize; 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate if (count_reloc(icache, _icache, lmp, flags, addr, 4410Sstevel@tonic-gate &rel_null_no, &rel_data_no, &rel_func_no)) { 4420Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, 4430Sstevel@tonic-gate fd, opath); 4440Sstevel@tonic-gate return (1); 4450Sstevel@tonic-gate } 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate /* 4500Sstevel@tonic-gate * If any form of relocations are to be applied to the output image 4510Sstevel@tonic-gate * then we will reorganize (localize) the relocation records. If this 4520Sstevel@tonic-gate * reorganization occurs, the relocation sections will no longer have a 4530Sstevel@tonic-gate * one-to-one relationship with the section they relocate, hence we 4540Sstevel@tonic-gate * rename them to a more generic name. 4550Sstevel@tonic-gate */ 4560Sstevel@tonic-gate _icache = icache; 4570Sstevel@tonic-gate for (_icache++; _icache->c_flags != FLG_C_END; _icache++) { 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate if ((shdr = _icache->c_shdr) == 0) 4600Sstevel@tonic-gate continue; 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate if ((shdr->sh_type == M_REL_SHT_TYPE) && shdr->sh_addr) { 4630Sstevel@tonic-gate if (rel_null_no) { 4640Sstevel@tonic-gate _icache->c_flags = FLG_C_RELOC; 4650Sstevel@tonic-gate _icache->c_name = 4660Sstevel@tonic-gate (char *)MSG_ORIG(MSG_SCN_RELOC); 4670Sstevel@tonic-gate } 4680Sstevel@tonic-gate shstr_size += strlen(_icache->c_name) + 1; 4690Sstevel@tonic-gate } 4700Sstevel@tonic-gate } 4710Sstevel@tonic-gate 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate /* 4740Sstevel@tonic-gate * If there is no data section, and a heap is required, warn the user 4750Sstevel@tonic-gate * and disable the heap addition. 4760Sstevel@tonic-gate */ 4770Sstevel@tonic-gate if (!data_cache) { 478*1618Srie eprintf(lml, ERR_WARNING, MSG_INTL(MSG_IMG_DATASEC), ipath); 4790Sstevel@tonic-gate status = 0; 4800Sstevel@tonic-gate endx = 0; 4810Sstevel@tonic-gate } 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate /* 4840Sstevel@tonic-gate * Determine the value of _edata (which will also be _end) and its 4850Sstevel@tonic-gate * section index for updating the data segments phdr and symbol table 4860Sstevel@tonic-gate * information later. If a new heap section is being added, update 4870Sstevel@tonic-gate * the values appropriately. 4880Sstevel@tonic-gate */ 4890Sstevel@tonic-gate edata = data_phdr->p_vaddr + data_phdr->p_memsz; 4900Sstevel@tonic-gate if (status) 4910Sstevel@tonic-gate edata += status->pr_brksize; 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate if (endx) { 4940Sstevel@tonic-gate /* LINTED */ 4950Sstevel@tonic-gate endx = (Half)elf_ndxscn(data_cache->c_scn); 4960Sstevel@tonic-gate if (status) 4970Sstevel@tonic-gate endx++; 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate /* 5010Sstevel@tonic-gate * We're now ready to construct the new elf image. 5020Sstevel@tonic-gate * 5030Sstevel@tonic-gate * Obtain a new elf header and initialize it with any basic information 5040Sstevel@tonic-gate * that isn't calculated as part of elf_update(). 5050Sstevel@tonic-gate */ 5060Sstevel@tonic-gate if ((oehdr = elf_newehdr(oelf)) == NULL) { 507*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_NEWEHDR), opath); 5080Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 5090Sstevel@tonic-gate return (1); 5100Sstevel@tonic-gate } 5110Sstevel@tonic-gate oehdr->e_machine = iehdr->e_machine; 5120Sstevel@tonic-gate oehdr->e_flags = iehdr->e_flags; 5130Sstevel@tonic-gate oehdr->e_type = ET_EXEC; 5140Sstevel@tonic-gate oehdr->e_entry = iehdr->e_entry; 5150Sstevel@tonic-gate if (addr) 5160Sstevel@tonic-gate oehdr->e_entry += addr; 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate /* 5190Sstevel@tonic-gate * Obtain a new set of program headers. Initialize these with the same 5200Sstevel@tonic-gate * information as the input program headers. Update the virtual address 5210Sstevel@tonic-gate * and the data segments size to reflect any new heap section. 5220Sstevel@tonic-gate */ 5230Sstevel@tonic-gate if ((ophdr = elf_newphdr(oelf, iehdr->e_phnum)) == NULL) { 524*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_NEWPHDR), opath); 5250Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 5260Sstevel@tonic-gate return (1); 5270Sstevel@tonic-gate } 5280Sstevel@tonic-gate for (num = 0; num != iehdr->e_phnum; num++, iphdr++, ophdr++) { 5290Sstevel@tonic-gate *ophdr = *iphdr; 5300Sstevel@tonic-gate if ((ophdr->p_type != PT_INTERP) && (ophdr->p_type != PT_NOTE)) 5310Sstevel@tonic-gate ophdr->p_vaddr += addr; 5320Sstevel@tonic-gate if (data_phdr == iphdr) { 5330Sstevel@tonic-gate if (status) 5340Sstevel@tonic-gate ophdr->p_memsz = edata - ophdr->p_vaddr; 5350Sstevel@tonic-gate ophdr->p_filesz = ophdr->p_memsz; 5360Sstevel@tonic-gate } 5370Sstevel@tonic-gate } 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate /* 5400Sstevel@tonic-gate * Establish a buffer for the new section header string table. This 5410Sstevel@tonic-gate * will be filled in as each new section is created. 5420Sstevel@tonic-gate */ 5430Sstevel@tonic-gate if ((shstr = malloc(shstr_size)) == 0) { 5440Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 5450Sstevel@tonic-gate return (1); 5460Sstevel@tonic-gate } 5470Sstevel@tonic-gate _shstr = shstr; 5480Sstevel@tonic-gate *_shstr++ = '\0'; 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate /* 5510Sstevel@tonic-gate * Use the input files cache information to generate new sections. 5520Sstevel@tonic-gate */ 5530Sstevel@tonic-gate _icache = icache; 5540Sstevel@tonic-gate for (_icache++; _icache->c_flags != FLG_C_END; _icache++) { 5550Sstevel@tonic-gate /* 5560Sstevel@tonic-gate * Skip any excluded sections. 5570Sstevel@tonic-gate */ 5580Sstevel@tonic-gate if (_icache->c_flags == FLG_C_EXCLUDE) 5590Sstevel@tonic-gate continue; 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate /* 5620Sstevel@tonic-gate * Create a matching section header in the output file. 5630Sstevel@tonic-gate */ 5640Sstevel@tonic-gate if ((scn = elf_newscn(oelf)) == NULL) { 565*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_NEWSCN), opath); 5660Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 5670Sstevel@tonic-gate return (1); 5680Sstevel@tonic-gate } 5690Sstevel@tonic-gate if ((shdr = elf_getshdr(scn)) == NULL) { 570*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_NEWSHDR), opath); 5710Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 5720Sstevel@tonic-gate return (1); 5730Sstevel@tonic-gate } 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate /* 5760Sstevel@tonic-gate * If this is the heap section initialize the appropriate 5770Sstevel@tonic-gate * entries, otherwise simply use the original section header 5780Sstevel@tonic-gate * information. 5790Sstevel@tonic-gate */ 5800Sstevel@tonic-gate if (_icache->c_flags == FLG_C_HEAP) { 5810Sstevel@tonic-gate shdr->sh_type = SHT_PROGBITS; 5820Sstevel@tonic-gate shdr->sh_flags = SHF_ALLOC | SHF_WRITE; 5830Sstevel@tonic-gate } else 5840Sstevel@tonic-gate *shdr = *_icache->c_shdr; 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate /* 5870Sstevel@tonic-gate * Create a matching data buffer for this section. 5880Sstevel@tonic-gate */ 5890Sstevel@tonic-gate if ((data = elf_newdata(scn)) == NULL) { 590*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_NEWDATA), opath); 5910Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 5920Sstevel@tonic-gate return (1); 5930Sstevel@tonic-gate } 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate /* 5960Sstevel@tonic-gate * Determine what data will be used for this section. 5970Sstevel@tonic-gate */ 5980Sstevel@tonic-gate if (_icache->c_flags == FLG_C_SHSTR) { 5990Sstevel@tonic-gate /* 6000Sstevel@tonic-gate * Reassign the shstrtab to the new data buffer we're 6010Sstevel@tonic-gate * creating. Insure that the new elf header references 6020Sstevel@tonic-gate * this section header table. 6030Sstevel@tonic-gate */ 6040Sstevel@tonic-gate *data = *_icache->c_data; 6050Sstevel@tonic-gate 6060Sstevel@tonic-gate data->d_buf = (void *)shstr; 6070Sstevel@tonic-gate data->d_size = shstr_size; 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate _icache->c_info = shstr; 6100Sstevel@tonic-gate 6110Sstevel@tonic-gate /* LINTED */ 6120Sstevel@tonic-gate oehdr->e_shstrndx = (Half)elf_ndxscn(scn); 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate } else if (_icache->c_flags == FLG_C_HEAP) { 6150Sstevel@tonic-gate /* 6160Sstevel@tonic-gate * Assign the heap to the appropriate memory offset. 6170Sstevel@tonic-gate */ 6180Sstevel@tonic-gate data->d_buf = status->pr_brkbase; 6190Sstevel@tonic-gate data->d_type = ELF_T_BYTE; 6200Sstevel@tonic-gate data->d_size = (size_t)status->pr_brksize; 6210Sstevel@tonic-gate data->d_off = 0; 6220Sstevel@tonic-gate data->d_align = 1; 6230Sstevel@tonic-gate data->d_version = EV_CURRENT; 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate shdr->sh_addr = data_cache->c_shdr->sh_addr + 6260Sstevel@tonic-gate data_cache->c_shdr->sh_size; 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate } else if (_icache->c_flags == FLG_C_RELOC) { 6290Sstevel@tonic-gate /* 6300Sstevel@tonic-gate * If some relocations are to be saved in the new image 6310Sstevel@tonic-gate * then the relocation sections will be reorganized to 6320Sstevel@tonic-gate * localize their contents. These relocation sections 6330Sstevel@tonic-gate * will no longer have a one-to-one relationship with 6340Sstevel@tonic-gate * the section they relocate, hence we rename them and 6350Sstevel@tonic-gate * remove their sh_info info. 6360Sstevel@tonic-gate */ 6370Sstevel@tonic-gate *data = *_icache->c_data; 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate shdr->sh_info = 0; 6400Sstevel@tonic-gate 6410Sstevel@tonic-gate } else { 6420Sstevel@tonic-gate /* 6430Sstevel@tonic-gate * By default simply pass the section through. If 6440Sstevel@tonic-gate * we've been asked to use the memory image of the 6450Sstevel@tonic-gate * input file reestablish the data buffer address. 6460Sstevel@tonic-gate */ 6470Sstevel@tonic-gate *data = *_icache->c_data; 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate if ((shdr->sh_addr) && (flags & RTLD_MEMORY)) 6500Sstevel@tonic-gate data->d_buf = (void *)(shdr->sh_addr + addr); 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate /* 6530Sstevel@tonic-gate * Update any NOBITS section to indicate that it now 6540Sstevel@tonic-gate * contains data. If this image is being created 6550Sstevel@tonic-gate * directly from the input file, zero out the .bss 6560Sstevel@tonic-gate * section (this saves ld.so.1 having to zero out memory 6570Sstevel@tonic-gate * or do any /dev/zero mappings). 6580Sstevel@tonic-gate */ 6590Sstevel@tonic-gate if (shdr->sh_type == SHT_NOBITS) { 6600Sstevel@tonic-gate shdr->sh_type = SHT_PROGBITS; 6610Sstevel@tonic-gate if (!(flags & RTLD_MEMORY)) { 6620Sstevel@tonic-gate if ((data->d_buf = calloc(1, 6630Sstevel@tonic-gate data->d_size)) == 0) { 6640Sstevel@tonic-gate cleanup(ielf, oelf, melf, 6650Sstevel@tonic-gate icache, mcache, fd, opath); 6660Sstevel@tonic-gate return (1); 6670Sstevel@tonic-gate } 6680Sstevel@tonic-gate } 6690Sstevel@tonic-gate } 6700Sstevel@tonic-gate } 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate /* 6730Sstevel@tonic-gate * Update the section header string table. 6740Sstevel@tonic-gate */ 6750Sstevel@tonic-gate /* LINTED */ 6760Sstevel@tonic-gate shdr->sh_name = (Word)(_shstr - shstr); 6770Sstevel@tonic-gate (void) strcpy(_shstr, _icache->c_name); 6780Sstevel@tonic-gate _shstr = _shstr + strlen(_icache->c_name) + 1; 6790Sstevel@tonic-gate 6800Sstevel@tonic-gate /* 6810Sstevel@tonic-gate * For each section that has a virtual address update its 6820Sstevel@tonic-gate * address to the fixed location of the new image. 6830Sstevel@tonic-gate */ 6840Sstevel@tonic-gate if (shdr->sh_addr) 6850Sstevel@tonic-gate shdr->sh_addr += addr; 6860Sstevel@tonic-gate 6870Sstevel@tonic-gate /* 6880Sstevel@tonic-gate * If we've inserted a new section any later sections may need 6890Sstevel@tonic-gate * their sh_link fields updated (.stabs comes to mind). 6900Sstevel@tonic-gate */ 6910Sstevel@tonic-gate if (status && endx && (shdr->sh_link >= endx)) 6920Sstevel@tonic-gate shdr->sh_link++; 6930Sstevel@tonic-gate } 6940Sstevel@tonic-gate 6950Sstevel@tonic-gate /* 6960Sstevel@tonic-gate * Generate the new image, and obtain a new elf descriptor that will 6970Sstevel@tonic-gate * allow us to write and update the new image. 6980Sstevel@tonic-gate */ 6990Sstevel@tonic-gate if (elf_update(oelf, ELF_C_WRIMAGE) == -1) { 700*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_UPDATE), opath); 7010Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 7020Sstevel@tonic-gate return (1); 7030Sstevel@tonic-gate } 7040Sstevel@tonic-gate if ((melf = elf_begin(0, ELF_C_IMAGE, oelf)) == NULL) { 705*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_BEGIN), opath); 7060Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 7070Sstevel@tonic-gate return (1); 7080Sstevel@tonic-gate } 7090Sstevel@tonic-gate if ((mehdr = elf_getehdr(melf)) == NULL) { 710*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETEHDR), opath); 7110Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 7120Sstevel@tonic-gate return (1); 7130Sstevel@tonic-gate } 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate /* 7160Sstevel@tonic-gate * Construct a cache to maintain the memory files section information. 7170Sstevel@tonic-gate */ 7180Sstevel@tonic-gate if ((mcache = malloc(mehdr->e_shnum * sizeof (Cache))) == 0) { 7190Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 7200Sstevel@tonic-gate return (1); 7210Sstevel@tonic-gate } 7220Sstevel@tonic-gate _mcache = mcache; 7230Sstevel@tonic-gate _mcache++; 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate for (scn = 0; scn = elf_nextscn(melf, scn); _mcache++) { 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate if ((_mcache->c_shdr = elf_getshdr(scn)) == NULL) { 728*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDR), opath); 7290Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 7300Sstevel@tonic-gate return (1); 7310Sstevel@tonic-gate } 7320Sstevel@tonic-gate 7330Sstevel@tonic-gate if ((_mcache->c_data = elf_getdata(scn, NULL)) == NULL) { 734*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_GETDATA), opath); 7350Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 7360Sstevel@tonic-gate return (1); 7370Sstevel@tonic-gate } 7380Sstevel@tonic-gate } 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate /* 7410Sstevel@tonic-gate * Now that we have a complete description of the new image update any 7420Sstevel@tonic-gate * sections that are required. 7430Sstevel@tonic-gate * 7440Sstevel@tonic-gate * o reset any symbol table entries. 7450Sstevel@tonic-gate * 7460Sstevel@tonic-gate * o reset any relocation entries. 7470Sstevel@tonic-gate * 7480Sstevel@tonic-gate * o reset dynamic entries. 7490Sstevel@tonic-gate */ 7500Sstevel@tonic-gate _mcache = &mcache[0]; 7510Sstevel@tonic-gate for (_icache = &icache[1]; _icache->c_flags != FLG_C_END; _icache++) { 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate if (_icache->c_flags == FLG_C_EXCLUDE) 7540Sstevel@tonic-gate continue; 7550Sstevel@tonic-gate 7560Sstevel@tonic-gate _mcache++; 7570Sstevel@tonic-gate shdr = _mcache->c_shdr; 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate /* 7600Sstevel@tonic-gate * Update the symbol table entries. _end and _edata will be 7610Sstevel@tonic-gate * changed to reflect any heap addition. All global symbols 7620Sstevel@tonic-gate * will be updated to their new fixed address. 7630Sstevel@tonic-gate */ 7640Sstevel@tonic-gate if ((shdr->sh_type == SHT_SYMTAB) || 7650Sstevel@tonic-gate (shdr->sh_type == SHT_DYNSYM)) { 7660Sstevel@tonic-gate update_sym(mcache, _mcache, edata, endx, addr); 7670Sstevel@tonic-gate continue; 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate 7700Sstevel@tonic-gate /* 7710Sstevel@tonic-gate * Update any relocations. All relocation requirements will 7720Sstevel@tonic-gate * have been established in count_reloc(). 7730Sstevel@tonic-gate */ 7740Sstevel@tonic-gate if (shdr->sh_type == M_REL_SHT_TYPE) { 7750Sstevel@tonic-gate if (rel_base == (Rel *)0) { 7760Sstevel@tonic-gate rel_base = (Rel *)_mcache->c_data->d_buf; 7770Sstevel@tonic-gate rel_null = rel_base; 7780Sstevel@tonic-gate rel_data = (Rel *)((Xword)rel_null + 7790Sstevel@tonic-gate (rel_null_no * rel_entsize)); 7800Sstevel@tonic-gate rel_func = (Rel *)((Xword)rel_data + 7810Sstevel@tonic-gate (rel_data_no * rel_entsize)); 7820Sstevel@tonic-gate } 7830Sstevel@tonic-gate 7840Sstevel@tonic-gate update_reloc(mcache, icache, _icache, opath, lmp, 7850Sstevel@tonic-gate &rel_null, &rel_data, &rel_func); 7860Sstevel@tonic-gate continue; 7870Sstevel@tonic-gate } 7880Sstevel@tonic-gate 7890Sstevel@tonic-gate /* 7900Sstevel@tonic-gate * Perform any dynamic entry updates after all relocation 7910Sstevel@tonic-gate * processing has been carried out (as its possible the .dynamic 7920Sstevel@tonic-gate * section could occur before the .rel sections, delay this 7930Sstevel@tonic-gate * processing until last). 7940Sstevel@tonic-gate */ 7950Sstevel@tonic-gate if (shdr->sh_type == SHT_DYNAMIC) 7960Sstevel@tonic-gate dyn_cache = _mcache; 7970Sstevel@tonic-gate } 7980Sstevel@tonic-gate 7990Sstevel@tonic-gate if (dyn_cache) { 8000Sstevel@tonic-gate Xword off = (Xword)rel_base - (Xword)mehdr; 8010Sstevel@tonic-gate 8020Sstevel@tonic-gate /* 8030Sstevel@tonic-gate * If we're dumping a fixed object (typically the dynamic 8040Sstevel@tonic-gate * executable) compensate for its real base address. 8050Sstevel@tonic-gate */ 8060Sstevel@tonic-gate if (!addr) 8070Sstevel@tonic-gate off += ADDR(lmp); 8080Sstevel@tonic-gate 8090Sstevel@tonic-gate if (update_dynamic(mcache, dyn_cache, lmp, flags, addr, off, 8100Sstevel@tonic-gate opath, rel_null_no, rel_data_no, rel_func_no, rel_entsize, 8110Sstevel@tonic-gate elf_checksum(melf))) { 8120Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 8130Sstevel@tonic-gate return (1); 8140Sstevel@tonic-gate } 8150Sstevel@tonic-gate } 8160Sstevel@tonic-gate 8170Sstevel@tonic-gate /* 8180Sstevel@tonic-gate * Having completed all section updates write the memory file out. 8190Sstevel@tonic-gate */ 8200Sstevel@tonic-gate if (elf_update(oelf, ELF_C_WRITE) == -1) { 821*1618Srie eprintf(lml, ERR_ELF, MSG_ORIG(MSG_ELF_UPDATE), opath); 8220Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 8230Sstevel@tonic-gate return (1); 8240Sstevel@tonic-gate } 8250Sstevel@tonic-gate 8260Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, 0); 8270Sstevel@tonic-gate return (0); 8280Sstevel@tonic-gate } 829