Esempio n. 1
0
void
Dbg_sec_unsup_strmerge(Lm_list *lml, Is_desc *isp)
{
	dbg_isec_name_buf_t	buf;
	char			*alloc_mem;
	const char		*str;

	if (DBG_NOTCLASS(DBG_C_SECTIONS))
		return;

	/*
	 * We can only merge string table sections with single byte
	 * (char) characters. For any other (wide) character types,
	 * issue a message so the user will understand why these
	 * sections are not being picked up.
	 */
	if ((isp->is_shdr->sh_entsize > 1) ||
	    (isp->is_shdr->sh_addralign > 1)) {
		str = (isp->is_file != NULL) ? isp->is_file->ifl_name :
		    MSG_INTL(MSG_STR_NULL);
		dbg_print(lml, MSG_INTL(MSG_SEC_STRMERGE_UNSUP),
		    dbg_fmt_isec_name(isp, buf, &alloc_mem), str,
		    EC_XWORD(isp->is_shdr->sh_addralign),
		    EC_XWORD(isp->is_shdr->sh_entsize));
		if (alloc_mem != NULL)
			free(alloc_mem);
	}
}
Esempio n. 2
0
void
Dbg_sec_genstr_compress(Lm_list *lml, const char *os_name,
    Xword raw_size, Xword merge_size)
{
	if (DBG_NOTCLASS(DBG_C_SECTIONS))
		return;

	dbg_print(lml, MSG_INTL(MSG_SEC_GENSTR_COMP), os_name,
	    EC_XWORD(raw_size), EC_XWORD(merge_size));
}
Esempio n. 3
0
void
Dbg_sec_strtab(Lm_list *lml, Os_desc *osp, Str_tbl *stp)
{
	uint_t	cnt;

	if (DBG_NOTCLASS(DBG_C_STRTAB))
		return;

	if (!osp)
		return;

	Dbg_util_nl(lml, DBG_NL_STD);
	if (stp->st_flags & FLG_STTAB_COMPRESS)
		dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_COMP), osp->os_name,
		    EC_XWORD(stp->st_fullstrsize), EC_XWORD(stp->st_strsize));
	else
		dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_STND), osp->os_name,
		    EC_XWORD(stp->st_fullstrsize));

	if ((DBG_NOTDETAIL()) ||
	    ((stp->st_flags & FLG_STTAB_COMPRESS) == 0))
		return;

	dbg_print(lml, MSG_ORIG(MSG_STR_EMPTY));
	dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_HD), osp->os_name,
	    stp->st_hbckcnt);

	for (cnt = 0; cnt < stp->st_hbckcnt; cnt++) {
		Str_hash	*strhash = stp->st_hashbcks[cnt];

		if (strhash == NULL)
			continue;

		dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_BCKT), cnt);

		while (strhash) {
			size_t	stroff = strhash->hi_mstr->sm_strlen -
			    strhash->hi_strlen;

			if (stroff == 0) {
				dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_MSTR),
				    EC_XWORD(strhash->hi_refcnt),
				    strhash->hi_mstr->sm_str);
			} else {
				dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_SUFSTR),
				    EC_XWORD(strhash->hi_refcnt),
				    &strhash->hi_mstr->sm_str[stroff],
				    strhash->hi_mstr->sm_str);
			}

			strhash = strhash->hi_next;
		}
	}
}
Esempio n. 4
0
void
Dbg_move_adjmovereloc(Lm_list *lml, Xword offset1, Xword offset2,
    const char *name)
{
	if (DBG_NOTCLASS(DBG_C_MOVE | DBG_C_RELOC))
		return;
	if (DBG_NOTDETAIL())
		return;

	dbg_print(lml, MSG_INTL(MSG_MOVE_ADJMOVE), Dbg_demangle_name(name),
	    EC_XWORD(offset1), EC_XWORD(offset2));
}
Esempio n. 5
0
elfedit_atoui_t
elfedit_atoui_range(const char *str, const char *item_name,
    elfedit_atoui_t min, elfedit_atoui_t max, const elfedit_atoui_sym_t *sym)
{
	elfedit_atoui_t v = elfedit_atoui(str, sym);

	if ((v < min) || (v > max))
		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_ATOUIRANGE),
		    item_name, EC_XWORD(min), EC_XWORD(max), EC_XWORD(v));

	return (v);
}
Esempio n. 6
0
void
Dbg_tls_static_resv(Rt_map *lmp, ulong_t size, ulong_t resv)
{
	Lm_list	*lml = LIST(lmp);

	if (DBG_NOTCLASS(DBG_C_TLS))
		return;

	Dbg_util_nl(lml, DBG_NL_STD);
	dbg_print(lml, MSG_INTL(MSG_TLS_STATBLOCK3), TLSMODID(lmp), NAME(lmp),
	    EC_XWORD(size), EC_XWORD(resv));
}
Esempio n. 7
0
void
Dbg_unused_sec(Lm_list *lml, Is_desc *isp)
{
	const char	*str;

	if (DBG_NOTCLASS(DBG_C_UNUSED))
		return;
	if (DBG_NOTDETAIL())
		return;

	/*
	 * If the file from which this section originates hasn't been referenced
	 * at all, skip this diagnostic, as it would have been covered under
	 * Dbg_unused_file() called from ignore_section_processing().
	 */
	if (isp->is_file &&
	    ((isp->is_file->ifl_flags & FLG_IF_FILEREF) == 0))
		return;

	if (isp->is_flags & FLG_IS_DISCARD)
		str = MSG_INTL(MSG_USD_SECDISCARD);
	else
		str = MSG_ORIG(MSG_STR_EMPTY);

	dbg_print(lml, MSG_INTL(MSG_USD_SEC), isp->is_basename,
	    EC_XWORD(isp->is_shdr->sh_size), isp->is_file->ifl_name, str);
}
Esempio n. 8
0
static int
conv_cap(Xword val, char *str, size_t len, Half mach,
    Conv_fmt_flags_t fmt_flags, elfcap_to_str_func_t *fptr)
{
	size_t	_len;
	int do_bkt = (fmt_flags & CONV_FMT_NOBKT) == 0;

	/*
	 * Note that for the purposes of this routine, I consider
	 * CONV_FMT_NOBKT to mean no brackets, or anything that
	 * is placed outside of them. We also drop the hex version
	 * of the flags that are put in front of the opening bracket.
	 */
	if (do_bkt) {
		_len = sprintf(str, MSG_ORIG(MSG_GBL_OSQBRKT), EC_XWORD(val));

		len -= _len;
		str += _len;
	}

	if ((*fptr)(ELFCAP_STYLE_UC, val, str, len, ELFCAP_FMT_SNGSPACE,
	    mach) != 0)
		return (0);

	if (do_bkt) {
		_len = strlen(str);
		if ((len - _len) >= MSG_GBL_CSQBRKT_SIZE) {
			str += _len;
			(void) strcpy(str, MSG_ORIG(MSG_GBL_CSQBRKT));
		}
	}
	return (1);
}
Esempio n. 9
0
void
Dbg_audit_pltenter(Lm_list *lml, int call, const char *lib, const char *name,
    Addr value)
{
	if (DBG_NOTCLASS(DBG_C_AUDITING))
		return;

	if (call == DBG_AUD_CALL) {
		Dbg_util_nl(lml, DBG_NL_STD);
		dbg_print(lml, MSG_INTL(MSG_AUD_PLTENTER), lib, name,
		    EC_XWORD(value));
	} else {
		dbg_print(lml, MSG_INTL(MSG_AUD_PLTENTER_R), lib, name,
		    EC_XWORD(value));
	}
}
Esempio n. 10
0
void
Elf_got_entry(Lm_list *lml, Sword ndx, Addr addr, Xword value, Half mach,
    uchar_t ei_target_data, uchar_t ei_host_data, Word type, void *reloc,
    const char *name)
{
	Rela		*rela;
	Rel		*rel;
	const char	*str;
	Conv_inv_buf_t	inv_buf;
	char		index[INDEX_STR_SIZE];

	(void) snprintf(index, INDEX_STR_SIZE, MSG_ORIG(MSG_GOT_INDEX),
	    EC_SWORD(ndx));

	/*
	 * Got sections are SHT_PROGBITS, and are therefore not xlated by
	 * libelf. If the target system has a different byte order than
	 * the system displaying the data, swap the bytes so they are
	 * presented properly.
	 */
	if (ei_target_data != ei_host_data)
		value = BSWAP_XWORD(value);

	if (reloc) {
		if (type == SHT_RELA) {
			rela = (Rela *)reloc;
			str = conv_reloc_type(mach,
			    ELF_R_TYPE(rela->r_info, mach), 0, &inv_buf);
		} else {
			rel = (Rel *)reloc;
			str = conv_reloc_type(mach,
			    ELF_R_TYPE(rel->r_info, mach), 0, &inv_buf);
		}

		if (name)
			name = Elf_demangle_name(name);
		else
			name = MSG_ORIG(MSG_STR_EMPTY);

		dbg_print(lml, MSG_INTL(MSG_GOT_ENTRY_RE), index, EC_ADDR(addr),
		    EC_XWORD(value), str, name);
	} else
		dbg_print(lml, MSG_INTL(MSG_GOT_ENTRY_NR), index, EC_ADDR(addr),
		    EC_XWORD(value));
}
Esempio n. 11
0
void
Dbg_audit_symbind(Lm_list *lml, int call, const char *lib, const char *name,
    Addr value, uint_t flags)
{
	Conv_la_symbind_buf_t	la_symbind_buf;

	if (DBG_NOTCLASS(DBG_C_AUDITING))
		return;

	if (call == DBG_AUD_CALL) {
		Dbg_util_nl(lml, DBG_NL_STD);
		dbg_print(lml, MSG_INTL(MSG_AUD_SYMBIND), lib, name,
		    EC_XWORD(value), conv_la_symbind(flags, &la_symbind_buf));
	} else {
		dbg_print(lml, MSG_INTL(MSG_AUD_SYMBIND_R), lib, name,
		    EC_XWORD(value), conv_la_symbind(flags, &la_symbind_buf));
	}
}
Esempio n. 12
0
void
Dbg_audit_symval(Lm_list *lml, const char *lib, const char *func,
    const char *sym, Addr pval, Addr nval)
{
	char	mesg[100];

	if (DBG_NOTCLASS(DBG_C_AUDITING))
		return;
	if (DBG_NOTDETAIL())
		return;

	if (pval == nval)
		mesg[0] = '\0';
	else
		(void) sprintf(mesg, MSG_INTL(MSG_AUD_SYMNEW), EC_XWORD(nval));

	dbg_print(lml, MSG_INTL(MSG_AUD_SYM), lib, func, Dbg_demangle_name(sym),
	    EC_XWORD(pval), mesg);
}
Esempio n. 13
0
/*
 * Sanity check the given capability bitmask.
 */
