void * aplist_append(APlist **lpp, const void *ptr, Aliste init_arritems) { Aliste ndx = ((*lpp) == NULL) ? 0 : (*lpp)->apl_nitems; return (aplist_insert(lpp, ptr, init_arritems, ndx)); }
/* * Add an entrance criteria record for the specified segment * * entry: * mf - Mapfile descriptor * sgp - Segment for which a new entrance criteria record is needed * name - NULL, or name by which the entrance criteria can be referenced. * * exit: * On success, a pointer to the new entrace criteria record is * returned, the contents of which have been zeroed. On failure, * NULL is returned. */ Ent_desc * ld_map_seg_ent_add(Mapfile *mf, Sg_desc *sgp, const char *name) { Ent_desc *enp; avl_index_t where; Ofl_desc *ofl = mf->mf_ofl; if ((name != NULL) && (ld_ent_lookup(mf->mf_ofl, name, &where) != NULL)) { mf_fatal(mf, (MSG_MAP_DUPNAMENT), name); return (NULL); } /* Allocate and initialize the entrace criteria descriptor */ if ((enp = libld_calloc(1, sizeof (*enp))) == NULL) return (NULL); enp->ec_name = name; enp->ec_segment = sgp; /* Tie criteria to segment */ /* * Insert into the APlist. The mf_ec_insndx field for each mapfile * starts at 0, and is incremented with each insertion. This means * that the entrance criteria for each mapfile go to the head of * the list, but that within a single mapfile, they are inserted in * the order they are seen. */ if (aplist_insert(&ofl->ofl_ents, enp, AL_CNT_OFL_ENTRANCE, mf->mf_ec_insndx) == NULL) return (NULL); mf->mf_ec_insndx++; /* * If the entrance criteria is named insert it into the AVL tree * as well. This provides O(logN) lookups by name. */ if (name != NULL) avl_insert(&ofl->ofl_ents_avl, enp, where); return (enp); }
/* * Attach an input section to an output section * * entry: * ofl - File descriptor * osp - Output section descriptor * isp - Input section descriptor * mapfile_sort - True (1) if segment supports mapfile specified ordering * of otherwise unordered input sections, and False (0) otherwise. * * exit: * - The input section has been attached to the output section * - If the input section is a candidate for string table merging, * then it is appended to the output section's list of merge * candidates (os_mstridescs). * * On success, returns True (1). On failure, False (0). */ static int os_attach_isp(Ofl_desc *ofl, Os_desc *osp, Is_desc *isp, int mapfile_sort) { Aliste init_arritems; int os_isdescs_idx, do_append = 1; if ((isp->is_flags & FLG_IS_ORDERED) == 0) { init_arritems = AL_CNT_OS_ISDESCS; os_isdescs_idx = OS_ISD_DEFAULT; /* * If section ordering was specified for an unordered section * via the mapfile, then search in the OS_ISD_DEFAULT list * and insert it in the specified position. Ordered sections * are placed in ascending order before unordered sections * (sections with an is_ordndx value of zero). * * If no mapfile ordering was specified, we append it in * the usual way below. */ if (mapfile_sort && (isp->is_ordndx > 0)) { APlist *ap_isdesc = osp->os_isdescs[OS_ISD_DEFAULT]; Aliste idx2; Is_desc *isp2; for (APLIST_TRAVERSE(ap_isdesc, idx2, isp2)) { if (isp2->is_ordndx && (isp2->is_ordndx <= isp->is_ordndx)) continue; if (aplist_insert( &osp->os_isdescs[OS_ISD_DEFAULT], isp, init_arritems, idx2) == NULL) return (0); do_append = 0; break; } }
/* * Finish the initialization of a new segment descriptor allocated by * ld_map_seg_alloc(), and enter it into the segment list. * * entry: * mf - Mapfile descriptor * seg_type - One of DBG_SEG_NEW or DBG_SEG_NEW_IMPLICIT * ins_head - If true, the new segment goes at the front of * others of its type. If false, it goes at the end. * sgp - Segment descriptor to enter. * where - Insertion point, initialized by a previous (failed) call to * ld_seg_lookup(). Ignored if the segment has a NULL sg_name. * * exit: * On success, returns SEG_INS_OK. A non-fatal error is indicated with * a return value of SEG_INS_SKIP, in which case the descriptor is * not entered, but the user is expected to discard it and continue * running. On failure, returns SEG_INS_FAIL. * * note: * This routine will modify the contents of the descriptor referenced * by sgp_tmpl before allocating the new descriptor. The caller must * not expect it to be unmodified. */ ld_map_seg_ins_t ld_map_seg_insert(Mapfile *mf, dbg_state_t dbg_state, Sg_desc *sgp, avl_index_t where) { Ofl_desc *ofl = mf->mf_ofl; size_t idx; Sg_desc *sgp2; /* temp segment descriptor pointer */ int ins_head; Elf64_Xword sg_ndx; /* * If specific fields have not been supplied via * map_equal(), make sure defaults are supplied. */ if (((sgp->sg_flags & FLG_SG_P_TYPE) == 0) && (sgp->sg_phdr.p_type == PT_NULL)) { /* * Default to a loadable segment. */ sgp->sg_phdr.p_type = PT_LOAD; sgp->sg_flags |= FLG_SG_P_TYPE; } if (sgp->sg_phdr.p_type == PT_LOAD) { if ((sgp->sg_flags & FLG_SG_P_FLAGS) == 0) { /* * Default to read/write and execute. */ sgp->sg_phdr.p_flags = PF_R + PF_W + PF_X; sgp->sg_flags |= FLG_SG_P_FLAGS; } if ((sgp->sg_flags & FLG_SG_P_ALIGN) == 0) { /* * Default to segment alignment */ sgp->sg_phdr.p_align = ld_targ.t_m.m_segm_align; sgp->sg_flags |= FLG_SG_P_ALIGN; } } /* * Determine where the new item should be inserted in * the segment descriptor list. */ switch (sgp->sg_phdr.p_type) { case PT_LOAD: if (sgp->sg_flags & FLG_SG_EMPTY) sgp->sg_id = SGID_TEXT_EMPTY; else sgp->sg_id = SGID_TEXT; break; case PT_NULL: if (sgp->sg_flags & FLG_SG_EMPTY) sgp->sg_id = SGID_NULL_EMPTY; else sgp->sg_id = SGID_NULL; break; case PT_NOTE: sgp->sg_id = SGID_NOTE; break; default: mf_fatal(mf, (MSG_MAP_UNKSEGTYP), EC_WORD(sgp->sg_phdr.p_type)); return (SEG_INS_FAIL); } /* * Add the descriptor to the segment list. In the v1 syntax, * new sections are added at the head of their type, while in * the newer syntax, they go at the end of their type. */ sg_ndx = 0; ins_head = (mf->mf_version == MFV_SYSV); for (APLIST_TRAVERSE(ofl->ofl_segs, idx, sgp2)) { if (ins_head) { /* Insert before the others of its type */ if (sgp->sg_id > sgp2->sg_id) { sg_ndx++; continue; } } else { /* Insert after the others of its type */ if (sgp->sg_id >= sgp2->sg_id) { sg_ndx++; continue; } } break; } if (aplist_insert(&ofl->ofl_segs, sgp, AL_CNT_SEGMENTS, idx) == NULL) return (SEG_INS_FAIL); if (sgp->sg_name != NULL) avl_insert(&ofl->ofl_segs_avl, sgp, where); //DBG_CALL(Dbg_map_seg(ofl, dbg_state, sg_ndx, sgp, mf->mf_lineno)); return (SEG_INS_OK); }