Is_desc * ld_os_first_isdesc(Os_desc *osp) { int i; for (i = 0; i < OS_ISD_NUM; i++) { APlist *ap_isdesc = osp->os_isdescs[i]; if (aplist_nitems(ap_isdesc) > 0) return ((Is_desc *)ap_isdesc->apl_data[0]); } return (NULL); }
/* * Generate a statistics line for the auxiliary relocation descriptor cache. * * entry: * ofl - output file descriptor */ static void rel_aux_cache_statistics(Ofl_desc *ofl) { Rel_aux_cachebuf *racp; Lm_list *lml = ofl->ofl_lml; size_t desc_cnt = 0, desc_used = 0, bytes; Aliste idx; char unit_buf[CONV_INV_BUFSIZE + 10]; /* Sum the total memory allocated across all the buffers */ for (APLIST_TRAVERSE(ofl->ofl_relaux, idx, racp)) { desc_cnt += racp->rac_end - racp->rac_arr; desc_used += racp->rac_free - racp->rac_arr; } bytes = desc_cnt * sizeof (Rel_desc); dbg_print(lml, MSG_INTL(MSG_STATS_REL_ACACHE), EC_WORD(aplist_nitems(ofl->ofl_relaux)), EC_XWORD(desc_used), EC_XWORD(desc_cnt), (desc_cnt == 0) ? 100 : EC_WORD((desc_used * 100) / desc_cnt), EC_XWORD(bytes), fmt_human_units(bytes, unit_buf, sizeof (unit_buf))); }
/* * Add a size symbol to a segment * * entry: * mf - Mapfile descriptor * sgp - Segment descriptor * eq_tol - Type of assignment: TK_EQUAL, or TK_PLUSEQ * symname - Name of symbol. Must be in stable static storage * that can be retained. * * exit: * On success, the symbol has been added and true is returned. * Otherwise an error is reported and false is returned. */ bool ld_map_seg_size_symbol(Mapfile *mf, Sg_desc *sgp, Token eq_tok, const char *symname) { Elf64_Sym *sym; /* New symbol pointer */ Sym_desc *sdp; /* New symbol node pointer */ Ifl_desc *ifl; /* Dummy input file structure */ avl_index_t where; Ofl_desc *ofl = mf->mf_ofl; /* * We don't allow resetting the list of size symbols, so if the * operator is TK_EQUAL and the list is not empty, issue an error. * * If we want to lift this restriction, we would have to save the * size symbols and enter them from ld_map_post_process(). Doing that * well would require a significant overhead in saved error reporting * state, and interactions with the same symbols created by symbol * directives. As size symbols are of little practical use, and are * maintained primarily for backward compatibility with SysV, we have * decided not to do that, but to create the symbols as the mapfiles * are processed, and to disallow later attempts to remove them. */ if ((eq_tok == TK_EQUAL) && (aplist_nitems(sgp->sg_sizesym) > 0)) { mf_fatal(mf, (MSG_MAP_SEGSIZE), sgp->sg_name); return (false); } /* * Make sure we have a pseudo file descriptor to associate to the * symbol. */ if ((ifl = ld_map_ifl(mf)) == NULL) return (false); /* * Make sure the symbol doesn't already exist. It is possible that the * symbol has been scoped or versioned, in which case it does exist * but we can freely update it here. */ if ((sdp = ld_sym_find(symname, SYM_NOHASH, &where, ofl)) == NULL) { Elf64_Word hval; if ((sym = libld_calloc(sizeof (Elf64_Sym), 1)) == NULL) return (false); sym->st_shndx = SHN_ABS; sym->st_size = 0; sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT); //DBG_CALL(Dbg_map_size_new(ofl->ofl_lml, symname, // sgp->sg_name, mf->mf_lineno)); /* LINTED */ hval = (Elf64_Word)elf_hash(symname); if ((sdp = ld_sym_enter(symname, sym, hval, ifl, ofl, 0, SHN_ABS, (FLG_SY_SPECSEC | FLG_SY_GLOBREF), &where)) == (Sym_desc *)S_ERROR) return (false); sdp->sd_flags &= ~FLG_SY_CLEAN; //DBG_CALL(Dbg_map_symbol(ofl, sdp)); } else { sym = sdp->sd_sym; if (sym->st_shndx == SHN_UNDEF) { sdp->sd_shndx = sym->st_shndx = SHN_ABS; sdp->sd_flags |= FLG_SY_SPECSEC; sym->st_size = 0; sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT); sdp->sd_flags &= ~FLG_SY_MAPREF; //DBG_CALL(Dbg_map_size_old(ofl, sdp, // sgp->sg_name, mf->mf_lineno)); } else { mf_fatal(mf, (MSG_MAP_SYMDEF1), demangle(sdp->sd_name), sdp->sd_file->ifl_name, (MSG_MAP_DIFF_SYMMUL)); return (false); } } /* * Assign the symbol to the segment. */ if (aplist_append(&sgp->sg_sizesym, sdp, AL_CNT_SG_SIZESYM) == NULL) return (false); return (true); }
void Dbg_sec_order_list(Ofl_desc *ofl, int flag) { Os_desc *osp; Is_desc *isp1; Aliste idx1; Lm_list *lml = ofl->ofl_lml; const char *str; if (DBG_NOTCLASS(DBG_C_SECTIONS)) return; if (DBG_NOTDETAIL()) return; Dbg_util_nl(lml, DBG_NL_STD); /* * If the flag == 0, then the routine is called before sorting. */ if (flag == 0) str = MSG_INTL(MSG_ORD_SORT_BEFORE); else str = MSG_INTL(MSG_ORD_SORT_AFTER); for (APLIST_TRAVERSE(ofl->ofl_ordered, idx1, osp)) { int os_isdescs_idx; Aliste idx2; Dbg_util_nl(lml, DBG_NL_STD); dbg_print(lml, str, osp->os_name); dbg_print(lml, MSG_INTL(MSG_ORD_HDR_1), EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_BEFORE])), EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_ORDERED])), EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_DEFAULT])), EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_AFTER]))); OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx2, isp1) { dbg_isec_name_buf_t buf; char *alloc_mem; const char *isp1_str; Word link; Ifl_desc *ifl = isp1->is_file; Is_desc *isp2; const char *msg; /* * An output segment that requires ordering might have * as little as two sorted input sections. For example, * the crt's can provide a SHN_BEGIN and SHN_AFTER, and * only these two sections must be processed. Thus, if * a input section is unordered, move on. Diagnosing * any unsorted section can produce way too much noise. */ if ((isp1->is_flags & FLG_IS_ORDERED) == 0) continue; if (isp1->is_shdr->sh_flags & SHF_ORDERED) { link = isp1->is_shdr->sh_info; msg = MSG_ORIG(MSG_SH_INFO); } else { /* SHF_LINK_ORDER */ link = isp1->is_shdr->sh_link; msg = MSG_ORIG(MSG_SH_LINK); } isp1_str = dbg_fmt_isec_name(isp1, buf, &alloc_mem); if (link == SHN_BEFORE) { dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_1), msg, isp1_str, isp1->is_file->ifl_name); } else if (link == SHN_AFTER) { dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_2), msg, isp1_str, isp1->is_file->ifl_name); } else { isp2 = ifl->ifl_isdesc[link]; dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_3), EC_WORD(isp2->is_keyident), isp1_str, ifl->ifl_name, msg, isp2->is_name); } if (alloc_mem != NULL) free(alloc_mem); } }