bool
ld_map_cap_sanitize(Mapfile *mf, Elf64_Word type, Capmask *capmask)
{
	elfcap_mask_t	mask;

	switch (type) {
	case CA_SUNW_SF_1:
		/*
		 * Unlike hardware capabilities, we do not allow setting
		 * software capability bits that do not have known definitions.
		 * Software capability tokens have to be validated as a unit
		 * as the bits can affect each others meaning (see sf1_cap()
		 * in files.c).
		 */
		if ((mask = (capmask->cm_val & ~SF1_SUNW_MASK)) != 0) {
			mf_warn(mf, (MSG_MAP_BADSF1),
			    EC_XWORD(mask));
			capmask->cm_val &= SF1_SUNW_MASK;
		}
		if ((capmask->cm_val &
		    (SF1_SUNW_FPKNWN | SF1_SUNW_FPUSED)) == SF1_SUNW_FPUSED) {
			mf_warn(mf, (MSG_MAP_BADSF1),
			    EC_XWORD(SF1_SUNW_FPUSED));
			capmask->cm_val &= ~SF1_SUNW_FPUSED;
		}
#if	!defined(_ELF64)
#if 0
		/*
		 * The SF1_SUNW_ADDR32 software capability is only meaningful
		 * when building a 64-bit object.  Warn the user, and remove the
		 * setting, if we're building a 32-bit object.
		 */
		if (capmask->cm_val & SF1_SUNW_ADDR32) {
			mf_warn0(mf, (MSG_MAP_INADDR32SF1));
			capmask->cm_val &= ~SF1_SUNW_ADDR32;
		}
#endif
#endif
	}

	return (true);
}
Esempio n. 14
0
void
Elf_dyn_entry(Lm_list *lml, Dyn *dyn, int ndx, const char *name,
    uchar_t osabi, Half mach)
{
	Conv_inv_buf_t	inv_buf;
	char		index[INDEX_STR_SIZE];

	(void) snprintf(index, sizeof (index), MSG_ORIG(MSG_FMT_INDEX), ndx);
	dbg_print(lml, MSG_INTL(MSG_DYN_ENTRY), index,
	    conv_dyn_tag(dyn->d_tag, osabi, mach, 0, &inv_buf),
	    EC_XWORD(dyn->d_un.d_val), name);
}
Esempio n. 15
0
static void
Dbg_tls_modent(Lm_list *lml, TLS_modinfo * tmodent)
{
	/*
	 * MSG_ORIG(MSG_TLS_FLAG_STATIC)
	 */
	static char	flagstr[FLAGSZ];
	static Val_desc	vda[] = {
		{ TM_FLG_STATICTLS,	MSG_TLS_FLAG_STATIC },
		{ 0,			0 }
	};
	static CONV_EXPN_FIELD_ARG conv_arg = { flagstr, sizeof (flagstr) };

	ulong_t	flags;

	if ((flags = tmodent->tm_flags) != 0) {
		conv_arg.oflags = conv_arg.rflags = flags;
		(void) conv_expn_field(&conv_arg, vda, 0);
	} else {
		flagstr[0] = '\0';
	}

	dbg_print(lml, MSG_INTL(MSG_TLS_MODENT1),
	    EC_XWORD((uintptr_t)tmodent->tm_tlsblock),
	    EC_XWORD(tmodent->tm_stattlsoffset), EC_XWORD(tmodent->tm_flags),
	    flagstr);
	dbg_print(lml, MSG_INTL(MSG_TLS_MODENT2),
	    EC_XWORD(tmodent->tm_filesz), EC_XWORD(tmodent->tm_memsz),
	    EC_XWORD(tmodent->tm_modid));
}
Esempio n. 16
0
/*
 * 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)));
}
Esempio n. 17
0
void
Dbg_tls_static_block(Lm_list *lml, void *list, ulong_t size, ulong_t resv)
{
	if (DBG_NOTCLASS(DBG_C_TLS))
		return;

	Dbg_util_nl(lml, DBG_NL_STD);

	if (list) {
		ulong_t		ndx;
		TLS_modinfo	**tlsmodlist;

		tlsmodlist = (TLS_modinfo **)list;

		for (ndx = 0; tlsmodlist[ndx]; ndx++) {
			dbg_print(lml, MSG_INTL(MSG_TLS_STATBLOCK1), ndx,
			    tlsmodlist[ndx]->tm_modname);
			Dbg_tls_modent(lml, tlsmodlist[ndx]);
			Dbg_util_nl(lml, DBG_NL_STD);
		}
	}
	dbg_print(lml, MSG_INTL(MSG_TLS_STATBLOCK2), EC_XWORD(size),
	    EC_XWORD(resv));
}
Esempio n. 18
0
/*
 * -P flag specified
 */
