void Dbg_util_lcinterface(Rt_map *lmp, int tag, char *val) { const char *str; static char string[CONV_INV_STRSIZE]; if (DBG_NOTDETAIL()) return; if (tag < CI_MAX) str = MSG_ORIG(tags[tag]); else str = conv_invalid_val(string, CONV_INV_STRSIZE, tag, 0); dbg_print(LIST(lmp), MSG_INTL(MSG_UTL_LCINTERFACE), NAME(lmp), str, EC_NATPTR(val)); }
void Dbg_util_call_array(Rt_map *lmp, void *addr, int ndx, Word shtype) { Lm_list *lml = LIST(lmp); const char *str; if (DBG_NOTCLASS(DBG_C_INIT)) return; if (shtype == SHT_INIT_ARRAY) str = MSG_ORIG(MSG_SCN_INITARRAY); else if (shtype == SHT_FINI_ARRAY) str = MSG_ORIG(MSG_SCN_FINIARRAY); else str = MSG_ORIG(MSG_SCN_PREINITARRAY); dbg_print(lml, MSG_INTL(MSG_UTL_ARRAY), str, ndx, EC_NATPTR(addr), NAME(lmp)); }
/* * Function binding routine - invoked on the first call to a function through * the procedure linkage table; * passes first through an assembly language interface. * * Takes the offset into the relocation table of the associated * relocation entry and the address of the link map (rt_private_map struct) * for the entry. * * Returns the address of the function referenced after re-writing the PLT * entry to invoke the function directly. * * On error, causes process to terminate with a signal. */ ulong_t elf_bndr(Rt_map *lmp, ulong_t reloff, caddr_t from) { Rt_map *nlmp, *llmp; ulong_t addr, symval, rsymndx; char *name; Rel *rptr; Sym *rsym, *nsym; uint_t binfo, sb_flags = 0, dbg_class; Slookup sl; Sresult sr; int entry, lmflags; Lm_list *lml; /* * For compatibility with libthread (TI_VERSION 1) we track the entry * value. A zero value indicates we have recursed into ld.so.1 to * further process a locking request. Under this recursion we disable * tsort and cleanup activities. */ entry = enter(0); lml = LIST(lmp); if ((lmflags = lml->lm_flags) & LML_FLG_RTLDLM) { dbg_class = dbg_desc->d_class; dbg_desc->d_class = 0; } /* * Perform some basic sanity checks. If we didn't get a load map or * the relocation offset is invalid then its possible someone has walked * over the .got entries or jumped to plt0 out of the blue. */ if (!lmp || ((reloff % sizeof (Rel)) != 0)) { Conv_inv_buf_t inv_buf; eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_PLTREF), conv_reloc_386_type(R_386_JMP_SLOT, 0, &inv_buf), EC_NATPTR(lmp), EC_XWORD(reloff), EC_NATPTR(from)); rtldexit(lml, 1); } /* * Use relocation entry to get symbol table entry and symbol name. */ addr = (ulong_t)JMPREL(lmp); rptr = (Rel *)(addr + reloff); rsymndx = ELF_R_SYM(rptr->r_info); rsym = (Sym *)((ulong_t)SYMTAB(lmp) + (rsymndx * SYMENT(lmp))); name = (char *)(STRTAB(lmp) + rsym->st_name); /* * Determine the last link-map of this list, this'll be the starting * point for any tsort() processing. */ llmp = lml->lm_tail; /* * Find definition for symbol. Initialize the symbol lookup, and * symbol result, data structures. */ SLOOKUP_INIT(sl, name, lmp, lml->lm_head, ld_entry_cnt, 0, rsymndx, rsym, 0, LKUP_DEFT); SRESULT_INIT(sr, name); if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) { eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), demangle(name)); rtldexit(lml, 1); } name = (char *)sr.sr_name; nlmp = sr.sr_dmap; nsym = sr.sr_sym; symval = nsym->st_value; if (!(FLAGS(nlmp) & FLG_RT_FIXED) && (nsym->st_shndx != SHN_ABS)) symval += ADDR(nlmp); if ((lmp != nlmp) && ((FLAGS1(nlmp) & FL1_RT_NOINIFIN) == 0)) { /* * Record that this new link map is now bound to the caller. */ if (bind_one(lmp, nlmp, BND_REFER) == 0) rtldexit(lml, 1); } if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_SYMBIND) { uint_t symndx = (((uintptr_t)nsym - (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp)); symval = audit_symbind(lmp, nlmp, nsym, symndx, symval, &sb_flags); } if (!(rtld_flags & RT_FL_NOBIND)) { addr = rptr->r_offset; if (!(FLAGS(lmp) & FLG_RT_FIXED)) addr += ADDR(lmp); if (((lml->lm_tflags | AFLAGS(lmp)) & (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) && AUDINFO(lmp)->ai_dynplts) { int fail = 0; uint_t pltndx = reloff / sizeof (Rel); uint_t symndx = (((uintptr_t)nsym - (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp)); symval = (ulong_t)elf_plt_trace_write(addr, lmp, nlmp, nsym, symndx, pltndx, (caddr_t)symval, sb_flags, &fail); if (fail) rtldexit(lml, 1); } else { /* * Write standard PLT entry to jump directly * to newly bound function. */ *(ulong_t *)addr = symval; } } /* * Print binding information and rebuild PLT entry. */ DBG_CALL(Dbg_bind_global(lmp, (Addr)from, (Off)(from - ADDR(lmp)), (Xword)(reloff / sizeof (Rel)), PLT_T_FULL, nlmp, (Addr)symval, nsym->st_value, name, binfo)); /* * Complete any processing for newly loaded objects. Note we don't * know exactly where any new objects are loaded (we know the object * that supplied the symbol, but others may have been loaded lazily as * we searched for the symbol), so sorting starts from the last * link-map know on entry to this routine. */ if (entry) load_completion(llmp); /* * Some operations like dldump() or dlopen()'ing a relocatable object * result in objects being loaded on rtld's link-map, make sure these * objects are initialized also. */ if ((LIST(nlmp)->lm_flags & LML_FLG_RTLDLM) && LIST(nlmp)->lm_init) load_completion(nlmp); /* * Make sure the object to which we've bound has had it's .init fired. * Cleanup before return to user code. */ if (entry) { is_dep_init(nlmp, lmp); leave(lml, 0); } if (lmflags & LML_FLG_RTLDLM) dbg_desc->d_class = dbg_class; return (symval); }