1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#include	<stdio.h>
28#include	"msg.h"
29#include	"_debug.h"
30#include	"libld.h"
31
32/*
33 * Print out a single `segment descriptor' entry.
34 */
35void
36Dbg_seg_desc_entry(Lm_list *lml, uchar_t osabi, Half mach, int ndx,
37    Sg_desc *sgp, Boolean space_nl)
38{
39	Conv_seg_flags_buf_t	seg_flags_buf;
40	Aliste			idx;
41	Sym_desc		*sdp;
42
43	if (space_nl)
44		Dbg_util_nl(lml, DBG_NL_STD);
45	dbg_print(lml, MSG_ORIG(MSG_SEG_DESC), ndx);
46	if (sgp->sg_name)
47		dbg_print(lml, MSG_ORIG(MSG_SEG_NAME), sgp->sg_name);
48
49	dbg_print(lml, MSG_ORIG(MSG_SEG_FLAGS),
50	    conv_seg_flags(sgp->sg_flags, &seg_flags_buf));
51
52	Elf_phdr(lml, osabi, mach, &sgp->sg_phdr);
53
54	if (sgp->sg_flags & FLG_SG_P_ALIGN)
55		dbg_print(lml, MSG_ORIG(MSG_SEG_ALIGN),
56		    EC_ADDR(sgp->sg_align));
57
58	if (sgp->sg_flags & FLG_SG_LENGTH)
59		dbg_print(lml, MSG_ORIG(MSG_SEG_LENGTH),
60		    EC_ADDR(sgp->sg_length));
61
62	if (sgp->sg_flags & FLG_SG_ROUND)
63		dbg_print(lml, MSG_ORIG(MSG_SEG_ROUND),
64		    EC_ADDR(sgp->sg_round));
65
66	if (aplist_nitems(sgp->sg_sizesym) > 0) {
67		dbg_print(lml, MSG_ORIG(MSG_SEG_SIZESYM_TITLE));
68		for (APLIST_TRAVERSE(sgp->sg_sizesym, idx, sdp))
69			if (sdp->sd_name)
70				dbg_print(lml, MSG_ORIG(MSG_SEG_SIZESYM),
71				    Dbg_demangle_name(sdp->sd_name));
72	}
73	if (aplist_nitems(sgp->sg_is_order) > 0) {
74		Aliste		idx;
75		Ent_desc	*enp;
76
77		dbg_print(lml, MSG_ORIG(MSG_SEG_IS_ORDER_TITLE));
78		for (APLIST_TRAVERSE(sgp->sg_is_order, idx, enp))
79			dbg_print(lml, MSG_ORIG(MSG_SEG_LIST_ITEM),
80			    enp->ec_name);
81	}
82	if (alist_nitems(sgp->sg_os_order) > 0) {
83		Aliste		idx;
84		Sec_order	*scop;
85
86		dbg_print(lml, MSG_ORIG(MSG_SEG_OS_ORDER_TITLE));
87		for (ALIST_TRAVERSE(sgp->sg_os_order, idx, scop))
88			dbg_print(lml, MSG_ORIG(MSG_SEG_LIST_ITEM),
89			    scop->sco_secname);
90	}
91	if (space_nl)
92		Dbg_util_nl(lml, DBG_NL_STD);
93}
94
95void
96Dbg_seg_title(Lm_list *lml)
97{
98	if (DBG_NOTCLASS(DBG_C_SEGMENTS))
99		return;
100
101	Dbg_util_nl(lml, DBG_NL_STD);
102	dbg_print(lml, MSG_INTL(MSG_SEG_DESC_INUSE));
103}
104
105void
106Dbg_seg_entry(Ofl_desc *ofl, int ndx, Sg_desc *sgp)
107{
108	if (DBG_NOTCLASS(DBG_C_SEGMENTS))
109		return;
110
111	Dbg_seg_desc_entry(ofl->ofl_lml, ofl->ofl_dehdr->e_ident[EI_OSABI],
112	    ofl->ofl_dehdr->e_machine, ndx, sgp, TRUE);
113}
114
115/*
116 * Print out the available segment descriptors.
117 */
118void
119Dbg_seg_list(Lm_list *lml, uchar_t osabi, Half mach, APlist *apl)
120{
121	Aliste		idx;
122	Sg_desc		*sgp;
123	int		ndx = 0;
124
125	if (DBG_NOTCLASS(DBG_C_SEGMENTS))
126		return;
127
128	Dbg_util_nl(lml, DBG_NL_STD);
129	dbg_print(lml, MSG_INTL(MSG_SEG_DESC_AVAIL));
130	for (APLIST_TRAVERSE(apl, idx, sgp))
131		Dbg_seg_desc_entry(lml, osabi, mach, ndx++, sgp, TRUE);
132}
133
134/*
135 * Print the output section information.  This includes the section header
136 * information and the output elf buffer information.  If the detail flag is
137 * set, traverse the input sections displaying all the input buffers that
138 * have been concatenated to form this output buffer.
139 */
140void
141Dbg_seg_os(Ofl_desc *ofl, Os_desc *osp, int ndx)
142{
143	Conv_inv_buf_t	inv_buf;
144	Lm_list		*lml = ofl->ofl_lml;
145	Aliste		idx;
146	Is_desc		*isp;
147	Elf_Data	*data;
148	Shdr		*shdr;
149	const char	*empty = MSG_ORIG(MSG_STR_EMPTY);
150	int		os_isdescs_idx;
151
152	if (DBG_NOTCLASS(DBG_C_SEGMENTS))
153		return;
154
155	dbg_print(lml, MSG_ORIG(MSG_SEC_NAME), ndx, osp->os_name);
156	Elf_shdr(lml, ofl->ofl_dehdr->e_ident[EI_OSABI],
157	    ofl->ofl_dehdr->e_machine, osp->os_shdr);
158	dbg_print(lml, MSG_INTL(MSG_EDATA_TITLE));
159
160	shdr = osp->os_shdr;
161	data = osp->os_outdata;
162	dbg_print(lml, MSG_INTL(MSG_EDATA_ENTRY), MSG_INTL(MSG_STR_OUT),
163	    EC_ADDR(shdr->sh_addr), conv_elfdata_type(data->d_type, &inv_buf),
164	    EC_XWORD(data->d_size), EC_OFF(data->d_off),
165	    EC_XWORD(data->d_align), empty, empty, empty);
166
167	if (DBG_NOTDETAIL())
168		return;
169
170	OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx, isp) {
171		dbg_isec_name_buf_t	buf;
172		char			*alloc_mem;
173		const char		*file, *str;
174		Addr			addr;
175
176		data = isp->is_indata;
177
178		if (isp->is_flags & FLG_IS_DISCARD) {
179			str = MSG_INTL(MSG_EDATA_IGNSCN);
180			addr = 0;
181		} else {
182			str = empty;
183			addr = (Addr)(shdr->sh_addr + data->d_off);
184		}
185
186		if (isp->is_file && isp->is_file->ifl_name)
187			file = isp->is_file->ifl_name;
188		else
189			file = empty;
190
191		dbg_print(lml, MSG_INTL(MSG_EDATA_ENTRY), MSG_INTL(MSG_STR_IN),
192		    EC_ADDR(addr), conv_elfdata_type(data->d_type, &inv_buf),
193		    EC_XWORD(data->d_size), EC_OFF(data->d_off),
194		    EC_XWORD(data->d_align), file,
195		    dbg_fmt_isec_name(isp, buf, &alloc_mem), str);
196		if (alloc_mem != NULL)
197			free(alloc_mem);
198	}
199}
200