static void
print_with_Pflag(
	int ndigits,
	Elf *elf_file,
	unsigned int shstrndx,
	SYM *sym_data
)
{
#define	SYM_LEN 10
	char sym_name[SYM_LEN+1];
	size_t len;
	const char * const fmt[] = {
		"%*llu %*llu \n",	/* FMT_T_DEC */
		"%*llx %*llx \n",	/* FMT_T_HEX */
		"%*llo %*llo \n"	/* FMT_T_OCT */
	};

	if (is_sym_print(sym_data) != 1)
		return;
	/*
	 * -A header
	 */
	if (A_flag != 0)
		(void) printf("%s", A_header);

	/*
	 * Symbol name
	 */
	len = strlen(sym_data->name);
	if (len >= SYM_LEN)
		(void) printf("%s ", sym_data->name);
	else {
		(void) sprintf(sym_name, "%-10s", sym_data->name);
		(void) printf("%s ", sym_name);
	}

	/*
	 * Symbol Type.
	 */
	print_brief_sym_type(elf_file, shstrndx, sym_data);

	/*
	 * Symbol Value & size
	 *	(hex/octal/decimal)
	 */
	(void) printf(fmt[fmt_flag], ndigits, EC_ADDR(sym_data->value),
	    ndigits, EC_XWORD(sym_data->size));
}
Esempio n. 19
0
/*
 * Variant of Elf_dyn_entry() specifically for DT_NULL. Handles the
 * case of multiple adjacent DT_NULL entries by displaying them on
 * a single line using an index range instead of a single index.
 */
