1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate * 26*0Sstevel@tonic-gate * dldump(3c) creates a new file image from the specified input file. 27*0Sstevel@tonic-gate */ 28*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #include <sys/param.h> 31*0Sstevel@tonic-gate #include <sys/procfs.h> 32*0Sstevel@tonic-gate #include <fcntl.h> 33*0Sstevel@tonic-gate #include <stdio.h> 34*0Sstevel@tonic-gate #include <libelf.h> 35*0Sstevel@tonic-gate #include <link.h> 36*0Sstevel@tonic-gate #include <dlfcn.h> 37*0Sstevel@tonic-gate #include <stdlib.h> 38*0Sstevel@tonic-gate #include <string.h> 39*0Sstevel@tonic-gate #include <unistd.h> 40*0Sstevel@tonic-gate #include <errno.h> 41*0Sstevel@tonic-gate #include "libld.h" 42*0Sstevel@tonic-gate #include "msg.h" 43*0Sstevel@tonic-gate #include "_librtld.h" 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate /* 46*0Sstevel@tonic-gate * Generic clean up routine 47*0Sstevel@tonic-gate */ 48*0Sstevel@tonic-gate static void 49*0Sstevel@tonic-gate cleanup(Elf *ielf, Elf *oelf, Elf *melf, Cache *icache, Cache *mcache, 50*0Sstevel@tonic-gate int fd, const char *opath) 51*0Sstevel@tonic-gate { 52*0Sstevel@tonic-gate if (icache) { 53*0Sstevel@tonic-gate Cache * _icache = icache; 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate for (++_icache; _icache->c_flags != FLG_C_END; _icache++) { 56*0Sstevel@tonic-gate if (_icache->c_info) 57*0Sstevel@tonic-gate (void) free(_icache->c_info); 58*0Sstevel@tonic-gate } 59*0Sstevel@tonic-gate (void) free((void *)icache); 60*0Sstevel@tonic-gate } 61*0Sstevel@tonic-gate if (mcache) 62*0Sstevel@tonic-gate (void) free((void *)mcache); 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate if (ielf) 65*0Sstevel@tonic-gate (void) elf_end(ielf); 66*0Sstevel@tonic-gate if (oelf) 67*0Sstevel@tonic-gate (void) elf_end(oelf); 68*0Sstevel@tonic-gate if (melf) 69*0Sstevel@tonic-gate (void) elf_end(melf); 70*0Sstevel@tonic-gate if (fd) 71*0Sstevel@tonic-gate (void) close(fd); 72*0Sstevel@tonic-gate if (opath) 73*0Sstevel@tonic-gate (void) unlink(opath); 74*0Sstevel@tonic-gate } 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate /* 77*0Sstevel@tonic-gate * The dldump(3x) interface directs control to the runtime linker. The runtime 78*0Sstevel@tonic-gate * linker brings in librtld.so.1 to provide the underlying support for this 79*0Sstevel@tonic-gate * call (this is because librtld.so.1 requires libelf.so.1, and the whole wad 80*0Sstevel@tonic-gate * is rather expensive to drag around with ld.so.1). 81*0Sstevel@tonic-gate * 82*0Sstevel@tonic-gate * rt_dldump(Rt_map * lmp, const char * opath, int flags, Addr addr) 83*0Sstevel@tonic-gate * 84*0Sstevel@tonic-gate * lmp provides the link-map of the ipath (the input file). 85*0Sstevel@tonic-gate * 86*0Sstevel@tonic-gate * opath specifies the output file. 87*0Sstevel@tonic-gate * 88*0Sstevel@tonic-gate * flags provides a variety of options that control how the new image will be 89*0Sstevel@tonic-gate * relocated (if required). 90*0Sstevel@tonic-gate * 91*0Sstevel@tonic-gate * addr indicates the base address at which the associated input image is mapped 92*0Sstevel@tonic-gate * within the process. 93*0Sstevel@tonic-gate * 94*0Sstevel@tonic-gate * The modes of operation and the various flags provide a number of combinations 95*0Sstevel@tonic-gate * of images that can be created, some are useful, some maybe not. The 96*0Sstevel@tonic-gate * following provide a couple of basic models for dldump(3x) use: 97*0Sstevel@tonic-gate * 98*0Sstevel@tonic-gate * new executable - dldump(0, outfile, RTLD_MEMORY) 99*0Sstevel@tonic-gate * 100*0Sstevel@tonic-gate * A dynamic executable may undergo some initialization 101*0Sstevel@tonic-gate * and the results of this saved in a new file for later 102*0Sstevel@tonic-gate * execution. The executable will presumable update 103*0Sstevel@tonic-gate * parts of its data segment and heap (note that the heap 104*0Sstevel@tonic-gate * should be acquired using malloc() so that it follows 105*0Sstevel@tonic-gate * the end of the data segment for this technique to be 106*0Sstevel@tonic-gate * useful). These updated memory elements are saved to the 107*0Sstevel@tonic-gate * new file, including a new .SUNW_heap section if 108*0Sstevel@tonic-gate * required. 109*0Sstevel@tonic-gate * 110*0Sstevel@tonic-gate * For greatest flexibility, no relocated information 111*0Sstevel@tonic-gate * should be saved (by default any relocated information is 112*0Sstevel@tonic-gate * returned to the value it had in its original file). 113*0Sstevel@tonic-gate * This allows the new image to bind to new dynamic objects 114*0Sstevel@tonic-gate * when executed on the same or newer upgrades of the OS. 115*0Sstevel@tonic-gate * 116*0Sstevel@tonic-gate * Fixing relocations by applying RTLD_REL_ALL will bind 117*0Sstevel@tonic-gate * the image to the dependencies presently mapped as part 118*0Sstevel@tonic-gate * of the process. Thus the new executable will only work 119*0Sstevel@tonic-gate * correctly when these same dependencies map to exactly 120*0Sstevel@tonic-gate * to the same locations. (note that RTLD_REL_RELATIVE will 121*0Sstevel@tonic-gate * have no effect as dynamic executables commonly don't 122*0Sstevel@tonic-gate * contain any relative relocations). 123*0Sstevel@tonic-gate * 124*0Sstevel@tonic-gate * new shared object - dldump(infile, outfile, RTLD_REL_RELATIVE) 125*0Sstevel@tonic-gate * 126*0Sstevel@tonic-gate * A shared object can be fixed to a known address so as 127*0Sstevel@tonic-gate * to reduce its relocation overhead on startup. Because 128*0Sstevel@tonic-gate * the new file is fixed to a new base address (which is 129*0Sstevel@tonic-gate * the address at which the object was found mapped to the 130*0Sstevel@tonic-gate * process) it is now a dynamic executable. 131*0Sstevel@tonic-gate * 132*0Sstevel@tonic-gate * Data changes that have occurred due to the object 133*0Sstevel@tonic-gate * gaining control (at the least this would be .init 134*0Sstevel@tonic-gate * processing) will not be carried over to the new image. 135*0Sstevel@tonic-gate * 136*0Sstevel@tonic-gate * By only performing relative relocations all global 137*0Sstevel@tonic-gate * relocations are available for unique binding to each 138*0Sstevel@tonic-gate * process - thus interposition etc. is still available. 139*0Sstevel@tonic-gate * 140*0Sstevel@tonic-gate * Using RTLD_REL_ALL will fix all relocations in the new 141*0Sstevel@tonic-gate * file, which will certainly provide for faster startup 142*0Sstevel@tonic-gate * of the new image, but at the loss of interposition 143*0Sstevel@tonic-gate * flexibility. 144*0Sstevel@tonic-gate */ 145*0Sstevel@tonic-gate int 146*0Sstevel@tonic-gate rt_dldump(Rt_map *lmp, const char *opath, int flags, Addr addr) 147*0Sstevel@tonic-gate { 148*0Sstevel@tonic-gate Elf * ielf = 0, *oelf = 0, *melf = 0; 149*0Sstevel@tonic-gate Ehdr *iehdr, *oehdr, *mehdr; 150*0Sstevel@tonic-gate Phdr *iphdr, *ophdr, *data_phdr = 0; 151*0Sstevel@tonic-gate Cache *icache = 0, *_icache, *mcache = 0, *_mcache; 152*0Sstevel@tonic-gate Cache *data_cache = 0, *dyn_cache = 0; 153*0Sstevel@tonic-gate Xword rel_null_no = 0, rel_data_no = 0, rel_func_no = 0; 154*0Sstevel@tonic-gate Xword rel_entsize; 155*0Sstevel@tonic-gate Rel *rel_base = 0, *rel_null, *rel_data, *rel_func; 156*0Sstevel@tonic-gate Elf_Scn *scn; 157*0Sstevel@tonic-gate Shdr *shdr; 158*0Sstevel@tonic-gate Elf_Data *data; 159*0Sstevel@tonic-gate Half endx = 1; 160*0Sstevel@tonic-gate int fd = 0, err, num; 161*0Sstevel@tonic-gate size_t shstr_size = 1; 162*0Sstevel@tonic-gate Addr edata; 163*0Sstevel@tonic-gate char *shstr, *_shstr, *ipath = NAME(lmp); 164*0Sstevel@tonic-gate prstatus_t *status = 0, _status; 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate if (lmp == lml_main.lm_head) { 167*0Sstevel@tonic-gate char proc[16]; 168*0Sstevel@tonic-gate int pfd; 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate /* 171*0Sstevel@tonic-gate * Get a /proc descriptor. 172*0Sstevel@tonic-gate */ 173*0Sstevel@tonic-gate (void) snprintf(proc, 16, MSG_ORIG(MSG_FMT_PROC), 174*0Sstevel@tonic-gate (int)getpid()); 175*0Sstevel@tonic-gate if ((pfd = open(proc, O_RDONLY)) == -1) { 176*0Sstevel@tonic-gate err = errno; 177*0Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), proc, 178*0Sstevel@tonic-gate strerror(err)); 179*0Sstevel@tonic-gate return (1); 180*0Sstevel@tonic-gate } 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate /* 183*0Sstevel@tonic-gate * If we've been asked to process the dynamic executable we 184*0Sstevel@tonic-gate * might not know its full path (this is prior to realpath() 185*0Sstevel@tonic-gate * processing becoming default), and thus use /proc to obtain a 186*0Sstevel@tonic-gate * file descriptor of the input file. 187*0Sstevel@tonic-gate */ 188*0Sstevel@tonic-gate if ((fd = ioctl(pfd, PIOCOPENM, (void *)0)) == -1) { 189*0Sstevel@tonic-gate err = errno; 190*0Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_PROC), ipath, 191*0Sstevel@tonic-gate strerror(err)); 192*0Sstevel@tonic-gate (void) close(pfd); 193*0Sstevel@tonic-gate return (1); 194*0Sstevel@tonic-gate } 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate /* 197*0Sstevel@tonic-gate * Obtain the process's status structure from which we can 198*0Sstevel@tonic-gate * determine the size of the process's heap. Note, if the 199*0Sstevel@tonic-gate * application is using mapmalloc then the heap size is going 200*0Sstevel@tonic-gate * to be zero, and if we're dumping a data section that makes 201*0Sstevel@tonic-gate * reference to the malloc'ed area we're not going to get a 202*0Sstevel@tonic-gate * useful image. 203*0Sstevel@tonic-gate */ 204*0Sstevel@tonic-gate if (!(flags & RTLD_NOHEAP)) { 205*0Sstevel@tonic-gate if (ioctl(pfd, PIOCSTATUS, (void *)&_status) == -1) { 206*0Sstevel@tonic-gate err = errno; 207*0Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_PROC), 208*0Sstevel@tonic-gate ipath, strerror(err)); 209*0Sstevel@tonic-gate (void) close(fd); 210*0Sstevel@tonic-gate (void) close(pfd); 211*0Sstevel@tonic-gate return (1); 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate if ((flags & RTLD_MEMORY) && _status.pr_brksize) 214*0Sstevel@tonic-gate status = &_status; 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate (void) close(pfd); 217*0Sstevel@tonic-gate } else { 218*0Sstevel@tonic-gate /* 219*0Sstevel@tonic-gate * Open the specified file. 220*0Sstevel@tonic-gate */ 221*0Sstevel@tonic-gate if ((fd = open(ipath, O_RDONLY, 0)) == -1) { 222*0Sstevel@tonic-gate err = errno; 223*0Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), ipath, 224*0Sstevel@tonic-gate strerror(err)); 225*0Sstevel@tonic-gate return (1); 226*0Sstevel@tonic-gate } 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate /* 230*0Sstevel@tonic-gate * Initialize with the ELF library and make sure this is a suitable 231*0Sstevel@tonic-gate * ELF file we're dealing with. 232*0Sstevel@tonic-gate */ 233*0Sstevel@tonic-gate (void) elf_version(EV_CURRENT); 234*0Sstevel@tonic-gate if ((ielf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 235*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_BEGIN), ipath); 236*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, 0); 237*0Sstevel@tonic-gate return (1); 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate (void) close(fd); 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate if ((elf_kind(ielf) != ELF_K_ELF) || 242*0Sstevel@tonic-gate ((iehdr = elf_getehdr(ielf)) == NULL) || 243*0Sstevel@tonic-gate ((iehdr->e_type != ET_EXEC) && (iehdr->e_type != ET_DYN))) { 244*0Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_IMG_ELF), ipath); 245*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, 0, 0); 246*0Sstevel@tonic-gate return (1); 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate /* 250*0Sstevel@tonic-gate * Make sure we can create the new output file. 251*0Sstevel@tonic-gate */ 252*0Sstevel@tonic-gate if ((fd = open(opath, (O_RDWR | O_CREAT | O_TRUNC), 0777)) == -1) { 253*0Sstevel@tonic-gate err = errno; 254*0Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), opath, 255*0Sstevel@tonic-gate strerror(err)); 256*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, 0, 0); 257*0Sstevel@tonic-gate return (1); 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate if ((oelf = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) { 260*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_BEGIN), opath); 261*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 262*0Sstevel@tonic-gate return (1); 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate /* 266*0Sstevel@tonic-gate * Obtain the input program headers. Remember the last data segments 267*0Sstevel@tonic-gate * program header entry as this will be updated later to reflect any new 268*0Sstevel@tonic-gate * heap section size. 269*0Sstevel@tonic-gate */ 270*0Sstevel@tonic-gate if ((iphdr = elf_getphdr(ielf)) == NULL) { 271*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_GETPHDR), ipath); 272*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 273*0Sstevel@tonic-gate return (1); 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate for (num = 0, ophdr = iphdr; num != iehdr->e_phnum; num++, ophdr++) { 277*0Sstevel@tonic-gate /* 278*0Sstevel@tonic-gate * Save the program header that contains the NOBITS section, or 279*0Sstevel@tonic-gate * the last loadable program header if no NOBITS exists. A 280*0Sstevel@tonic-gate * NOBITS section translates to a memory size requirement that 281*0Sstevel@tonic-gate * is greater than the file data it is mapped from. Note that 282*0Sstevel@tonic-gate * we inspect all headers just incase there only exist text 283*0Sstevel@tonic-gate * segments. 284*0Sstevel@tonic-gate */ 285*0Sstevel@tonic-gate if (ophdr->p_type == PT_LOAD) { 286*0Sstevel@tonic-gate if (ophdr->p_filesz != ophdr->p_memsz) 287*0Sstevel@tonic-gate data_phdr = ophdr; 288*0Sstevel@tonic-gate else if (data_phdr) { 289*0Sstevel@tonic-gate if (data_phdr->p_vaddr < ophdr->p_vaddr) 290*0Sstevel@tonic-gate data_phdr = ophdr; 291*0Sstevel@tonic-gate } else 292*0Sstevel@tonic-gate data_phdr = ophdr; 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate /* 297*0Sstevel@tonic-gate * If there is no data segment, and a heap section is required, 298*0Sstevel@tonic-gate * warn the user and disable the heap addition (Note that you can't 299*0Sstevel@tonic-gate * simply append the heap to the last segment, as it might be a text 300*0Sstevel@tonic-gate * segment, and would therefore have the wrong permissions). 301*0Sstevel@tonic-gate */ 302*0Sstevel@tonic-gate if (status && !data_phdr) { 303*0Sstevel@tonic-gate eprintf(ERR_WARNING, MSG_INTL(MSG_IMG_DATASEG), ipath); 304*0Sstevel@tonic-gate status = 0; 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate /* 308*0Sstevel@tonic-gate * Obtain the input files section header string table. 309*0Sstevel@tonic-gate */ 310*0Sstevel@tonic-gate if ((scn = elf_getscn(ielf, iehdr->e_shstrndx)) == NULL) { 311*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_GETSCN), ipath); 312*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 313*0Sstevel@tonic-gate return (1); 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate if ((data = elf_getdata(scn, NULL)) == NULL) { 316*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_GETDATA), ipath); 317*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 318*0Sstevel@tonic-gate return (1); 319*0Sstevel@tonic-gate } 320*0Sstevel@tonic-gate shstr = (char *)data->d_buf; 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate /* 323*0Sstevel@tonic-gate * Construct a cache to maintain the input files section information. 324*0Sstevel@tonic-gate * Obtain an extra cache element if a heap addition is required. Also 325*0Sstevel@tonic-gate * add an additional entry (marked FLG_C_END) to make the processing of 326*0Sstevel@tonic-gate * this cache easier. 327*0Sstevel@tonic-gate */ 328*0Sstevel@tonic-gate num = iehdr->e_shnum; 329*0Sstevel@tonic-gate if (status) 330*0Sstevel@tonic-gate num++; 331*0Sstevel@tonic-gate if ((icache = malloc((num + 1) * sizeof (Cache))) == 0) { 332*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 333*0Sstevel@tonic-gate return (1); 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate icache[num].c_flags = FLG_C_END; 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate _icache = icache; 338*0Sstevel@tonic-gate _icache++; 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate /* 341*0Sstevel@tonic-gate * Traverse each section from the input file collecting the appropriate 342*0Sstevel@tonic-gate * ELF information. Indicate how the section will be processed to 343*0Sstevel@tonic-gate * generate the output image. 344*0Sstevel@tonic-gate */ 345*0Sstevel@tonic-gate for (scn = 0; scn = elf_nextscn(ielf, scn); _icache++) { 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate if ((_icache->c_shdr = shdr = elf_getshdr(scn)) == NULL) { 348*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDR), ipath); 349*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 350*0Sstevel@tonic-gate return (1); 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate if ((_icache->c_data = elf_getdata(scn, NULL)) == NULL) { 354*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_GETDATA), ipath); 355*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 356*0Sstevel@tonic-gate return (1); 357*0Sstevel@tonic-gate } 358*0Sstevel@tonic-gate _icache->c_name = shstr + (size_t)(shdr->sh_name); 359*0Sstevel@tonic-gate _icache->c_scn = scn; 360*0Sstevel@tonic-gate _icache->c_flags = 0; 361*0Sstevel@tonic-gate _icache->c_info = 0; 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate /* 364*0Sstevel@tonic-gate * If the section has no address it is not part of the mapped 365*0Sstevel@tonic-gate * image, and is unlikely to require any further processing. 366*0Sstevel@tonic-gate * The section header string table will be rewritten (this isn't 367*0Sstevel@tonic-gate * always necessary, it's only really required when relocation 368*0Sstevel@tonic-gate * sections are renamed or sections are stripped, but we do 369*0Sstevel@tonic-gate * things the same way regardless). 370*0Sstevel@tonic-gate */ 371*0Sstevel@tonic-gate if (shdr->sh_addr == 0) { 372*0Sstevel@tonic-gate if ((shdr->sh_type == SHT_STRTAB) && 373*0Sstevel@tonic-gate ((strcmp(_icache->c_name, 374*0Sstevel@tonic-gate MSG_ORIG(MSG_SCN_SHSTR))) == 0)) 375*0Sstevel@tonic-gate _icache->c_flags = FLG_C_SHSTR; 376*0Sstevel@tonic-gate else if (flags & RTLD_STRIP) { 377*0Sstevel@tonic-gate _icache->c_flags = FLG_C_EXCLUDE; 378*0Sstevel@tonic-gate continue; 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate /* 383*0Sstevel@tonic-gate * Skip relocation sections for the time being, they'll be 384*0Sstevel@tonic-gate * analyzed after all sections have been processed. 385*0Sstevel@tonic-gate */ 386*0Sstevel@tonic-gate if ((shdr->sh_type == M_REL_SHT_TYPE) && shdr->sh_addr) 387*0Sstevel@tonic-gate continue; 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gate /* 390*0Sstevel@tonic-gate * Sections at this point will simply be passed through to the 391*0Sstevel@tonic-gate * output file. Keep track of the section header string table 392*0Sstevel@tonic-gate * size. 393*0Sstevel@tonic-gate */ 394*0Sstevel@tonic-gate shstr_size += strlen(_icache->c_name) + 1; 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate /* 397*0Sstevel@tonic-gate * If a heap section is to be added to the output image, 398*0Sstevel@tonic-gate * indicate that it will be added following the last data 399*0Sstevel@tonic-gate * section. 400*0Sstevel@tonic-gate */ 401*0Sstevel@tonic-gate if (shdr->sh_addr && ((shdr->sh_addr + shdr->sh_size) == 402*0Sstevel@tonic-gate (data_phdr->p_vaddr + data_phdr->p_memsz))) { 403*0Sstevel@tonic-gate data_cache = _icache; 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate if (status) { 406*0Sstevel@tonic-gate _icache++; 407*0Sstevel@tonic-gate _icache->c_name = 408*0Sstevel@tonic-gate (char *)MSG_ORIG(MSG_SCN_HEAP); 409*0Sstevel@tonic-gate _icache->c_flags = FLG_C_HEAP; 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate _icache->c_scn = 0; 412*0Sstevel@tonic-gate _icache->c_shdr = 0; 413*0Sstevel@tonic-gate _icache->c_data = 0; 414*0Sstevel@tonic-gate _icache->c_info = 0; 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate shstr_size += strlen(_icache->c_name) + 1; 417*0Sstevel@tonic-gate } 418*0Sstevel@tonic-gate } 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate /* 422*0Sstevel@tonic-gate * Now that we've processed all input sections count the relocation 423*0Sstevel@tonic-gate * entries (relocation sections need to reference their symbol tables). 424*0Sstevel@tonic-gate */ 425*0Sstevel@tonic-gate _icache = icache; 426*0Sstevel@tonic-gate for (_icache++; _icache->c_flags != FLG_C_END; _icache++) { 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate if ((shdr = _icache->c_shdr) == 0) 429*0Sstevel@tonic-gate continue; 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate /* 432*0Sstevel@tonic-gate * If any form of relocations are to be applied to the output 433*0Sstevel@tonic-gate * image determine what relocation counts exist. These will be 434*0Sstevel@tonic-gate * used to reorganize (localize) the relocation records. 435*0Sstevel@tonic-gate */ 436*0Sstevel@tonic-gate if ((shdr->sh_type == M_REL_SHT_TYPE) && shdr->sh_addr) { 437*0Sstevel@tonic-gate rel_entsize = shdr->sh_entsize; 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate if (count_reloc(icache, _icache, lmp, flags, addr, 440*0Sstevel@tonic-gate &rel_null_no, &rel_data_no, &rel_func_no)) { 441*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, 442*0Sstevel@tonic-gate fd, opath); 443*0Sstevel@tonic-gate return (1); 444*0Sstevel@tonic-gate } 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate } 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate /* 449*0Sstevel@tonic-gate * If any form of relocations are to be applied to the output image 450*0Sstevel@tonic-gate * then we will reorganize (localize) the relocation records. If this 451*0Sstevel@tonic-gate * reorganization occurs, the relocation sections will no longer have a 452*0Sstevel@tonic-gate * one-to-one relationship with the section they relocate, hence we 453*0Sstevel@tonic-gate * rename them to a more generic name. 454*0Sstevel@tonic-gate */ 455*0Sstevel@tonic-gate _icache = icache; 456*0Sstevel@tonic-gate for (_icache++; _icache->c_flags != FLG_C_END; _icache++) { 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate if ((shdr = _icache->c_shdr) == 0) 459*0Sstevel@tonic-gate continue; 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate if ((shdr->sh_type == M_REL_SHT_TYPE) && shdr->sh_addr) { 462*0Sstevel@tonic-gate if (rel_null_no) { 463*0Sstevel@tonic-gate _icache->c_flags = FLG_C_RELOC; 464*0Sstevel@tonic-gate _icache->c_name = 465*0Sstevel@tonic-gate (char *)MSG_ORIG(MSG_SCN_RELOC); 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate shstr_size += strlen(_icache->c_name) + 1; 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate /* 473*0Sstevel@tonic-gate * If there is no data section, and a heap is required, warn the user 474*0Sstevel@tonic-gate * and disable the heap addition. 475*0Sstevel@tonic-gate */ 476*0Sstevel@tonic-gate if (!data_cache) { 477*0Sstevel@tonic-gate eprintf(ERR_WARNING, MSG_INTL(MSG_IMG_DATASEC), ipath); 478*0Sstevel@tonic-gate status = 0; 479*0Sstevel@tonic-gate endx = 0; 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate /* 483*0Sstevel@tonic-gate * Determine the value of _edata (which will also be _end) and its 484*0Sstevel@tonic-gate * section index for updating the data segments phdr and symbol table 485*0Sstevel@tonic-gate * information later. If a new heap section is being added, update 486*0Sstevel@tonic-gate * the values appropriately. 487*0Sstevel@tonic-gate */ 488*0Sstevel@tonic-gate edata = data_phdr->p_vaddr + data_phdr->p_memsz; 489*0Sstevel@tonic-gate if (status) 490*0Sstevel@tonic-gate edata += status->pr_brksize; 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate if (endx) { 493*0Sstevel@tonic-gate /* LINTED */ 494*0Sstevel@tonic-gate endx = (Half)elf_ndxscn(data_cache->c_scn); 495*0Sstevel@tonic-gate if (status) 496*0Sstevel@tonic-gate endx++; 497*0Sstevel@tonic-gate } 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate /* 500*0Sstevel@tonic-gate * We're now ready to construct the new elf image. 501*0Sstevel@tonic-gate * 502*0Sstevel@tonic-gate * Obtain a new elf header and initialize it with any basic information 503*0Sstevel@tonic-gate * that isn't calculated as part of elf_update(). 504*0Sstevel@tonic-gate */ 505*0Sstevel@tonic-gate if ((oehdr = elf_newehdr(oelf)) == NULL) { 506*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_NEWEHDR), opath); 507*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 508*0Sstevel@tonic-gate return (1); 509*0Sstevel@tonic-gate } 510*0Sstevel@tonic-gate oehdr->e_machine = iehdr->e_machine; 511*0Sstevel@tonic-gate oehdr->e_flags = iehdr->e_flags; 512*0Sstevel@tonic-gate oehdr->e_type = ET_EXEC; 513*0Sstevel@tonic-gate oehdr->e_entry = iehdr->e_entry; 514*0Sstevel@tonic-gate if (addr) 515*0Sstevel@tonic-gate oehdr->e_entry += addr; 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate /* 518*0Sstevel@tonic-gate * Obtain a new set of program headers. Initialize these with the same 519*0Sstevel@tonic-gate * information as the input program headers. Update the virtual address 520*0Sstevel@tonic-gate * and the data segments size to reflect any new heap section. 521*0Sstevel@tonic-gate */ 522*0Sstevel@tonic-gate if ((ophdr = elf_newphdr(oelf, iehdr->e_phnum)) == NULL) { 523*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_NEWPHDR), opath); 524*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 525*0Sstevel@tonic-gate return (1); 526*0Sstevel@tonic-gate } 527*0Sstevel@tonic-gate for (num = 0; num != iehdr->e_phnum; num++, iphdr++, ophdr++) { 528*0Sstevel@tonic-gate *ophdr = *iphdr; 529*0Sstevel@tonic-gate if ((ophdr->p_type != PT_INTERP) && (ophdr->p_type != PT_NOTE)) 530*0Sstevel@tonic-gate ophdr->p_vaddr += addr; 531*0Sstevel@tonic-gate if (data_phdr == iphdr) { 532*0Sstevel@tonic-gate if (status) 533*0Sstevel@tonic-gate ophdr->p_memsz = edata - ophdr->p_vaddr; 534*0Sstevel@tonic-gate ophdr->p_filesz = ophdr->p_memsz; 535*0Sstevel@tonic-gate } 536*0Sstevel@tonic-gate } 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate /* 539*0Sstevel@tonic-gate * Establish a buffer for the new section header string table. This 540*0Sstevel@tonic-gate * will be filled in as each new section is created. 541*0Sstevel@tonic-gate */ 542*0Sstevel@tonic-gate if ((shstr = malloc(shstr_size)) == 0) { 543*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 544*0Sstevel@tonic-gate return (1); 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate _shstr = shstr; 547*0Sstevel@tonic-gate *_shstr++ = '\0'; 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate /* 550*0Sstevel@tonic-gate * Use the input files cache information to generate new sections. 551*0Sstevel@tonic-gate */ 552*0Sstevel@tonic-gate _icache = icache; 553*0Sstevel@tonic-gate for (_icache++; _icache->c_flags != FLG_C_END; _icache++) { 554*0Sstevel@tonic-gate /* 555*0Sstevel@tonic-gate * Skip any excluded sections. 556*0Sstevel@tonic-gate */ 557*0Sstevel@tonic-gate if (_icache->c_flags == FLG_C_EXCLUDE) 558*0Sstevel@tonic-gate continue; 559*0Sstevel@tonic-gate 560*0Sstevel@tonic-gate /* 561*0Sstevel@tonic-gate * Create a matching section header in the output file. 562*0Sstevel@tonic-gate */ 563*0Sstevel@tonic-gate if ((scn = elf_newscn(oelf)) == NULL) { 564*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_NEWSCN), opath); 565*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 566*0Sstevel@tonic-gate return (1); 567*0Sstevel@tonic-gate } 568*0Sstevel@tonic-gate if ((shdr = elf_getshdr(scn)) == NULL) { 569*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_NEWSHDR), opath); 570*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 571*0Sstevel@tonic-gate return (1); 572*0Sstevel@tonic-gate } 573*0Sstevel@tonic-gate 574*0Sstevel@tonic-gate /* 575*0Sstevel@tonic-gate * If this is the heap section initialize the appropriate 576*0Sstevel@tonic-gate * entries, otherwise simply use the original section header 577*0Sstevel@tonic-gate * information. 578*0Sstevel@tonic-gate */ 579*0Sstevel@tonic-gate if (_icache->c_flags == FLG_C_HEAP) { 580*0Sstevel@tonic-gate shdr->sh_type = SHT_PROGBITS; 581*0Sstevel@tonic-gate shdr->sh_flags = SHF_ALLOC | SHF_WRITE; 582*0Sstevel@tonic-gate } else 583*0Sstevel@tonic-gate *shdr = *_icache->c_shdr; 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate /* 586*0Sstevel@tonic-gate * Create a matching data buffer for this section. 587*0Sstevel@tonic-gate */ 588*0Sstevel@tonic-gate if ((data = elf_newdata(scn)) == NULL) { 589*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_NEWDATA), opath); 590*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 591*0Sstevel@tonic-gate return (1); 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate /* 595*0Sstevel@tonic-gate * Determine what data will be used for this section. 596*0Sstevel@tonic-gate */ 597*0Sstevel@tonic-gate if (_icache->c_flags == FLG_C_SHSTR) { 598*0Sstevel@tonic-gate /* 599*0Sstevel@tonic-gate * Reassign the shstrtab to the new data buffer we're 600*0Sstevel@tonic-gate * creating. Insure that the new elf header references 601*0Sstevel@tonic-gate * this section header table. 602*0Sstevel@tonic-gate */ 603*0Sstevel@tonic-gate *data = *_icache->c_data; 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate data->d_buf = (void *)shstr; 606*0Sstevel@tonic-gate data->d_size = shstr_size; 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate _icache->c_info = shstr; 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate /* LINTED */ 611*0Sstevel@tonic-gate oehdr->e_shstrndx = (Half)elf_ndxscn(scn); 612*0Sstevel@tonic-gate 613*0Sstevel@tonic-gate } else if (_icache->c_flags == FLG_C_HEAP) { 614*0Sstevel@tonic-gate /* 615*0Sstevel@tonic-gate * Assign the heap to the appropriate memory offset. 616*0Sstevel@tonic-gate */ 617*0Sstevel@tonic-gate data->d_buf = status->pr_brkbase; 618*0Sstevel@tonic-gate data->d_type = ELF_T_BYTE; 619*0Sstevel@tonic-gate data->d_size = (size_t)status->pr_brksize; 620*0Sstevel@tonic-gate data->d_off = 0; 621*0Sstevel@tonic-gate data->d_align = 1; 622*0Sstevel@tonic-gate data->d_version = EV_CURRENT; 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate shdr->sh_addr = data_cache->c_shdr->sh_addr + 625*0Sstevel@tonic-gate data_cache->c_shdr->sh_size; 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate } else if (_icache->c_flags == FLG_C_RELOC) { 628*0Sstevel@tonic-gate /* 629*0Sstevel@tonic-gate * If some relocations are to be saved in the new image 630*0Sstevel@tonic-gate * then the relocation sections will be reorganized to 631*0Sstevel@tonic-gate * localize their contents. These relocation sections 632*0Sstevel@tonic-gate * will no longer have a one-to-one relationship with 633*0Sstevel@tonic-gate * the section they relocate, hence we rename them and 634*0Sstevel@tonic-gate * remove their sh_info info. 635*0Sstevel@tonic-gate */ 636*0Sstevel@tonic-gate *data = *_icache->c_data; 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate shdr->sh_info = 0; 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate } else { 641*0Sstevel@tonic-gate /* 642*0Sstevel@tonic-gate * By default simply pass the section through. If 643*0Sstevel@tonic-gate * we've been asked to use the memory image of the 644*0Sstevel@tonic-gate * input file reestablish the data buffer address. 645*0Sstevel@tonic-gate */ 646*0Sstevel@tonic-gate *data = *_icache->c_data; 647*0Sstevel@tonic-gate 648*0Sstevel@tonic-gate if ((shdr->sh_addr) && (flags & RTLD_MEMORY)) 649*0Sstevel@tonic-gate data->d_buf = (void *)(shdr->sh_addr + addr); 650*0Sstevel@tonic-gate 651*0Sstevel@tonic-gate /* 652*0Sstevel@tonic-gate * Update any NOBITS section to indicate that it now 653*0Sstevel@tonic-gate * contains data. If this image is being created 654*0Sstevel@tonic-gate * directly from the input file, zero out the .bss 655*0Sstevel@tonic-gate * section (this saves ld.so.1 having to zero out memory 656*0Sstevel@tonic-gate * or do any /dev/zero mappings). 657*0Sstevel@tonic-gate */ 658*0Sstevel@tonic-gate if (shdr->sh_type == SHT_NOBITS) { 659*0Sstevel@tonic-gate shdr->sh_type = SHT_PROGBITS; 660*0Sstevel@tonic-gate if (!(flags & RTLD_MEMORY)) { 661*0Sstevel@tonic-gate if ((data->d_buf = calloc(1, 662*0Sstevel@tonic-gate data->d_size)) == 0) { 663*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, 664*0Sstevel@tonic-gate icache, mcache, fd, opath); 665*0Sstevel@tonic-gate return (1); 666*0Sstevel@tonic-gate } 667*0Sstevel@tonic-gate } 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate } 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gate /* 672*0Sstevel@tonic-gate * Update the section header string table. 673*0Sstevel@tonic-gate */ 674*0Sstevel@tonic-gate /* LINTED */ 675*0Sstevel@tonic-gate shdr->sh_name = (Word)(_shstr - shstr); 676*0Sstevel@tonic-gate (void) strcpy(_shstr, _icache->c_name); 677*0Sstevel@tonic-gate _shstr = _shstr + strlen(_icache->c_name) + 1; 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate /* 680*0Sstevel@tonic-gate * For each section that has a virtual address update its 681*0Sstevel@tonic-gate * address to the fixed location of the new image. 682*0Sstevel@tonic-gate */ 683*0Sstevel@tonic-gate if (shdr->sh_addr) 684*0Sstevel@tonic-gate shdr->sh_addr += addr; 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate /* 687*0Sstevel@tonic-gate * If we've inserted a new section any later sections may need 688*0Sstevel@tonic-gate * their sh_link fields updated (.stabs comes to mind). 689*0Sstevel@tonic-gate */ 690*0Sstevel@tonic-gate if (status && endx && (shdr->sh_link >= endx)) 691*0Sstevel@tonic-gate shdr->sh_link++; 692*0Sstevel@tonic-gate } 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate /* 695*0Sstevel@tonic-gate * Generate the new image, and obtain a new elf descriptor that will 696*0Sstevel@tonic-gate * allow us to write and update the new image. 697*0Sstevel@tonic-gate */ 698*0Sstevel@tonic-gate if (elf_update(oelf, ELF_C_WRIMAGE) == -1) { 699*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_UPDATE), opath); 700*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 701*0Sstevel@tonic-gate return (1); 702*0Sstevel@tonic-gate } 703*0Sstevel@tonic-gate if ((melf = elf_begin(0, ELF_C_IMAGE, oelf)) == NULL) { 704*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_BEGIN), opath); 705*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 706*0Sstevel@tonic-gate return (1); 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate if ((mehdr = elf_getehdr(melf)) == NULL) { 709*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_GETEHDR), opath); 710*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 711*0Sstevel@tonic-gate return (1); 712*0Sstevel@tonic-gate } 713*0Sstevel@tonic-gate 714*0Sstevel@tonic-gate /* 715*0Sstevel@tonic-gate * Construct a cache to maintain the memory files section information. 716*0Sstevel@tonic-gate */ 717*0Sstevel@tonic-gate if ((mcache = malloc(mehdr->e_shnum * sizeof (Cache))) == 0) { 718*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 719*0Sstevel@tonic-gate return (1); 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate _mcache = mcache; 722*0Sstevel@tonic-gate _mcache++; 723*0Sstevel@tonic-gate 724*0Sstevel@tonic-gate for (scn = 0; scn = elf_nextscn(melf, scn); _mcache++) { 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate if ((_mcache->c_shdr = elf_getshdr(scn)) == NULL) { 727*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_GETSHDR), opath); 728*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 729*0Sstevel@tonic-gate return (1); 730*0Sstevel@tonic-gate } 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate if ((_mcache->c_data = elf_getdata(scn, NULL)) == NULL) { 733*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_GETDATA), opath); 734*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 735*0Sstevel@tonic-gate return (1); 736*0Sstevel@tonic-gate } 737*0Sstevel@tonic-gate } 738*0Sstevel@tonic-gate 739*0Sstevel@tonic-gate /* 740*0Sstevel@tonic-gate * Now that we have a complete description of the new image update any 741*0Sstevel@tonic-gate * sections that are required. 742*0Sstevel@tonic-gate * 743*0Sstevel@tonic-gate * o reset any symbol table entries. 744*0Sstevel@tonic-gate * 745*0Sstevel@tonic-gate * o reset any relocation entries. 746*0Sstevel@tonic-gate * 747*0Sstevel@tonic-gate * o reset dynamic entries. 748*0Sstevel@tonic-gate */ 749*0Sstevel@tonic-gate _mcache = &mcache[0]; 750*0Sstevel@tonic-gate for (_icache = &icache[1]; _icache->c_flags != FLG_C_END; _icache++) { 751*0Sstevel@tonic-gate 752*0Sstevel@tonic-gate if (_icache->c_flags == FLG_C_EXCLUDE) 753*0Sstevel@tonic-gate continue; 754*0Sstevel@tonic-gate 755*0Sstevel@tonic-gate _mcache++; 756*0Sstevel@tonic-gate shdr = _mcache->c_shdr; 757*0Sstevel@tonic-gate 758*0Sstevel@tonic-gate /* 759*0Sstevel@tonic-gate * Update the symbol table entries. _end and _edata will be 760*0Sstevel@tonic-gate * changed to reflect any heap addition. All global symbols 761*0Sstevel@tonic-gate * will be updated to their new fixed address. 762*0Sstevel@tonic-gate */ 763*0Sstevel@tonic-gate if ((shdr->sh_type == SHT_SYMTAB) || 764*0Sstevel@tonic-gate (shdr->sh_type == SHT_DYNSYM)) { 765*0Sstevel@tonic-gate update_sym(mcache, _mcache, edata, endx, addr); 766*0Sstevel@tonic-gate continue; 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gate 769*0Sstevel@tonic-gate /* 770*0Sstevel@tonic-gate * Update any relocations. All relocation requirements will 771*0Sstevel@tonic-gate * have been established in count_reloc(). 772*0Sstevel@tonic-gate */ 773*0Sstevel@tonic-gate if (shdr->sh_type == M_REL_SHT_TYPE) { 774*0Sstevel@tonic-gate if (rel_base == (Rel *)0) { 775*0Sstevel@tonic-gate rel_base = (Rel *)_mcache->c_data->d_buf; 776*0Sstevel@tonic-gate rel_null = rel_base; 777*0Sstevel@tonic-gate rel_data = (Rel *)((Xword)rel_null + 778*0Sstevel@tonic-gate (rel_null_no * rel_entsize)); 779*0Sstevel@tonic-gate rel_func = (Rel *)((Xword)rel_data + 780*0Sstevel@tonic-gate (rel_data_no * rel_entsize)); 781*0Sstevel@tonic-gate } 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate update_reloc(mcache, icache, _icache, opath, lmp, 784*0Sstevel@tonic-gate &rel_null, &rel_data, &rel_func); 785*0Sstevel@tonic-gate continue; 786*0Sstevel@tonic-gate } 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gate /* 789*0Sstevel@tonic-gate * Perform any dynamic entry updates after all relocation 790*0Sstevel@tonic-gate * processing has been carried out (as its possible the .dynamic 791*0Sstevel@tonic-gate * section could occur before the .rel sections, delay this 792*0Sstevel@tonic-gate * processing until last). 793*0Sstevel@tonic-gate */ 794*0Sstevel@tonic-gate if (shdr->sh_type == SHT_DYNAMIC) 795*0Sstevel@tonic-gate dyn_cache = _mcache; 796*0Sstevel@tonic-gate } 797*0Sstevel@tonic-gate 798*0Sstevel@tonic-gate if (dyn_cache) { 799*0Sstevel@tonic-gate Xword off = (Xword)rel_base - (Xword)mehdr; 800*0Sstevel@tonic-gate 801*0Sstevel@tonic-gate /* 802*0Sstevel@tonic-gate * If we're dumping a fixed object (typically the dynamic 803*0Sstevel@tonic-gate * executable) compensate for its real base address. 804*0Sstevel@tonic-gate */ 805*0Sstevel@tonic-gate if (!addr) 806*0Sstevel@tonic-gate off += ADDR(lmp); 807*0Sstevel@tonic-gate 808*0Sstevel@tonic-gate if (update_dynamic(mcache, dyn_cache, lmp, flags, addr, off, 809*0Sstevel@tonic-gate opath, rel_null_no, rel_data_no, rel_func_no, rel_entsize, 810*0Sstevel@tonic-gate elf_checksum(melf))) { 811*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 812*0Sstevel@tonic-gate return (1); 813*0Sstevel@tonic-gate } 814*0Sstevel@tonic-gate } 815*0Sstevel@tonic-gate 816*0Sstevel@tonic-gate /* 817*0Sstevel@tonic-gate * Having completed all section updates write the memory file out. 818*0Sstevel@tonic-gate */ 819*0Sstevel@tonic-gate if (elf_update(oelf, ELF_C_WRITE) == -1) { 820*0Sstevel@tonic-gate eprintf(ERR_ELF, MSG_ORIG(MSG_ELF_UPDATE), opath); 821*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, opath); 822*0Sstevel@tonic-gate return (1); 823*0Sstevel@tonic-gate } 824*0Sstevel@tonic-gate 825*0Sstevel@tonic-gate cleanup(ielf, oelf, melf, icache, mcache, fd, 0); 826*0Sstevel@tonic-gate return (0); 827*0Sstevel@tonic-gate } 828