27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
55aefb65rie * Common Development and Distribution License (the "License").
65aefb65rie * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
23bf99481Ali Bahrami * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bdstevel@tonic-gate */
26bf99481Ali Bahrami#include	<stdio.h>
277c478bdstevel@tonic-gate#include	"_debug.h"
287c478bdstevel@tonic-gate#include	"msg.h"
297c478bdstevel@tonic-gate#include	"libld.h"
31bf99481Ali Bahramistatic const char *
32bf99481Ali Bahramifmt_human_units(size_t bytes, char *buf, size_t bufsize)
33bf99481Ali Bahrami{
34bf99481Ali Bahrami	static int	unit_arr[] = { 'K', 'M', 'G', 'T' };
35bf99481Ali Bahrami
36bf99481Ali Bahrami	int		i, unit_ch;
37bf99481Ali Bahrami	size_t		unit_bytes = bytes;
38bf99481Ali Bahrami
39bf99481Ali Bahrami	/* Convert to human readable units */
40bf99481Ali Bahrami	for (i = 0; i < sizeof (unit_arr) / sizeof (unit_arr[0]); i++) {
41bf99481Ali Bahrami		if (unit_bytes < 1024)
42bf99481Ali Bahrami			break;
43bf99481Ali Bahrami		unit_ch = unit_arr[i];
44bf99481Ali Bahrami		unit_bytes /= 1024;
45bf99481Ali Bahrami	}
46bf99481Ali Bahrami	if (unit_bytes == bytes)
47bf99481Ali Bahrami		buf[0] = '\0';
48bf99481Ali Bahrami	else
49bf99481Ali Bahrami		(void) snprintf(buf, bufsize, MSG_ORIG(MSG_FMT_MEMUNIT),
50bf99481Ali Bahrami		    EC_XWORD(unit_bytes), unit_ch);
51bf99481Ali Bahrami
52bf99481Ali Bahrami	return (buf);
53bf99481Ali Bahrami}
54bf99481Ali Bahrami
55bf99481Ali Bahrami/*
56bf99481Ali Bahrami * Generate a relocation cache statistics line for the active or
57bf99481Ali Bahrami * output relocation cache.
58bf99481Ali Bahrami *
59bf99481Ali Bahrami * entry:
60bf99481Ali Bahrami *	ofl - output file descriptor
61bf99481Ali Bahrami *	alp - One of ofl->ofl_actrels or ofl->ofl_outrels.
62bf99481Ali Bahrami */
63bf99481Ali Bahramistatic void
64bf99481Ali Bahramirel_cache_statistics(Ofl_desc *ofl, const char *title, APlist *alp)
65bf99481Ali Bahrami{
66bf99481Ali Bahrami	Lm_list		*lml = ofl->ofl_lml;
67bf99481Ali Bahrami	size_t		desc_cnt = 0, desc_used = 0, bytes;
68bf99481Ali Bahrami	Aliste		idx;
69bf99481Ali Bahrami	Rel_cachebuf	*rcp;
70bf99481Ali Bahrami	char		unit_buf[CONV_INV_BUFSIZE + 10];
71bf99481Ali Bahrami
72bf99481Ali Bahrami	/* Sum the total memory allocated across all the buffers */
73bf99481Ali Bahrami	for (APLIST_TRAVERSE(alp, idx, rcp)) {
74bf99481Ali Bahrami		desc_cnt += rcp->rc_end - rcp->rc_arr;
75bf99481Ali Bahrami		desc_used += rcp->rc_free - rcp->rc_arr;
76bf99481Ali Bahrami	}
77bf99481Ali Bahrami	bytes = desc_cnt * sizeof (Rel_desc);
78bf99481Ali Bahrami
79bf99481Ali Bahrami	dbg_print(lml, MSG_INTL(MSG_STATS_REL_CACHE), title,
80bf99481Ali Bahrami	    EC_WORD(aplist_nitems(alp)),
81bf99481Ali Bahrami	    EC_XWORD(desc_used), EC_XWORD(desc_cnt),
82bf99481Ali Bahrami	    (desc_cnt == 0) ? 100 : EC_WORD((desc_used * 100) / desc_cnt),
83bf99481Ali Bahrami	    EC_XWORD(bytes),
84bf99481Ali Bahrami	    fmt_human_units(bytes, unit_buf, sizeof (unit_buf)));
85bf99481Ali Bahrami}
86bf99481Ali Bahrami
87bf99481Ali Bahrami
88bf99481Ali Bahrami/*
89bf99481Ali Bahrami * Generate a statistics line for the auxiliary relocation descriptor cache.
90bf99481Ali Bahrami *
91bf99481Ali Bahrami * entry:
92bf99481Ali Bahrami *	ofl - output file descriptor
93bf99481Ali Bahrami */
94bf99481Ali Bahramistatic void
95bf99481Ali Bahramirel_aux_cache_statistics(Ofl_desc *ofl)
96bf99481Ali Bahrami{
97bf99481Ali Bahrami	Rel_aux_cachebuf	*racp;
98bf99481Ali Bahrami	Lm_list	*lml = ofl->ofl_lml;
99bf99481Ali Bahrami	size_t	desc_cnt = 0, desc_used = 0, bytes;
100bf99481Ali Bahrami	Aliste	idx;
101bf99481Ali Bahrami	char	unit_buf[CONV_INV_BUFSIZE + 10];
102bf99481Ali Bahrami
103bf99481Ali Bahrami	/* Sum the total memory allocated across all the buffers */
104bf99481Ali Bahrami	for (APLIST_TRAVERSE(ofl->ofl_relaux, idx, racp)) {
105bf99481Ali Bahrami		desc_cnt += racp->rac_end - racp->rac_arr;
106bf99481Ali Bahrami		desc_used += racp->rac_free - racp->rac_arr;
107bf99481Ali Bahrami	}
108bf99481Ali Bahrami	bytes = desc_cnt * sizeof (Rel_desc);
109bf99481Ali Bahrami
110bf99481Ali Bahrami	dbg_print(lml, MSG_INTL(MSG_STATS_REL_ACACHE),
111bf99481Ali Bahrami	    EC_WORD(aplist_nitems(ofl->ofl_relaux)),
112bf99481Ali Bahrami	    EC_XWORD(desc_used), EC_XWORD(desc_cnt),
113bf99481Ali Bahrami	    (desc_cnt == 0) ? 100 : EC_WORD((desc_used * 100) / desc_cnt),
114bf99481Ali Bahrami	    EC_XWORD(bytes),
115bf99481Ali Bahrami	    fmt_human_units(bytes, unit_buf, sizeof (unit_buf)));
116bf99481Ali Bahrami}
117bf99481Ali Bahrami
118bf99481Ali Bahrami
1207c478bdstevel@tonic-gateDbg_statistics_ld(Ofl_desc *ofl)
1225aefb65rie	Lm_list	*lml = ofl->ofl_lml;
1245aefb65rie	if (DBG_NOTCLASS(DBG_C_STATS))
1257c478bdstevel@tonic-gate		return;
1275aefb65rie	Dbg_util_nl(lml, DBG_NL_STD);
1285aefb65rie	dbg_print(lml, MSG_INTL(MSG_STATS_GENERAL));
1307c478bdstevel@tonic-gate	if (ofl->ofl_objscnt || ofl->ofl_soscnt || ofl->ofl_arscnt) {
1315aefb65rie		dbg_print(lml, MSG_INTL(MSG_STATS_FILES),
1327c478bdstevel@tonic-gate		    EC_XWORD(ofl->ofl_objscnt), EC_XWORD(ofl->ofl_soscnt),
1337c478bdstevel@tonic-gate		    EC_XWORD(ofl->ofl_arscnt));
1347c478bdstevel@tonic-gate	}
136c174926rie	if (ofl->ofl_locscnt || ofl->ofl_globcnt) {
1375aefb65rie		dbg_print(lml, MSG_INTL(MSG_STATS_SYMBOLS_OUT),
138c174926rie		    EC_XWORD(ofl->ofl_globcnt), EC_XWORD(ofl->ofl_locscnt));
139c174926rie	}
140c174926rie	if (ofl->ofl_entercnt || ofl->ofl_scopecnt || ofl->ofl_elimcnt) {
1415aefb65rie		dbg_print(lml, MSG_INTL(MSG_STATS_SYMBOLS_IN),
142c174926rie		    EC_XWORD(ofl->ofl_entercnt), EC_XWORD(ofl->ofl_scopecnt),
143c174926rie		    EC_XWORD(ofl->ofl_elimcnt));
1447c478bdstevel@tonic-gate	}
146bf99481Ali Bahrami	dbg_print(lml, MSG_INTL(MSG_STATS_REL_OUT),
147bf99481Ali Bahrami	    EC_XWORD(ofl->ofl_outrels.rc_cnt));
148bf99481Ali Bahrami
149bf99481Ali Bahrami	dbg_print(lml, MSG_INTL(MSG_STATS_REL_IN),
150bf99481Ali Bahrami	    EC_XWORD(ofl->ofl_entrelscnt), EC_XWORD(ofl->ofl_actrels.rc_cnt));
151bf99481Ali Bahrami
152bf99481Ali Bahrami	dbg_print(lml, MSG_INTL(MSG_STATS_REL_TICACHE));
153bf99481Ali Bahrami	rel_cache_statistics(ofl, MSG_INTL(MSG_STATS_REL_TIOUT),
154bf99481Ali Bahrami	    ofl->ofl_outrels.rc_list);
155bf99481Ali Bahrami	rel_cache_statistics(ofl, MSG_INTL(MSG_STATS_REL_TIACT),
156bf99481Ali Bahrami	    ofl->ofl_actrels.rc_list);
157bf99481Ali Bahrami	rel_aux_cache_statistics(ofl);
1617c478bdstevel@tonic-gateDbg_statistics_ar(Ofl_desc *ofl)
16357ef7aaRod Evans	Aliste		idx;
1647c478bdstevel@tonic-gate	Ar_desc		*adp;
1657c478bdstevel@tonic-gate	Elf_Arsym	*arsym;
1667c478bdstevel@tonic-gate	Ar_aux		*aux;
1675aefb65rie	Lm_list		*lml = ofl->ofl_lml;
1707c478bdstevel@tonic-gate		return;
1725aefb65rie	Dbg_util_nl(lml, DBG_NL_STD);
17357ef7aaRod Evans	for (APLIST_TRAVERSE(ofl->ofl_ars, idx, adp)) {
1747c478bdstevel@tonic-gate		size_t	poffset = 0;
1757c478bdstevel@tonic-gate		uint_t	count = 0, used = 0;
1777c478bdstevel@tonic-gate		if ((adp->ad_flags & FLG_ARD_EXTRACT) == 0) {
1785aefb65rie			Dbg_unused_file(lml, adp->ad_name, 0, 0);
1797c478bdstevel@tonic-gate			continue;
1807c478bdstevel@tonic-gate		}
1825aefb65rie		if (DBG_NOTCLASS(DBG_C_STATS))
1837c478bdstevel@tonic-gate			continue;
1857c478bdstevel@tonic-gate		arsym = adp->ad_start;
1867c478bdstevel@tonic-gate		aux = adp->ad_aux;
187ad24f9fToomas Soome		while ((arsym != NULL) && (arsym->as_off != 0)) {
1887c478bdstevel@tonic-gate			/*
1897c478bdstevel@tonic-gate			 * Assume that symbols from the same member file are
1907c478bdstevel@tonic-gate			 * adjacent within the archive symbol table.
1917c478bdstevel@tonic-gate			 */
1927c478bdstevel@tonic-gate			if (poffset != arsym->as_off) {
1937c478bdstevel@tonic-gate				count++;
1947c478bdstevel@tonic-gate				poffset = arsym->as_off;
1957c478bdstevel@tonic-gate				if (aux->au_mem == FLG_ARMEM_PROC)
1967c478bdstevel@tonic-gate					used++;
1977c478bdstevel@tonic-gate			}
1987c478bdstevel@tonic-gate			aux++, arsym++;
1997c478bdstevel@tonic-gate		}
2007c478bdstevel@tonic-gate		if ((count == 0) || (used == 0))
2017c478bdstevel@tonic-gate			continue;
20210a268cRichard Lowe
2035aefb65rie		dbg_print(lml, MSG_INTL(MSG_STATS_AR), adp->ad_name, count,
2045aefb65rie		    used, ((used * 100) / count));
2057c478bdstevel@tonic-gate	}
2065aefb65rie	Dbg_util_nl(lml, DBG_NL_STD);