void
Elf_dyn_null_entry(Lm_list *lml, Dyn *dyn, int start_ndx, int end_ndx)
{
	Conv_inv_buf_t	inv_buf;
	char		index[2 * INDEX_STR_SIZE];

	if (start_ndx == end_ndx) {
		Elf_dyn_entry(lml, dyn, start_ndx, MSG_ORIG(MSG_STR_EMPTY),
		    ELFOSABI_NONE, 0);
	} else {
		(void) snprintf(index, sizeof (index),
		    MSG_ORIG(MSG_FMT_INDEX_RANGE), start_ndx, end_ndx);
		dbg_print(lml, MSG_INTL(MSG_DYN_ENTRY), index,
		    conv_dyn_tag(DT_NULL, ELFOSABI_NONE, 0, 0, &inv_buf),
		    EC_XWORD(dyn->d_un.d_val), MSG_ORIG(MSG_STR_EMPTY));
	}
}
Esempio n. 20
0
void
Dbg_move_entry2(Lm_list *lml, Move *mv, Word st_name, const char *name)
{
	const char *sname;

	if (DBG_NOTCLASS(DBG_C_MOVE))
		return;
	if (DBG_NOTDETAIL())
		return;

	if (st_name)
		sname = name;
	else
		sname = MSG_INTL(MSG_STR_UNKNOWN);

	dbg_print(lml, MSG_INTL(MSG_MOVE_ENTRYIN), EC_XWORD(mv->m_poffset),
	    EC_LWORD(mv->m_value), mv->m_repeat, mv->m_stride, sname);
}
Esempio n. 21
0
void
Dbg_move_entry1(Lm_list *lml, int which, Move *mv, Sym_desc *s)
{
	const char *str;

	if (DBG_NOTCLASS(DBG_C_MOVE))
		return;
	if (DBG_NOTDETAIL())
		return;

	if (which)
		str = MSG_INTL(MSG_MOVE_ENTRYIN);
	else
		str = MSG_INTL(MSG_MOVE_ENTRYOUT);

	dbg_print(lml, str, EC_XWORD(mv->m_poffset), EC_LWORD(mv->m_value),
	    mv->m_repeat, mv->m_stride, s->sd_name);
}
Esempio n. 22
0
static const char *
fmt_human_units(size_t bytes, char *buf, size_t bufsize)
{
	static int	unit_arr[] = { 'K', 'M', 'G', 'T' };

	int		i, unit_ch;
	size_t		unit_bytes = bytes;

	/* Convert to human readable units */
	for (i = 0; i < sizeof (unit_arr) / sizeof (unit_arr[0]); i++) {
		if (unit_bytes < 1024)
			break;
		unit_ch = unit_arr[i];
		unit_bytes /= 1024;
	}
	if (unit_bytes == bytes)
		buf[0] = '\0';
	else
		(void) snprintf(buf, bufsize, MSG_ORIG(MSG_FMT_MEMUNIT),
		    EC_XWORD(unit_bytes), unit_ch);

	return (buf);
}
Esempio n. 23
0
/*
 * Warning message for bad move target.
 */
void
elf_move_bad(Lm_list *lml, Rt_map *lmp, Sym *sym, ulong_t num, Addr addr)
{
	const char	*name;
	int		trace;

	trace = (lml->lm_flags & LML_FLG_TRC_ENABLE) &&
	    (((rtld_flags & RT_FL_SILENCERR) == 0) ||
	    (lml->lm_flags & (LML_FLG_TRC_VERBOSE | LML_FLG_TRC_WARN)));

	if ((trace == 0) && (DBG_ENABLED == 0))
		return;

	if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
		name = (const char *)(STRTAB(lmp) + sym->st_name);
	else
		name = MSG_INTL(MSG_STR_UNKNOWN);

	if (trace)
		(void) printf(MSG_INTL(MSG_LDD_MOVE_ERR), EC_XWORD(num), name,
		    EC_ADDR(addr));
	else
		DBG_CALL(Dbg_move_bad(lml, num, name, addr));
}
Esempio n. 24
0
/*
 * Track any static TLS use, retain the TLS header, and assign a TLS module
 * identifier.
 */
