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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26#include	<stdio.h>
27#include	<debug.h>
28#include	<libld.h>
29#include	<conv.h>
30#include	"msg.h"
31#include	"_debug.h"
32
33void
34Dbg_cap_candidate(Lm_list *lml, const char *name)
35{
36	if (DBG_NOTCLASS(DBG_C_CAP | DBG_C_FILES))
37		return;
38
39	dbg_print(lml, MSG_INTL(MSG_CAP_CANDIDATE), name);
40}
41
42void
43Dbg_cap_filter(Lm_list *lml, const char *dir, Rt_map *flmp)
44{
45	if (DBG_NOTCLASS(DBG_C_CAP | DBG_C_FILES))
46		return;
47
48	Dbg_util_nl(lml, DBG_NL_STD);
49	if (flmp)
50		dbg_print(lml, MSG_INTL(MSG_CAP_FILTER_1), dir, NAME(flmp));
51	else
52		dbg_print(lml, MSG_INTL(MSG_CAP_FILTER_2), dir);
53}
54
55void
56Dbg_cap_identical(Lm_list *lml, const char *file1, const char *file2)
57{
58	if (DBG_NOTCLASS(DBG_C_CAP | DBG_C_FILES))
59		return;
60
61	dbg_print(lml, MSG_INTL(MSG_CAP_IDENTICAL), file1, file2);
62}
63
64void
65Dbg_cap_val(Lm_list *lml, Syscapset *sys, Syscapset *alt, Half mach)
66{
67	Conv_cap_val_buf_t	cap_val_buf;
68
69	if ((sys->sc_plat == NULL) && (sys->sc_mach == NULL) &&
70	    (sys->sc_hw_2 == 0) && (sys->sc_hw_1 == 0) &&
71	    (sys->sc_sf_1 == 0))
72		return;
73
74	Dbg_util_nl(lml, DBG_NL_FRC);
75
76	/*
77	 * Print any capabilities in precedence order.
78	 */
79	if (sys->sc_plat) {
80		dbg_print(lml, MSG_INTL(MSG_CAP_SYS_PLAT), sys->sc_plat);
81	}
82	if (sys->sc_mach) {
83		dbg_print(lml, MSG_INTL(MSG_CAP_SYS_MACH), sys->sc_mach);
84	}
85	if (sys->sc_hw_2) {
86		dbg_print(lml, MSG_INTL(MSG_CAP_SYS_HW_2),
87		    conv_cap_val_hw2(sys->sc_hw_2, mach, 0,
88		    &cap_val_buf.cap_val_hw2_buf));
89	}
90	if (sys->sc_hw_1) {
91		dbg_print(lml, MSG_INTL(MSG_CAP_SYS_HW_1),
92		    conv_cap_val_hw1(sys->sc_hw_1, mach, 0,
93		    &cap_val_buf.cap_val_hw1_buf));
94	}
95	if (sys->sc_sf_1) {
96		dbg_print(lml, MSG_INTL(MSG_CAP_SYS_SF_1),
97		    conv_cap_val_sf1(sys->sc_sf_1, mach, 0,
98		    &cap_val_buf.cap_val_sf1_buf));
99	}
100
101	if (alt != sys) {
102		Dbg_util_nl(lml, DBG_NL_FRC);
103		if (alt->sc_plat != sys->sc_plat) {
104			dbg_print(lml, MSG_INTL(MSG_CAP_ALT_PLAT),
105			    alt->sc_plat);
106		}
107		if (alt->sc_mach != sys->sc_mach) {
108			dbg_print(lml, MSG_INTL(MSG_CAP_ALT_MACH),
109			    alt->sc_mach);
110		}
111		if (alt->sc_hw_2 != sys->sc_hw_2) {
112			dbg_print(lml, MSG_INTL(MSG_CAP_ALT_HW_2),
113			    conv_cap_val_hw2(alt->sc_hw_2, mach, 0,
114			    &cap_val_buf.cap_val_hw2_buf));
115		}
116		if (alt->sc_hw_1 != sys->sc_hw_1) {
117			dbg_print(lml, MSG_INTL(MSG_CAP_ALT_HW_1),
118			    conv_cap_val_hw1(alt->sc_hw_1, mach, 0,
119			    &cap_val_buf.cap_val_hw1_buf));
120		}
121		if (alt->sc_sf_1 != sys->sc_sf_1) {
122			dbg_print(lml, MSG_INTL(MSG_CAP_ALT_SF_1),
123			    conv_cap_val_sf1(alt->sc_sf_1, mach, 0,
124			    &cap_val_buf.cap_val_sf1_buf));
125		}
126	}
127
128	Dbg_util_nl(lml, DBG_NL_FRC);
129}
130
131/*
132 * This version takes a pointer to a Capmask, and will report the exclusion
133 * bits if they exist.
134 */
135void
136Dbg_cap_ptr_entry(Lm_list *lml, dbg_state_t dbg_state, Xword tag,
137    const char *ptr)
138{
139	Conv_inv_buf_t		inv_buf;
140
141	if (DBG_NOTCLASS(DBG_C_CAP))
142		return;
143
144	dbg_print(lml, MSG_INTL(MSG_CAP_SEC_ENTRY), Dbg_state_str(dbg_state),
145	    conv_cap_tag(tag, 0, &inv_buf), ptr);
146}
147
148/*
149 * This version takes a pointer to a CapMask, and will report the exclusion
150 * bits if they exist.
151 */
152void
153Dbg_cap_val_entry(Lm_list *lml, dbg_state_t dbg_state, Xword tag, Xword val,
154    Half mach)
155{
156	Conv_inv_buf_t		inv_buf;
157	Conv_cap_val_buf_t	cap_val_buf;
158
159	if (DBG_NOTCLASS(DBG_C_CAP))
160		return;
161
162	dbg_print(lml, MSG_INTL(MSG_CAP_SEC_ENTRY), Dbg_state_str(dbg_state),
163	    conv_cap_tag(tag, 0, &inv_buf), conv_cap_val(tag, val, mach, 0,
164	    &cap_val_buf));
165}
166
167void
168Dbg_cap_sec_title(Lm_list *lml, const char *name)
169{
170	if (DBG_NOTCLASS(DBG_C_CAP))
171		return;
172
173	Dbg_util_nl(lml, DBG_NL_STD);
174	dbg_print(lml, MSG_INTL(MSG_CAP_SEC_TITLE), name);
175}
176
177void
178Dbg_cap_mapfile_title(Lm_list *lml, Lineno lineno)
179{
180	if (DBG_NOTCLASS(DBG_C_MAP | DBG_C_CAP))
181		return;
182
183	dbg_print(lml, MSG_INTL(MSG_MAP_CAP), EC_LINENO(lineno));
184}
185
186void
187Dbg_cap_id(Lm_list *lml, Lineno lineno, const char *oid, const char *nid)
188{
189	Dbg_cap_mapfile_title(lml, lineno);
190	Dbg_cap_ptr_entry(lml, DBG_STATE_CURRENT, CA_SUNW_ID, oid);
191	Dbg_cap_ptr_entry(lml, DBG_STATE_NEW, CA_SUNW_ID, nid);
192	Dbg_cap_ptr_entry(lml, DBG_STATE_RESOLVED, CA_SUNW_ID, nid);
193}
194
195void
196Dbg_cap_post_title(Lm_list *lml, int *title)
197{
198	if (DBG_NOTCLASS(DBG_C_CAP))
199		return;
200
201	Dbg_util_nl(lml, DBG_NL_STD);
202	if ((*title)++ == 0)
203		dbg_print(lml, MSG_INTL(MSG_CAP_POST_TITLE));
204}
205
206void
207Elf_cap_title(Lm_list *lml)
208{
209	dbg_print(lml, MSG_INTL(MSG_CAP_ELF_TITLE));
210}
211
212void
213Elf_cap_entry(Lm_list *lml, Cap *cap, int ndx, const char *str, size_t str_size,
214    Half mach)
215{
216	Conv_inv_buf_t		inv_buf;
217	Conv_cap_val_buf_t	cap_val_buf;
218	char			index[INDEX_STR_SIZE];
219
220	(void) snprintf(index, INDEX_STR_SIZE, MSG_ORIG(MSG_FMT_INDEX), ndx);
221
222	switch (cap->c_tag) {
223	case CA_SUNW_PLAT:
224	case CA_SUNW_MACH:
225	case CA_SUNW_ID:
226		/* If offset is in range, format as a string */
227		if (str && (cap->c_un.c_ptr < str_size)) {
228			str += cap->c_un.c_ptr;
229			break;
230		}
231		/*FALLTHROUGH*/
232	default:
233		/* Format numerically */
234		str = conv_cap_val(cap->c_tag, cap->c_un.c_val, mach, 0,
235		    &cap_val_buf);
236	}
237
238	dbg_print(lml, MSG_INTL(MSG_CAP_ELF_ENTRY), index,
239	    conv_cap_tag(cap->c_tag, 0, &inv_buf), str);
240}
241