17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 23*2020b2b6SRod Evans * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257257d1b4Sraf 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Object file dependent suport for ELF objects. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <sys/mman.h> 317c478bd9Sstevel@tonic-gate #include <stdio.h> 327c478bd9Sstevel@tonic-gate #include <unistd.h> 337c478bd9Sstevel@tonic-gate #include <libelf.h> 347c478bd9Sstevel@tonic-gate #include <string.h> 357c478bd9Sstevel@tonic-gate #include <dlfcn.h> 365aefb655Srie #include <debug.h> 375aefb655Srie #include <libld.h> 387c478bd9Sstevel@tonic-gate #include "_rtld.h" 397c478bd9Sstevel@tonic-gate #include "_audit.h" 407c478bd9Sstevel@tonic-gate #include "_elf.h" 417c478bd9Sstevel@tonic-gate 4256deab07SRod Evans static Rt_map *olmp = NULL; 4356deab07SRod Evans static Alist *mpalp = NULL; 447c478bd9Sstevel@tonic-gate 455aefb655Srie static Ehdr dehdr = { { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, 465aefb655Srie M_CLASS, M_DATA }, 0, M_MACH, EV_CURRENT }; 475aefb655Srie 487c478bd9Sstevel@tonic-gate /* 497c478bd9Sstevel@tonic-gate * Process a relocatable object. The static object link map pointer is used as 507c478bd9Sstevel@tonic-gate * a flag to determine whether a concatenation is already in progress (ie. an 517c478bd9Sstevel@tonic-gate * LD_PRELOAD may specify a list of objects). The link map returned simply 527c478bd9Sstevel@tonic-gate * specifies an `object' flag which the caller can interpret and thus call 537c478bd9Sstevel@tonic-gate * elf_obj_fini() to complete the concatenation. 547c478bd9Sstevel@tonic-gate */ 557c478bd9Sstevel@tonic-gate static Rt_map * 5656deab07SRod Evans elf_obj_init(Lm_list *lml, Aliste lmco, const char *oname) 577c478bd9Sstevel@tonic-gate { 587c478bd9Sstevel@tonic-gate Ofl_desc *ofl; 5956deab07SRod Evans const char *name; 6056deab07SRod Evans size_t lmsz; 6156deab07SRod Evans 6256deab07SRod Evans /* 6356deab07SRod Evans * Allocate the name of this object, as the original name may be 6456deab07SRod Evans * associated with a data buffer that can be reused to load the 6556deab07SRod Evans * dependencies needed to processes this object. 6656deab07SRod Evans */ 6756deab07SRod Evans if ((name = stravl_insert(oname, 0, 0, 0)) == NULL) 6856deab07SRod Evans return (NULL); 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* 717c478bd9Sstevel@tonic-gate * Initialize an output file descriptor and the entrance criteria. 727c478bd9Sstevel@tonic-gate */ 7356deab07SRod Evans if ((ofl = calloc(sizeof (Ofl_desc), 1)) == NULL) 7456deab07SRod Evans return (NULL); 755aefb655Srie 765aefb655Srie ofl->ofl_dehdr = &dehdr; 775aefb655Srie 782926dd2eSrie ofl->ofl_flags = (FLG_OF_DYNAMIC | FLG_OF_SHAROBJ | FLG_OF_STRIP); 792926dd2eSrie ofl->ofl_flags1 = (FLG_OF1_RELDYN | FLG_OF1_TEXTOFF | FLG_OF1_MEMORY); 805aefb655Srie ofl->ofl_lml = lml; 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate /* 837c478bd9Sstevel@tonic-gate * As ent_setup() will effectively lazy load the necessary support 847c478bd9Sstevel@tonic-gate * libraries, make sure ld.so.1 is initialized for plt relocations. 8556deab07SRod Evans * Then configure libld.so to process objects of the desired target 86ba2be530Sab196087 * type (this is the first call to libld.so, which will effectively 87ba2be530Sab196087 * lazyload it). 88ba2be530Sab196087 */ 8956deab07SRod Evans if ((elf_rtld_load() == 0) || (ld_init_target(lml, M_MACH) != 0)) { 9056deab07SRod Evans free(ofl); 9156deab07SRod Evans return (NULL); 9256deab07SRod Evans } 93ba2be530Sab196087 94ba2be530Sab196087 /* 9556deab07SRod Evans * Obtain a generic set of entrance criteria, and generate a link map 9656deab07SRod Evans * place holder and use the ELFPRV() element to maintain the output 9756deab07SRod Evans * file descriptor. 987c478bd9Sstevel@tonic-gate */ 9956deab07SRod Evans lmsz = S_DROUND(sizeof (Rt_map)) + sizeof (Rt_elfp); 10056deab07SRod Evans if ((ld_ent_setup(ofl, syspagsz) == S_ERROR) || 10156deab07SRod Evans ((olmp = calloc(lmsz, 1)) == NULL)) { 10256deab07SRod Evans free(ofl); 10356deab07SRod Evans return (NULL); 10456deab07SRod Evans } 1057c478bd9Sstevel@tonic-gate 10656deab07SRod Evans DBG_CALL(Dbg_file_elf(lml, name, 0, 0, lml->lm_lmidstr, lmco)); 1077c478bd9Sstevel@tonic-gate FLAGS(olmp) |= FLG_RT_OBJECT; 10856deab07SRod Evans ELFPRV(olmp) = (void *)ofl; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* 111c1c6f601Srie * Initialize string tables. 1127c478bd9Sstevel@tonic-gate */ 11356deab07SRod Evans if (ld_init_strings(ofl) == S_ERROR) { 11456deab07SRod Evans free(ofl); 11556deab07SRod Evans free(olmp); 11656deab07SRod Evans olmp = NULL; 11756deab07SRod Evans return (NULL); 11856deab07SRod Evans } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* 1217c478bd9Sstevel@tonic-gate * Assign the output file name to be the initial object that got us 1227c478bd9Sstevel@tonic-gate * here. This name is being used for diagnostic purposes only as we 1237c478bd9Sstevel@tonic-gate * don't actually generate an output file unless debugging is enabled. 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate ofl->ofl_name = name; 12656deab07SRod Evans NAME(olmp) = (char *)name; 1277c478bd9Sstevel@tonic-gate LIST(olmp) = lml; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate lm_append(lml, lmco, olmp); 1307c478bd9Sstevel@tonic-gate return (olmp); 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* 13456deab07SRod Evans * Define a structure to retain the mapping information of the original 13556deab07SRod Evans * relocatable object. Typically, mmapobj(2) maps a relocatable object into one 13656deab07SRod Evans * mapping. However, if padding has been enabled by a debugger, then additional 13756deab07SRod Evans * padding segments may have been added. elf_obj_file() needs to know which 13856deab07SRod Evans * segment is the relocatable objects data, and retain the initial segment and 13956deab07SRod Evans * the associated segment number for unmapping this object later (see 14056deab07SRod Evans * elf_obj_fini()). Note, even if padding is enabled, the final shared object 14156deab07SRod Evans * that is created by the link-editor for this relocatable object will have no 14256deab07SRod Evans * associated padding, as ld(1) has no capabilities to provide padding. 14356deab07SRod Evans */ 14456deab07SRod Evans typedef struct { 14556deab07SRod Evans mmapobj_result_t *md_mpp; 14656deab07SRod Evans uint_t md_mnum; 14756deab07SRod Evans } Mmap_desc; 14856deab07SRod Evans 14956deab07SRod Evans /* 1507c478bd9Sstevel@tonic-gate * Initial processing of a relocatable object. If this is the first object 1517c478bd9Sstevel@tonic-gate * encountered we need to initialize some structures, then simply call the 1527c478bd9Sstevel@tonic-gate * link-edit functionality to provide the initial processing of the file (ie. 1537c478bd9Sstevel@tonic-gate * reads in sections and symbols, performs symbol resolution if more that one 1547c478bd9Sstevel@tonic-gate * object file have been specified, and assigns input sections to output 1557c478bd9Sstevel@tonic-gate * sections). 1567c478bd9Sstevel@tonic-gate */ 1577c478bd9Sstevel@tonic-gate Rt_map * 158*2020b2b6SRod Evans elf_obj_file(Lm_list *lml, Aliste lmco, Rt_map *clmp, const char *name, 15956deab07SRod Evans mmapobj_result_t *hmpp, mmapobj_result_t *mpp, uint_t mnum) 1607c478bd9Sstevel@tonic-gate { 1617c478bd9Sstevel@tonic-gate Rej_desc rej; 16256deab07SRod Evans Mmap_desc md; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * If this is the first relocatable object (LD_PRELOAD could provide a 1667c478bd9Sstevel@tonic-gate * list of objects), initialize an input file descriptor and a link map. 1677c478bd9Sstevel@tonic-gate */ 16856deab07SRod Evans if ((olmp == NULL) && ((olmp = elf_obj_init(lml, lmco, name)) == NULL)) 16956deab07SRod Evans return (NULL); 17056deab07SRod Evans 17156deab07SRod Evans DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD)); 17256deab07SRod Evans 1737c478bd9Sstevel@tonic-gate /* 17456deab07SRod Evans * Keep track of the input image, as this must be free'd after all ELF 17556deab07SRod Evans * processing is completed. 1767c478bd9Sstevel@tonic-gate */ 17756deab07SRod Evans md.md_mpp = mpp; 17856deab07SRod Evans md.md_mnum = mnum; 17956deab07SRod Evans if (alist_append(&mpalp, &md, sizeof (Mmap_desc), 18056deab07SRod Evans AL_CNT_MPOBJS) == NULL) { 181*2020b2b6SRod Evans remove_so(lml, olmp, clmp); 18256deab07SRod Evans return (NULL); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate /* 18656deab07SRod Evans * Pass the object mapping to the link-editor to commence processing the 18756deab07SRod Evans * file. 1887c478bd9Sstevel@tonic-gate */ 18956deab07SRod Evans if (ld_process_mem(name, name, hmpp->mr_addr, hmpp->mr_msize, 19056deab07SRod Evans (Ofl_desc *)ELFPRV(olmp), &rej) == (Ifl_desc *)S_ERROR) { 191*2020b2b6SRod Evans remove_so(lml, olmp, clmp); 19256deab07SRod Evans return (NULL); 19356deab07SRod Evans } 19456deab07SRod Evans 1957c478bd9Sstevel@tonic-gate return (olmp); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate /* 19908278a5eSRod Evans * Ensure any platform or machine capability names are valid. 20008278a5eSRod Evans */ 20108278a5eSRod Evans inline static int 20208278a5eSRod Evans check_plat_names(Syscapset *scapset, Alist *caps, Rej_desc *rej) 20308278a5eSRod Evans { 20408278a5eSRod Evans Capstr *capstr; 20508278a5eSRod Evans Aliste idx; 20608278a5eSRod Evans 20708278a5eSRod Evans for (ALIST_TRAVERSE(caps, idx, capstr)) { 20808278a5eSRod Evans if (platcap_check(scapset, capstr->cs_str, rej) == 1) 20908278a5eSRod Evans return (1); 21008278a5eSRod Evans } 21108278a5eSRod Evans return (0); 21208278a5eSRod Evans } 21308278a5eSRod Evans 21408278a5eSRod Evans inline static int 21508278a5eSRod Evans check_mach_names(Syscapset *scapset, Alist *caps, Rej_desc *rej) 21608278a5eSRod Evans { 21708278a5eSRod Evans Capstr *capstr; 21808278a5eSRod Evans Aliste idx; 21908278a5eSRod Evans 22008278a5eSRod Evans for (ALIST_TRAVERSE(caps, idx, capstr)) { 22108278a5eSRod Evans if (machcap_check(scapset, capstr->cs_str, rej) == 1) 22208278a5eSRod Evans return (1); 22308278a5eSRod Evans } 22408278a5eSRod Evans return (0); 22508278a5eSRod Evans } 22608278a5eSRod Evans 22708278a5eSRod Evans /* 2287c478bd9Sstevel@tonic-gate * Finish relocatable object processing. Having already initially processed one 2297c478bd9Sstevel@tonic-gate * or more objects, complete the generation of a shared object image by calling 2307c478bd9Sstevel@tonic-gate * the appropriate link-edit functionality (refer to sgs/ld/common/main.c). 2317c478bd9Sstevel@tonic-gate */ 2327c478bd9Sstevel@tonic-gate Rt_map * 233*2020b2b6SRod Evans elf_obj_fini(Lm_list *lml, Rt_map *lmp, Rt_map *clmp, int *in_nfavl) 2347c478bd9Sstevel@tonic-gate { 23556deab07SRod Evans Ofl_desc *ofl = (Ofl_desc *)ELFPRV(lmp); 23656deab07SRod Evans Rt_map *nlmp, *tlmp; 2377c478bd9Sstevel@tonic-gate Ehdr *ehdr; 2387c478bd9Sstevel@tonic-gate Phdr *phdr; 23956deab07SRod Evans mmapobj_result_t *mpp, *hmpp; 24056deab07SRod Evans uint_t phnum; 24156deab07SRod Evans int mnum; 2427c478bd9Sstevel@tonic-gate Lm_cntl *lmc; 24356deab07SRod Evans Aliste idx1; 24456deab07SRod Evans Mmap_desc *mdp; 24556deab07SRod Evans Fdesc fd = { 0 }; 24656deab07SRod Evans Grp_hdl *ghp; 24756deab07SRod Evans Rej_desc rej = { 0 }; 24808278a5eSRod Evans Syscapset *scapset; 24908278a5eSRod Evans elfcap_mask_t omsk; 25008278a5eSRod Evans Alist *oalp; 2517c478bd9Sstevel@tonic-gate 2525aefb655Srie DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD)); 2537c478bd9Sstevel@tonic-gate 2545aefb655Srie if (ld_reloc_init(ofl) == S_ERROR) 25556deab07SRod Evans return (NULL); 2565aefb655Srie if (ld_sym_validate(ofl) == S_ERROR) 25756deab07SRod Evans return (NULL); 25856deab07SRod Evans 25956deab07SRod Evans /* 26056deab07SRod Evans * At this point, all input section processing is complete. If any 26108278a5eSRod Evans * capabilities have been established, ensure that they are appropriate 26208278a5eSRod Evans * for this system. 26356deab07SRod Evans */ 26408278a5eSRod Evans if (pnavl_recorded(&capavl, ofl->ofl_name, NULL, NULL)) 26508278a5eSRod Evans scapset = alt_scapset; 26608278a5eSRod Evans else 26708278a5eSRod Evans scapset = org_scapset; 26856deab07SRod Evans 26908278a5eSRod Evans if ((((omsk = ofl->ofl_ocapset.oc_hw_1.cm_val) != 0) && 27008278a5eSRod Evans (hwcap1_check(scapset, omsk, &rej) == 0)) || 27108278a5eSRod Evans (((omsk = ofl->ofl_ocapset.oc_sf_1.cm_val) != 0) && 27208278a5eSRod Evans (sfcap1_check(scapset, omsk, &rej) == 0)) || 27308278a5eSRod Evans (((omsk = ofl->ofl_ocapset.oc_hw_2.cm_val) != 0) && 27408278a5eSRod Evans (hwcap2_check(scapset, omsk, &rej) == 0)) || 27508278a5eSRod Evans (((oalp = ofl->ofl_ocapset.oc_plat.cl_val) != NULL) && 27608278a5eSRod Evans (check_plat_names(scapset, oalp, &rej) == 0)) || 27708278a5eSRod Evans (((oalp = ofl->ofl_ocapset.oc_mach.cl_val) != NULL) && 27808278a5eSRod Evans (check_mach_names(scapset, oalp, &rej) == 0))) { 279dde769a2SRod Evans if ((lml_main.lm_flags & LML_FLG_TRC_LDDSTUB) && lmp && 280dde769a2SRod Evans (FLAGS1(lmp) & FL1_RT_LDDSTUB) && (NEXT(lmp) == NULL)) { 28108278a5eSRod Evans /* LINTED */ 28208278a5eSRod Evans (void) printf(MSG_INTL(ldd_reject[rej.rej_type]), 28356deab07SRod Evans ofl->ofl_name, rej.rej_str); 28456deab07SRod Evans } 28556deab07SRod Evans return (NULL); 28656deab07SRod Evans } 28756deab07SRod Evans 28856deab07SRod Evans /* 28956deab07SRod Evans * Finish creating the output file. 29056deab07SRod Evans */ 2915aefb655Srie if (ld_make_sections(ofl) == S_ERROR) 29256deab07SRod Evans return (NULL); 2935aefb655Srie if (ld_create_outfile(ofl) == S_ERROR) 29456deab07SRod Evans return (NULL); 29556deab07SRod Evans if (ld_update_outfile(ofl) == S_ERROR) 29656deab07SRod Evans return (NULL); 2975aefb655Srie if (ld_reloc_process(ofl) == S_ERROR) 29856deab07SRod Evans return (NULL); 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate /* 3017c478bd9Sstevel@tonic-gate * At this point we have a memory image of the shared object. The link 3027c478bd9Sstevel@tonic-gate * editor would normally simply write this to the required output file. 3037c478bd9Sstevel@tonic-gate * If we're debugging generate a standard temporary output file. 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_file_output(ofl)); 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate /* 3087c478bd9Sstevel@tonic-gate * Allocate a mapping array to retain mapped segment information. 3097c478bd9Sstevel@tonic-gate */ 3105aefb655Srie ehdr = ofl->ofl_nehdr; 3117c478bd9Sstevel@tonic-gate phdr = ofl->ofl_phdr; 31256deab07SRod Evans 31356deab07SRod Evans if ((mpp = hmpp = calloc(ehdr->e_phnum, 31456deab07SRod Evans sizeof (mmapobj_result_t))) == NULL) 31556deab07SRod Evans return (NULL); 31656deab07SRod Evans for (mnum = 0, phnum = 0; phnum < ehdr->e_phnum; phnum++) { 3177c478bd9Sstevel@tonic-gate if (phdr[phnum].p_type != PT_LOAD) 3187c478bd9Sstevel@tonic-gate continue; 3197c478bd9Sstevel@tonic-gate 32056deab07SRod Evans mpp[mnum].mr_addr = (caddr_t)((uintptr_t)phdr[phnum].p_vaddr + 32156deab07SRod Evans (uintptr_t)ehdr); 32256deab07SRod Evans mpp[mnum].mr_msize = phdr[phnum].p_memsz; 32356deab07SRod Evans mpp[mnum].mr_fsize = phdr[phnum].p_filesz; 32456deab07SRod Evans mpp[mnum].mr_prot = (PROT_READ | PROT_WRITE | PROT_EXEC); 32556deab07SRod Evans mnum++; 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate /* 3297c478bd9Sstevel@tonic-gate * Generate a new link map representing the memory image created. 3307c478bd9Sstevel@tonic-gate */ 33156deab07SRod Evans fd.fd_nname = ofl->ofl_name; 33256deab07SRod Evans if ((nlmp = elf_new_lmp(lml, CNTL(olmp), &fd, (Addr)hmpp->mr_addr, 333*2020b2b6SRod Evans ofl->ofl_size, NULL, clmp, in_nfavl)) == NULL) 33456deab07SRod Evans return (NULL); 33556deab07SRod Evans 33656deab07SRod Evans MMAPS(nlmp) = hmpp; 33756deab07SRod Evans MMAPCNT(nlmp) = mnum; 33856deab07SRod Evans PADSTART(nlmp) = (ulong_t)hmpp->mr_addr; 33956deab07SRod Evans PADIMLEN(nlmp) = mpp->mr_addr + mpp->mr_msize - hmpp->mr_addr; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate /* 34256deab07SRod Evans * Replace the original (temporary) link map with the new link map. 3437c478bd9Sstevel@tonic-gate */ 3447c478bd9Sstevel@tonic-gate /* LINTED */ 345cce0e03bSab196087 lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, CNTL(nlmp)); 3467c478bd9Sstevel@tonic-gate lml->lm_obj--; 3477c478bd9Sstevel@tonic-gate 34856deab07SRod Evans if ((tlmp = PREV_RT_MAP(nlmp)) == olmp) 34956deab07SRod Evans tlmp = nlmp; 35056deab07SRod Evans 35156deab07SRod Evans if (PREV(olmp)) { 35256deab07SRod Evans NEXT(PREV_RT_MAP(olmp)) = (Link_map *)nlmp; 3537c478bd9Sstevel@tonic-gate PREV(nlmp) = PREV(olmp); 35456deab07SRod Evans } else { 35556deab07SRod Evans PREV(nlmp) = NULL; 35656deab07SRod Evans lmc->lc_head = nlmp; 35756deab07SRod Evans if (CNTL(nlmp) == ALIST_OFF_DATA) 35856deab07SRod Evans lml->lm_head = nlmp; 35956deab07SRod Evans } 36056deab07SRod Evans 36156deab07SRod Evans if (NEXT(olmp) != (Link_map *)nlmp) { 3627c478bd9Sstevel@tonic-gate NEXT(nlmp) = NEXT(olmp); 36356deab07SRod Evans PREV(NEXT_RT_MAP(olmp)) = (Link_map *)nlmp; 36456deab07SRod Evans } 36556deab07SRod Evans 36656deab07SRod Evans NEXT(tlmp) = NULL; 36756deab07SRod Evans 36856deab07SRod Evans lmc->lc_tail = tlmp; 36956deab07SRod Evans if (CNTL(nlmp) == ALIST_OFF_DATA) 37056deab07SRod Evans lml->lm_tail = tlmp; 37156deab07SRod Evans 3727c478bd9Sstevel@tonic-gate HANDLES(nlmp) = HANDLES(olmp); 3737c478bd9Sstevel@tonic-gate GROUPS(nlmp) = GROUPS(olmp); 3747c478bd9Sstevel@tonic-gate STDEV(nlmp) = STDEV(olmp); 3757c478bd9Sstevel@tonic-gate STINO(nlmp) = STINO(olmp); 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate FLAGS(nlmp) |= ((FLAGS(olmp) & ~FLG_RT_OBJECT) | FLG_RT_IMGALLOC); 3787c478bd9Sstevel@tonic-gate FLAGS1(nlmp) |= FLAGS1(olmp); 3797c478bd9Sstevel@tonic-gate MODE(nlmp) |= MODE(olmp); 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate NAME(nlmp) = NAME(olmp); 38256deab07SRod Evans 38356deab07SRod Evans /* 38456deab07SRod Evans * Reassign any original handles to the new link-map. 38556deab07SRod Evans */ 38656deab07SRod Evans for (APLIST_TRAVERSE(HANDLES(nlmp), idx1, ghp)) { 38756deab07SRod Evans Grp_desc *gdp; 38856deab07SRod Evans Aliste idx2; 38956deab07SRod Evans 39056deab07SRod Evans ghp->gh_ownlmp = nlmp; 39156deab07SRod Evans 39256deab07SRod Evans for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 39356deab07SRod Evans if (gdp->gd_depend == olmp) { 39456deab07SRod Evans gdp->gd_depend = nlmp; 39556deab07SRod Evans break; 39656deab07SRod Evans } 39756deab07SRod Evans } 39856deab07SRod Evans } 3997c478bd9Sstevel@tonic-gate 4005aefb655Srie ld_ofl_cleanup(ofl); 40156deab07SRod Evans free(ELFPRV(olmp)); 40256deab07SRod Evans free(olmp); 4037c478bd9Sstevel@tonic-gate olmp = 0; 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate /* 40656deab07SRod Evans * Unmap the original relocatable object. 4077c478bd9Sstevel@tonic-gate */ 40856deab07SRod Evans for (ALIST_TRAVERSE(mpalp, idx1, mdp)) { 40956deab07SRod Evans unmap_obj(mdp->md_mpp, mdp->md_mnum); 41056deab07SRod Evans free(mdp->md_mpp); 41156deab07SRod Evans } 41256deab07SRod Evans free(mpalp); 41356deab07SRod Evans mpalp = NULL; 41456deab07SRod Evans 41556deab07SRod Evans /* 41656deab07SRod Evans * Now that we've allocated our permanent link map structure, expand the 41756deab07SRod Evans * PATHNAME() and insert this path name into the FullPathNode AVL tree. 41856deab07SRod Evans */ 4197c478bd9Sstevel@tonic-gate (void) fullpath(nlmp, 0); 4207c478bd9Sstevel@tonic-gate if (fpavl_insert(lml, nlmp, PATHNAME(nlmp), 0) == 0) 42156deab07SRod Evans return (NULL); 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate /* 4247c478bd9Sstevel@tonic-gate * If we're being audited tell the audit library of the file we've just 4257c478bd9Sstevel@tonic-gate * opened. 4267c478bd9Sstevel@tonic-gate */ 42756deab07SRod Evans if ((lml->lm_tflags | AFLAGS(nlmp)) & LML_TFLG_AUD_MASK) { 428*2020b2b6SRod Evans if (audit_objopen(nlmp, nlmp) == 0) 42956deab07SRod Evans return (NULL); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate return (nlmp); 4327c478bd9Sstevel@tonic-gate } 433