int
tls_assign(Lm_list *lml, Rt_map *lmp, Phdr *phdr)
{
	ulong_t	memsz = S_ROUND(phdr->p_memsz, M_TLSSTATALIGN);
	ulong_t	filesz = phdr->p_filesz;
	ulong_t	resv = tls_static_resv;

	/*
	 * If this object explicitly references static TLS, then there are some
	 * limitations.
	 */
	if (FLAGS1(lmp) & FL1_RT_TLSSTAT) {
		/*
		 * Static TLS is only available to objects on the primary
		 * link-map list.
		 */
		if (((lml->lm_flags & LML_FLG_BASELM) == 0) ||
		    ((rtld_flags2 & RT_FL2_NOPLM) != 0)) {
			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_TLS_STATBASE),
			    NAME(lmp));
			return (0);
		}

		/*
		 * All TLS blocks that are processed before thread
		 * initialization, are registered with libc.  This
		 * initialization is carried out through a handshake with libc
		 * prior to executing any user code (ie. before the first .init
		 * sections are called).  As part of this initialization, a
		 * small backup TLS reservation is added (tls_static_resv).
		 * Only explicit static TLS references that can be satisfied by
		 * this TLS backup reservation can be satisfied.
		 */
		if (rtld_flags2 & RT_FL2_PLMSETUP) {
			/*
			 * Initialized static TLS can not be satisfied from the
			 * TLS backup reservation.
			 */
			if (filesz) {
				eprintf(lml, ERR_FATAL,
				    MSG_INTL(MSG_TLS_STATINIT), NAME(lmp));
				return (0);
			}

			/*
			 * Make sure the backup reservation is sufficient.
			 */
			if (memsz > tls_static_resv) {
				eprintf(lml, ERR_FATAL,
				    MSG_INTL(MSG_TLS_STATSIZE), NAME(lmp),
				    EC_XWORD(memsz), EC_XWORD(tls_static_resv));
				return (0);
			}

			tls_static_resv -= memsz;
		}
	}

	/*
	 * If we haven't yet initialized threads, or this static reservation can
	 * be satisfied from the TLS backup reservation, determine the total
	 * static TLS size, and assign this object a static TLS offset.
	 */
	if (((rtld_flags2 & RT_FL2_PLMSETUP) == 0) ||
	    (FLAGS1(lmp) & FL1_RT_TLSSTAT)) {
		tls_static_size += memsz;
		TLSSTATOFF(lmp) = tls_static_size;
	}

	/*
	 * Retain the PT_TLS header, obtain a new module identifier, and
	 * indicate that this link-map list contains a new TLS object.
	 */
	PTTLS(lmp) = phdr;
	TLSMODID(lmp) = tls_getmodid();

	/*
	 * Now that we have a TLS module id, generate any static TLS reservation
	 * diagnostic.
	 */
	if (resv != tls_static_resv)
		DBG_CALL(Dbg_tls_static_resv(lmp, memsz, tls_static_resv));

	return (++lml->lm_tls);
}
Esempio n. 25
0
void
Dbg_got_display(Ofl_desc *ofl, Off goff, int stage,
    Word m_got_xnumber, size_t m_got_entsize)
{
	Lm_list		*lml = ofl->ofl_lml;
	Gottable	*gtp = ofl->ofl_gottable;
	Word		gotndx;
	Xword		*gptr;

	if (DBG_NOTCLASS(DBG_C_GOT))
		return;

	if (ofl->ofl_gotcnt == m_got_xnumber)
		return;

	Dbg_util_nl(lml, DBG_NL_STD);
	dbg_print(lml, MSG_INTL(MSG_GOT_INFO), EC_WORD(ofl->ofl_gotcnt));

	if (DBG_NOTDETAIL())
		return;

	qsort((char *)gtp, ofl->ofl_gotcnt, sizeof (Gottable),
	    (int(*)(const void *, const void *))Dbg_got_compare);

	if (stage == 0)
		dbg_print(lml, MSG_INTL(MSG_GOT_COLUMNS1));
	else
		dbg_print(lml, MSG_INTL(MSG_GOT_COLUMNS2));

	gptr = (Xword *)ofl->ofl_osgot->os_outdata->d_buf;

	for (gotndx = 0; gotndx < ofl->ofl_gotcnt; gotndx++, gtp++, gptr++) {
		Sym_desc	*sdp = gtp->gt_sym;
		const char	*refstr, *name;
		Gotndx		*gnp = &gtp->gt_gndx;
		Lword		gotaddval;
		Off		off = goff + (gotndx * m_got_entsize);
		char		index[INDEX_STR_SIZE];

		(void) snprintf(index, INDEX_STR_SIZE, MSG_ORIG(MSG_GOT_INDEX),
		    EC_SWORD(gnp->gn_gotndx));

		if (sdp == 0)
			refstr = MSG_ORIG(MSG_STR_EMPTY);
		else if (sdp->sd_flags & FLG_SY_SMGOT)
			refstr = MSG_ORIG(MSG_GOT_SMALL_PIC);
		else
			refstr = MSG_ORIG(MSG_GOT_BIG_PIC);

		if (sdp == 0)
			name = MSG_ORIG(MSG_STR_EMPTY);
		else if (sdp->sd_name)
			name = Dbg_demangle_name(sdp->sd_name);
		else
			name = MSG_INTL(MSG_STR_UNKNOWN);

		if (stage == 0)
			gotaddval = gnp->gn_addend;
		else
			gotaddval = *gptr;

		if ((sdp == 0) || (sdp->sd_sym->st_shndx == SHN_UNDEF) ||
		    (sdp->sd_file == 0)) {
			dbg_print(lml, MSG_INTL(MSG_GOT_FORMAT1), index,
			    refstr, EC_OFF(off), EC_XWORD(gotaddval), name);
		} else {
			dbg_print(lml, MSG_INTL(MSG_GOT_FORMAT2), index,
			    refstr, EC_OFF(off), EC_XWORD(gotaddval),
			    sdp->sd_file->ifl_name, name);
		}
	}
}
Esempio n. 26
0
/*
 * 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);
}
Esempio n. 27
0
/*
 * Assign move descriptors with the associated target symbol.
 */
static uintptr_t
append_move_desc(Ofl_desc *ofl, Sym_desc *sdp, Elf64_Move *mvp, Is_desc *isp)
{
	int 	i, cnt = mvp->m_repeat;

	for (i = 0; i < cnt; i++) {
		size_t		idx;
		Mv_desc		*omdp, nmd;

		/* LINTED */
		nmd.md_len = ELF_M_SIZE(mvp->m_info);
		nmd.md_start = mvp->m_poffset + i *
		    ((mvp->m_stride + 1) * nmd.md_len);
		nmd.md_move = mvp;

		/*
		 * Verify that this move descriptor doesn't overlap any existing
		 * move descriptors.
		 */
		for (ALIST_TRAVERSE(sdp->sd_move, idx, omdp)) {
			Mv_desc	*smdp, *lmdp;

			if (nmd.md_start > omdp->md_start) {
				smdp = omdp;
				lmdp = &nmd;
			} else {
				smdp = &nmd;
				lmdp = omdp;
			}

			/*
			 * If this move entry is exactly the same as that of
			 * a symbol that has overridden this symbol (for example
			 * should two identical COMMON definitions be associated
			 * with the same move data), simply ignore this move
			 * element.
			 */
			if ((nmd.md_start == omdp->md_start) &&
			    ((nmd.md_len == smdp->md_len) &&
			    sdp->sd_file != isp->is_file))
				continue;

			if ((nmd.md_start != omdp->md_start) &&
			    ((smdp->md_start + smdp->md_len) <= lmdp->md_start))
				continue;

			ld_eprintf(ofl, ERR_FATAL, MSG_MOVE_OVERLAP,
			    sdp->sd_file->ifl_name, EC_WORD(isp->is_scnndx),
			    isp->is_name, demangle(sdp->sd_name),
			    EC_XWORD(nmd.md_start), EC_XWORD(nmd.md_len),
			    EC_XWORD(omdp->md_start), EC_XWORD(omdp->md_len));

			/*
			 * Indicate that an error has occurred, so that
			 * processing can be terminated once all move errors
			 * are flushed out.
			 */
			sdp->sd_flags |= FLG_SY_OVERLAP;
			return (1);
		}

		if (alist_append(&sdp->sd_move, &nmd, sizeof (Mv_desc),
		    AL_CNT_SDP_MOVE) == NULL)
			return (S_ERROR);
	}
	return (1);
}
Esempio n. 28
0
/*
 * Validate a SHT_SUNW_move section.  These are only processed from input
 * relocatable objects.  The move section entries are validated and any data
 * structures required for later processing are created.
 */
uintptr_t
ld_process_move(Ofl_desc *ofl)
{
	size_t		idx;
	Is_desc		*isp;
	int 		errcnt = 0;

	for (APLIST_TRAVERSE(ofl->ofl_ismove, idx, isp)) {
		Ifl_desc	*ifile = isp->is_file;
		Elf64_Move		*mvp;
		Elf64_Xword		i, num;

		mvp = (Elf64_Move *)isp->is_indata->d_buf;

		if (isp->is_shdr->sh_entsize == 0) {
			ld_eprintf(ofl, ERR_FATAL,
			    MSG_FIL_INVSHENTSIZE,
			    isp->is_file->ifl_name, EC_WORD(isp->is_scnndx),
			    isp->is_name, EC_XWORD(0));
			return (S_ERROR);
		}
		num = isp->is_shdr->sh_size / isp->is_shdr->sh_entsize;

		for (i = 0; i < num; i++) {
			Elf64_Xword 		ndx = ELF_M_SYM(mvp->m_info);
			Sym_desc	*sdp;
			Elf64_Sym	*sym;

			if ((ndx >= (Elf64_Xword) isp->is_file->ifl_symscnt) ||
			    (ndx == 0)) {
				ld_eprintf(ofl, ERR_FATAL,
				    MSG_PSYM_INVMINFO1,
				    isp->is_file->ifl_name,
				    EC_WORD(isp->is_scnndx), isp->is_name, i,
				    EC_XWORD(mvp->m_info));
				return (S_ERROR);
			}
			if (mvp->m_repeat == 0) {
				ld_eprintf(ofl, ERR_FATAL,
				    MSG_PSYM_INVMREPEAT,
				    isp->is_file->ifl_name,
				    EC_WORD(isp->is_scnndx), isp->is_name, i,
				    EC_XWORD(mvp->m_repeat));
				return (S_ERROR);
			}

			sdp = isp->is_file->ifl_oldndx[ndx];

			/*
			 * Validate that this entry has a valid size.
			 */
			/* LINTED */
			switch (ELF_M_SIZE(mvp->m_info)) {
			case 1: case 2: case 4: case 8:
				break;
			default:
				ld_eprintf(ofl, ERR_FATAL,
				    MSG_PSYM_INVMINFO2,
				    isp->is_file->ifl_name,
				    EC_WORD(isp->is_scnndx), isp->is_name, i,
				    EC_XWORD(mvp->m_info));
				return (S_ERROR);
			}

			/*
			 * If this is a global symbol, adjust the visibility.
			 */
			if (sdp->sd_aux &&
			    ((sdp->sd_flags & FLG_SY_VISIBLE) == 0))
				ld_sym_adjust_vis(sdp, ofl);

			sym = sdp->sd_sym;

			if (sdp->sd_move == NULL) {
				/*
				 * If this is the first move entry associated
				 * with this symbol, save the symbol on the
				 * partial symbol list, and initialize various
				 * state regarding this symbol.
				 */
				if (aplist_append(&ofl->ofl_parsyms, sdp,
				    AL_CNT_OFL_PARSYMS) == NULL)
					return (S_ERROR);

				/*
				 * Even if -zredlocsym is in effect, the local
				 * symbol used for partial initialization is
				 * kept.
				 */
				if ((ofl->ofl_flags & FLG_OF_REDLSYM) &&
				    (ELF_ST_BIND(sym->st_info) == STB_LOCAL) &&
				    (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)) {
					ofl->ofl_locscnt++;
					if (st_insert(ofl->ofl_strtab,
					    sdp->sd_name) == -1)
						return (S_ERROR);
				}

				/*
				 * Mark the input section associated with this
				 * partially initialized symbol.
				 * This is needed when the symbol
				 * the relocation entry uses symbol information
				 * not from the symbol entry.
				 *
				 * For executable, the following is
				 * needed only for expanded symbol. However,
				 * for shared object any partially non
				 * expanded symbols are moved from
				 * .bss/COMMON to .sunwbss. So the following are
				 * needed.
				 */
				if ((sym->st_shndx != SHN_UNDEF) &&
				    (sym->st_shndx < SHN_LOPROC)) {
					Is_desc	*isc;

					isc = ifile->ifl_isdesc[ sym->st_shndx];
					isc->is_flags |= FLG_IS_RELUPD;

					if (sdp->sd_osym == NULL) {
						if ((sdp->sd_osym =
						    libld_calloc(sizeof(Elf64_Sym),
						    1)) == NULL)
							return (S_ERROR);
						*(sdp->sd_osym) =
						    *(sdp->sd_sym);
					}
				}
			}

			if (append_move_desc(ofl, sdp, mvp, isp) == S_ERROR)
				return (S_ERROR);

			if (sdp->sd_flags & FLG_SY_OVERLAP)
				errcnt++;

			/*
			 * If this symbol is marked to be expanded, go to the
			 * next move entry.
			 */
			if (sdp->sd_flags & FLG_SY_PAREXPN) {
				mvp++;
				continue;
			}

			/*
			 * Decide whether this partial symbol is to be expanded
			 * or not.
			 *
			 * The symbol will be expanded if:
			 *	a) '-z nopartial' is specified
			 *	b) move entries covered entire symbol
			 *
			 * To expand an move entry, size of the symbol to be
			 * expanded need to be known to generate a file space.
			 * (see make_movesections().)
			 *
			 * Therefore the move entry can not be expanded
			 * if the partial symbol is a section symbol.
			 * (The size of the symbol may be unknown.)
			 * This may happen, for example, when a local symbol is
			 * reduced by the -zredlocsym.
			 *
			 * The following two if statements checks the
			 * if the move entry can be expanded or not.
			 */
			if (OFL_IS_STATIC_EXEC(ofl)) {
				if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) {
					errcnt++;
					ld_eprintf(ofl, ERR_FATAL,
					    MSG_PSYM_CANNOTEXPND,
					    sdp->sd_file->ifl_name,
					    EC_WORD(isp->is_scnndx),
					    isp->is_name, i,
					    MSG_PSYM_NOSTATIC);
				} else {
					sdp->sd_flags |= FLG_SY_PAREXPN;
				}
			} else if ((ofl->ofl_flags1 & FLG_OF1_NOPARTI) != 0) {
				if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) {
					ld_eprintf(ofl, ERR_WARNING,
					    MSG_PSYM_CANNOTEXPND,
					    sdp->sd_file->ifl_name,
					    EC_WORD(isp->is_scnndx),
					    isp->is_name, i,
					    MSG_STR_EMPTY);
				} else {
					sdp->sd_flags |= FLG_SY_PAREXPN;
				}
			} else if (((Elf64_Xword)((sizeof (Elf64_Move)) *
			    alist_nitems(sdp->sd_move)) > sym->st_size) &&
			    (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)) {
				sdp->sd_flags |= FLG_SY_PAREXPN;
			}

			/*
			 * If a move entry exists that references a local
			 * symbol, and this symbol reference will eventually
			 * be assigned to the associated section, make sure the
			 * section symbol is available for relocating against
			 * at runtime.
			 */
			if ((ELF_ST_BIND(sym->st_info) == STB_LOCAL) &&
			    (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) ||
			    (ofl->ofl_flags & FLG_OF_REDLSYM))) {
				Os_desc *osp = sdp->sd_isc->is_osdesc;

				if (osp &&
				    ((osp->os_flags & FLG_OS_OUTREL) == 0)) {
					ofl->ofl_dynshdrcnt++;
					osp->os_flags |= FLG_OS_OUTREL;
				} else if ((sdp->sd_flags &
				    FLG_SY_PAREXPN) == 0)
					ofl->ofl_flags1 |= FLG_OF1_BSSOREL;
			}
			mvp++;
		}
	}

	if (errcnt != 0)
		return (S_ERROR);
	if (make_mvsections(ofl) == S_ERROR)
		return (S_ERROR);

	return (1);
}
Esempio n. 29
0
uintptr_t
ld_group_process(Is_desc *gisc, Ofl_desc *ofl)
{
	Ifl_desc	*gifl = gisc->is_file;
	Shdr		*sshdr, *gshdr = gisc->is_shdr;
	Is_desc		*isc;
	Sym		*sym;
	const char	*str;
	Group_desc	gd;
	size_t		ndx;
	int		gnu_stt_section;

	/*
	 * Confirm that the sh_link points to a valid section.
	 */
	if ((gshdr->sh_link == SHN_UNDEF) ||
	    (gshdr->sh_link >= gifl->ifl_shnum) ||
	    ((isc = gifl->ifl_isdesc[gshdr->sh_link]) == NULL)) {
		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_FIL_INVSHLINK),
		    gifl->ifl_name, EC_WORD(gisc->is_scnndx),
		    gisc->is_name, EC_XWORD(gshdr->sh_link));
		return (0);
	}
	if (gshdr->sh_entsize == 0) {
		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_FIL_INVSHENTSIZE),
		    gifl->ifl_name, EC_WORD(gisc->is_scnndx), gisc->is_name,
		    EC_XWORD(gshdr->sh_entsize));
		return (0);
	}

	/*
	 * Get the associated symbol table.  Sanity check the sh_info field
	 * (which points to the signature symbol table entry) against the size
	 * of the symbol table.
	 */
	sshdr = isc->is_shdr;
	sym = (Sym *)isc->is_indata->d_buf;

	if ((sshdr->sh_info == SHN_UNDEF) ||
	    (gshdr->sh_info >= (Word)(sshdr->sh_size / sshdr->sh_entsize)) ||
	    ((isc = gifl->ifl_isdesc[sshdr->sh_link]) == NULL)) {
		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_FIL_INVSHINFO),
		    gifl->ifl_name, EC_WORD(gisc->is_scnndx), gisc->is_name,
		    EC_XWORD(gshdr->sh_info));
		return (0);
	}

	sym += gshdr->sh_info;

	/*
	 * Get the symbol name from the associated string table.
	 */
	str = (char *)isc->is_indata->d_buf;
	str += sym->st_name;

	/*
	 * The GNU assembler can use section symbols as the signature symbol
	 * as described by this comment in the gold linker (found via google):
	 *
	 *	It seems that some versions of gas will create a section group
	 *	associated with a section symbol, and then fail to give a name
	 *	to the section symbol.  In such a case, use the name of the
	 *	section.
	 *
	 * In order to support such objects, we do the same.
	 */
	gnu_stt_section = ((sym->st_name == 0) || (*str == '\0')) &&
	    (ELF_ST_TYPE(sym->st_info) == STT_SECTION);
	if (gnu_stt_section)
		str = gisc->is_name;


	/*
	 * Generate a group descriptor.
	 */
	gd.gd_isc = gisc;
	gd.gd_oisc = NULL;
	gd.gd_name = str;
	gd.gd_data = gisc->is_indata->d_buf;
	gd.gd_cnt = gisc->is_indata->d_size / sizeof (Word);

	/*
	 * If this group is a COMDAT group, validate the signature symbol.
	 */
	if ((gd.gd_data[0] & GRP_COMDAT) && !gnu_stt_section &&
	    ((ELF_ST_BIND(sym->st_info) == STB_LOCAL) ||
	    (sym->st_shndx == SHN_UNDEF))) {
		/* If section symbol, construct a printable name for it */
		if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) {
			if (gisc->is_sym_name == NULL)
				(void) ld_stt_section_sym_name(gisc);

			if (gisc->is_sym_name != NULL)
				str = gisc->is_sym_name;
		}

		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_GRP_INVALSYM),
		    gifl->ifl_name, EC_WORD(gisc->is_scnndx),
		    gisc->is_name, str);
		return (0);
	}

	/*
	 * If the signature symbol is a name generated by the GNU compiler to
	 * refer to a header, we need sloppy relocation.
	 */
	if (is_header_gensym(str)) {
		if ((ofl->ofl_flags1 & FLG_OF1_NRLXREL) == 0)
			ofl->ofl_flags1 |= FLG_OF1_RLXREL;
		DBG_CALL(Dbg_sec_gnu_comdat(ofl->ofl_lml, gisc, TRUE,
		    (ofl->ofl_flags1 & FLG_OF1_RLXREL) != 0));
	}

	/*
	 * Validate the section indices within the group.  If this is a COMDAT
	 * group, mark each section as COMDAT.
	 */
	for (ndx = 1; ndx < gd.gd_cnt; ndx++) {
		Word	gndx;

		if ((gndx = gd.gd_data[ndx]) >= gifl->ifl_shnum) {
			ld_eprintf(ofl, ERR_FATAL,
			    MSG_INTL(MSG_GRP_INVALNDX), gifl->ifl_name,
			    EC_WORD(gisc->is_scnndx), gisc->is_name, ndx, gndx);
			return (0);
		}

		if (gd.gd_data[0] & GRP_COMDAT)
			gifl->ifl_isdesc[gndx]->is_flags |= FLG_IS_COMDAT;
	}

	/*
	 * If this is a COMDAT group, determine whether this group has already
	 * been encountered, or whether this is the first instance of the group.
	 */
	if ((gd.gd_data[0] & GRP_COMDAT) &&
	    (gpavl_loaded(ofl, &gd) == S_ERROR))
		return (S_ERROR);

	/*
	 * Associate the group descriptor with this input file.
	 */
	if (alist_append(&(gifl->ifl_groups), &gd, sizeof (Group_desc),
	    AL_CNT_IFL_GROUPS) == NULL)
		return (S_ERROR);

	return (1);
}
Esempio n. 30
0
void
Dbg_statistics_ld(Ofl_desc *ofl)
{
	Lm_list	*lml = ofl->ofl_lml;

	if (DBG_NOTCLASS(DBG_C_STATS))
		return;

	Dbg_util_nl(lml, DBG_NL_STD);
	dbg_print(lml, MSG_INTL(MSG_STATS_GENERAL));

	if (ofl->ofl_objscnt || ofl->ofl_soscnt || ofl->ofl_arscnt) {
		dbg_print(lml, MSG_INTL(MSG_STATS_FILES),
		    EC_XWORD(ofl->ofl_objscnt), EC_XWORD(ofl->ofl_soscnt),
		    EC_XWORD(ofl->ofl_arscnt));
	}

	if (ofl->ofl_locscnt || ofl->ofl_globcnt) {
		dbg_print(lml, MSG_INTL(MSG_STATS_SYMBOLS_OUT),
		    EC_XWORD(ofl->ofl_globcnt), EC_XWORD(ofl->ofl_locscnt));
	}
	if (ofl->ofl_entercnt || ofl->ofl_scopecnt || ofl->ofl_elimcnt) {
		dbg_print(lml, MSG_INTL(MSG_STATS_SYMBOLS_IN),
		    EC_XWORD(ofl->ofl_entercnt), EC_XWORD(ofl->ofl_scopecnt),
		    EC_XWORD(ofl->ofl_elimcnt));
	}

	dbg_print(lml, MSG_INTL(MSG_STATS_REL_OUT),
	    EC_XWORD(ofl->ofl_outrels.rc_cnt));

	dbg_print(lml, MSG_INTL(MSG_STATS_REL_IN),
	    EC_XWORD(ofl->ofl_entrelscnt), EC_XWORD(ofl->ofl_actrels.rc_cnt));

	dbg_print(lml, MSG_INTL(MSG_STATS_REL_TICACHE));
	rel_cache_statistics(ofl, MSG_INTL(MSG_STATS_REL_TIOUT),
	    ofl->ofl_outrels.rc_list);
	rel_cache_statistics(ofl, MSG_INTL(MSG_STATS_REL_TIACT),
	    ofl->ofl_actrels.rc_list);
	rel_aux_cache_statistics(ofl);
}