globals.c revision 9273:9a0603d78ad3
194575Sdes/*
294575Sdes * CDDL HEADER START
394575Sdes *
494575Sdes * The contents of this file are subject to the terms of the
594575Sdes * Common Development and Distribution License (the "License").
694575Sdes * You may not use this file except in compliance with the License.
794575Sdes *
894575Sdes * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
994575Sdes * or http://www.opensolaris.org/os/licensing.
1094575Sdes * See the License for the specific language governing permissions
1194575Sdes * and limitations under the License.
1294575Sdes *
1394575Sdes * When distributing Covered Code, include this CDDL HEADER in each
1494575Sdes * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1594575Sdes * If applicable, add the following below this CDDL HEADER, with the
1694575Sdes * fields enclosed by brackets "[]" replaced with your own identifying
1794575Sdes * information: Portions Copyright [yyyy] [name of copyright owner]
1894575Sdes *
1994575Sdes * CDDL HEADER END
2094575Sdes */
2194575Sdes
2294575Sdes/*
2394575Sdes * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2494575Sdes * Use is subject to license terms.
2594575Sdes */
2694575Sdes
2794575Sdes#include	<stdio.h>
2894575Sdes#include	<strings.h>
2994575Sdes#include	<ctype.h>
3094575Sdes#include	<_machelf.h>
3194575Sdes#include	"_conv.h"
3294575Sdes#include	"globals_msg.h"
3394575Sdes
3494575Sdes
3594575Sdes/*
3694575Sdes * Map an integer into a descriptive string.
3794577Sdes *
3894577Sdes * entry:
3994577Sdes *	inv_buf - A buffer into which this routine can format
4094577Sdes *		a result string, if necessary.
4194575Sdes *	val - The value for which a string is desired.
4294575Sdes *	flags - CONV_FMT_* values to be passed to conv_invalid_val() if
4394577Sdes *		necessary. The caller is reponsible for having examined
4494577Sdes *		the CONV_FMT_ALT_* part of flags and passing the proper
4594575Sdes *		msg array.
4694575Sdes *	num_msg - # of Msg entries in msg.
4794575Sdes *	msg - Array of num_msg Msg items corresponding to the possible
4894577Sdes *		strings corresponding to val.
4994575Sdes *	local_sgs_msg - Message string table from module from which
5094575Sdes *		this function is called.
5194575Sdes *
5294575Sdes * exit:
5394575Sdes *	If val lies in the range [0-(num_msg-1)], then the string
5494577Sdes *	corresponding to it is returned. If val is outside the range,
5594575Sdes *	conv_invalid_val() is called to format an ASCII representation
5694577Sdes *	of it into inv_buf, and that is returned.
5794577Sdes */
5894577Sdes/*ARGSUSED5*/
5994575Sdesstatic const char *
6094575Sdesmap_msg2str(Conv_inv_buf_t *inv_buf, Conv_elfvalue_t val,
6194575Sdes    Conv_fmt_flags_t flags, size_t num_msg, const Msg *msg,
6294577Sdes    const char *local_sgs_msg)
6394577Sdes{
6494575Sdes	if ((val < num_msg) && (msg[val] != 0))
6594575Sdes		return (MSG_ORIG_STRTAB(msg[val], local_sgs_msg));
6694575Sdes
6794575Sdes	/* If we get here, it's an unknown value */
6894575Sdes	return (conv_invalid_val(inv_buf, val, flags));
6994575Sdes}
7094575Sdes
7194575Sdes/*
7294577Sdes * Map an integer into a descriptive string from a NULL terminated
7394577Sdes * array of Val_desc or Val_desc2 descriptors.
7494577Sdes *
7594577Sdes * entry:
7694577Sdes *	inv_buf - A buffer into which this routine can format
7794577Sdes *		a result string, if necessary.
7894577Sdes *	osabi,mach (_conv_vd22str only) - The osab/mach under which
7994577Sdes *		val is to be interpreted. Items with a non-0 osabi or machine
8094577Sdes *		that do not match are quietly ignored.
8194577Sdes *	val - The value for which a string is desired.
8294577Sdes *	flags - CONV_FMT_* values to be passed to conv_invalid_val() if
8394577Sdes *		necessary. The caller is reponsible for having examined
8494577Sdes *		the CONV_FMT_ALT_* part of flags and passing the proper
8594577Sdes *		descriptor array.
8694577Sdes *	vdp - Pointer to NULL terminated array of Val_desc descriptors.
8794577Sdes *	local_sgs_msg - Message string table from module from which
8894577Sdes *		this function is called.
8994577Sdes *
9094577Sdes * exit:
9194577Sdes *	If val is found in the vdp array, and in the osabi version of
9294577Sdes *	this function if the osabi matches, then the string corresponding
9394577Sdes *	val is returned. If a string for val is not found, conv_invalid_val()
9494577Sdes *	is called to format an ASCII representation of it into inv_buf, and
9594577Sdes *	that is returned.
9694577Sdes */
9794577Sdes/*ARGSUSED4*/
9894577Sdesstatic const char *
9994577Sdesmap_vd2str(Conv_inv_buf_t *inv_buf, Conv_elfvalue_t val,
10094577Sdes    Conv_fmt_flags_t flags, const Val_desc *vdp, const char *local_sgs_msg)
10194577Sdes{
10294577Sdes	for (; vdp->v_msg; vdp++) {
10394577Sdes		if (val == vdp->v_val)
10494577Sdes			return (MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg));
10594577Sdes	}
10694577Sdes
10794577Sdes	/* If we get here, it's an unknown value */
10894577Sdes	return (conv_invalid_val(inv_buf, val, flags));
10994577Sdes}
11094577Sdes
11194577Sdes/*ARGSUSED6*/
11294577Sdesstatic const char *
11394577Sdesmap_vd22str(Conv_inv_buf_t *inv_buf, uchar_t osabi, Half mach,
11494577Sdes    Conv_elfvalue_t val, Conv_fmt_flags_t flags, const Val_desc2 *vdp,
11594577Sdes    const char *local_sgs_msg)
11694577Sdes{
11794577Sdes	for (; vdp->v_msg; vdp++) {
11894577Sdes		if (CONV_VD2_SKIP(osabi, mach, vdp))
11994577Sdes			continue;
12094577Sdes
12194577Sdes		if (val == vdp->v_val)
12294577Sdes			return (MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg));
12394577Sdes	}
12494577Sdes
12594577Sdes	/* If we get here, it's an unknown value */
12694577Sdes	return (conv_invalid_val(inv_buf, val, flags));
12794577Sdes}
12894577Sdes
12994577Sdes/*
13094577Sdes * Process an array of conv_ds_XXX_t structures and call the appropriate
13194577Sdes * map functions for the format of the strings given.
13294577Sdes */
13394577Sdesconst char *
13494577Sdes_conv_map_ds(uchar_t osabi, Half mach, Conv_elfvalue_t value,
13594577Sdes    const conv_ds_t **dsp, Conv_fmt_flags_t fmt_flags, Conv_inv_buf_t *inv_buf,
13694577Sdes    const char *local_sgs_msg)
13794577Sdes{
13894577Sdes	const conv_ds_t *ds;
13994577Sdes
14094577Sdes	for (ds = *dsp; ds != NULL; ds = *(++dsp)) {
14194577Sdes		if ((value < ds->ds_baseval) || (value > ds->ds_topval))
14294577Sdes			continue;
14394577Sdes
14494577Sdes		switch (ds->ds_type) {
14594577Sdes		case CONV_DS_MSGARR:
14694577Sdes			return (map_msg2str(inv_buf, value - ds->ds_baseval,
14794577Sdes			    fmt_flags, ds->ds_topval - ds->ds_baseval + 1,
14894577Sdes			    /*LINTED*/
14994577Sdes			    ((conv_ds_msg_t *)ds)->ds_msg,
15094577Sdes			    local_sgs_msg));
15194577Sdes
15294577Sdes		case CONV_DS_VD:
15394577Sdes			return (map_vd2str(inv_buf, value, fmt_flags,
15494577Sdes			    /*LINTED*/
15594577Sdes			    ((conv_ds_vd_t *)ds)->ds_vd,
15694577Sdes			    local_sgs_msg));
15794577Sdes
15894577Sdes		case CONV_DS_VD2:
15994577Sdes			return (map_vd22str(inv_buf, osabi, mach, value,
16094577Sdes			    fmt_flags,
16194577Sdes			    /*LINTED*/
16294577Sdes			    ((conv_ds_vd2_t *)ds)->ds_vd2,
16394577Sdes			    local_sgs_msg));
16494577Sdes		}
16594577Sdes	}
16694577Sdes
16794577Sdes	return (conv_invalid_val(inv_buf, value, fmt_flags));
16894577Sdes}
16994577Sdes
17094577Sdes/*
17194577Sdes * Iterate over every message string in a given array of Msg codes,
17294577Sdes * calling a user supplied callback for each one.
17394577Sdes *
17494577Sdes * entry:
17594577Sdes *	basevalue - Value corresponding to the first Msg in the array.
17694577Sdes *	local_sgs_msg - Pointer to the __sgs_msg array for the
17794577Sdes *		libconv module making the call.
17894577Sdes *	num_msg - # of items in array referenced by msg
17994577Sdes *	msg - Array of Msg indexes for the strings to iterate over.
18094577Sdes *		The value corresponding to each element of msg must be:
18194577Sdes *			value[i] = basevalue + i
18294577Sdes *	func, uvalue - User supplied function to be called for each
18394577Sdes *		string in msg. uvalue is an arbitrary user supplied pointer
18494577Sdes *		to be passed to func.
18594577Sdes *	local_sgs_msg - Pointer to the __sgs_msg array for the
18694577Sdes *		libconv module making the call.
18794577Sdes *
18894577Sdes * exit:
18994577Sdes *	The callback function is called for every non-zero item in
19094577Sdes *	msg[]. If any callback returns CONV_ITER_DONE, execution stops
19194577Sdes *	with that item and the function returns immediately. Otherwise,
19294577Sdes *	it continues to the end of the array.
19394577Sdes *
19494577Sdes *	The value from the last callback is returned.
19594577Sdes */
19694577Sdes/*ARGSUSED5*/
19794577Sdesstatic conv_iter_ret_t
19894577Sdes_conv_iter_msgarr(uint32_t basevalue, const Msg *msg, size_t num_msg,
19994577Sdes    conv_iter_cb_t func, void *uvalue, const char *local_sgs_msg)
20094577Sdes{
20194575Sdes	for (; num_msg-- > 0; basevalue++, msg++) {
20294575Sdes		if (*msg != 0)
20394575Sdes			if ((* func)(MSG_ORIG_STRTAB(*msg, local_sgs_msg),
20494575Sdes			    basevalue, uvalue) == CONV_ITER_DONE)
20594575Sdes				return (CONV_ITER_DONE);
20694575Sdes	}
20794575Sdes
20894575Sdes	return (CONV_ITER_CONT);
20994575Sdes}
21094575Sdes
21194575Sdes/*
21294575Sdes * Iterate over every message string in a given array of Val_desc or
21394575Sdes * Val_desc2 descriptors, calling a user supplied callback for each one.
21494575Sdes *
21594575Sdes * entry:
21694575Sdes *	osabi,mach (_conv_iter_vd2 only) - The osabi/mach for which
21794575Sdes *		strings are desired. Strings with a non-0 osabi or machine
21894575Sdes *		that do not match are quietly ignored.
21994575Sdes *	vdp - Pointer to NULL terminated array of Val_desc descriptors.
22094575Sdes *	func, uvalue - User supplied function to be called for each
22194575Sdes *		string in msg. uvalue is an arbitrary user supplied pointer
22294575Sdes *		to be passed to func.
22394575Sdes *	local_sgs_msg - Pointer to the __sgs_msg array for the
22494575Sdes *		libconv module making the call.
22594575Sdes *
22694575Sdes * exit:
22794575Sdes *	The callback function is called for every descriptor referenced by
22894575Sdes *	vdp. In the case of the OSABI-version of this function, strings from
22994575Sdes *	the wrong osabi are not used. If any callback returns CONV_ITER_DONE,
23094575Sdes *	execution stops with that item and the function returns immediately.
23194575Sdes *	Otherwise, it continues to the end of the array.
23294575Sdes *
23394575Sdes *	The value from the last callback is returned.
23494575Sdes */
23594575Sdes/*ARGSUSED3*/
23694575Sdesconv_iter_ret_t
23794575Sdes_conv_iter_vd(const Val_desc *vdp, conv_iter_cb_t func, void *uvalue,
23894575Sdes    const char *local_sgs_msg)
23994575Sdes{
24094575Sdes	for (; vdp->v_msg; vdp++) {
24194575Sdes		if ((* func)(MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg),
24294575Sdes		    vdp->v_val, uvalue) == CONV_ITER_DONE)
24394575Sdes			return (CONV_ITER_DONE);
24494575Sdes	}
24594575Sdes
24694575Sdes	return (CONV_ITER_CONT);
24794575Sdes}
24894575Sdes
24994575Sdes/*ARGSUSED5*/
25094575Sdesconv_iter_ret_t
25194575Sdes_conv_iter_vd2(conv_iter_osabi_t osabi, Half mach, const Val_desc2 *vdp,
25294575Sdes    conv_iter_cb_t func, void *uvalue, const char *local_sgs_msg)
25394575Sdes{
25494575Sdes	for (; vdp->v_msg; vdp++) {
25594575Sdes		if (CONV_ITER_VD2_SKIP(osabi, mach, vdp))
25694575Sdes			continue;
25794575Sdes
25894575Sdes		if ((* func)(MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg),
25994575Sdes		    vdp->v_val, uvalue) == CONV_ITER_DONE)
26094575Sdes			return (CONV_ITER_DONE);
26194575Sdes	}
26294575Sdes
26394575Sdes	return (CONV_ITER_CONT);
26494575Sdes}
26594575Sdes
26694575Sdes/*
26794575Sdes * Process an array of conv_ds_XXX_t structures and call the appropriate
268 * iteration functions for the format of the strings given.
269 */
270conv_iter_ret_t
271_conv_iter_ds(conv_iter_osabi_t osabi, Half mach, const conv_ds_t **dsp,
272    conv_iter_cb_t func, void *uvalue, const char *local_sgs_msg)
273{
274	const conv_ds_t *ds;
275
276	for (ds = *dsp; ds != NULL; ds = *(++dsp)) {
277		switch (ds->ds_type) {
278		case CONV_DS_MSGARR:
279			if (_conv_iter_msgarr(ds->ds_baseval,
280			    /*LINTED*/
281			    ((conv_ds_msg_t *)ds)->ds_msg,
282			    ds->ds_topval - ds->ds_baseval + 1, func, uvalue,
283			    local_sgs_msg) == CONV_ITER_DONE)
284				return (CONV_ITER_DONE);
285			break;
286
287		case CONV_DS_VD:
288			/*LINTED*/
289			if (_conv_iter_vd(((conv_ds_vd_t *)ds)->ds_vd,
290			    func, uvalue, local_sgs_msg) == CONV_ITER_DONE)
291				return (CONV_ITER_DONE);
292			break;
293
294		case CONV_DS_VD2:
295			if (_conv_iter_vd2(osabi, mach,
296			    /*LINTED*/
297			    ((conv_ds_vd2_t *)ds)->ds_vd2,
298			    func, uvalue, local_sgs_msg) == CONV_ITER_DONE)
299				return (CONV_ITER_DONE);
300			break;
301		}
302	}
303
304	return (CONV_ITER_CONT);
305}
306
307/*
308 * Initialize the uvalue block prior to use of an interation function
309 * employing conv_iter_strtol().
310 *
311 * entry:
312 *	str - String to be matched to a value
313 *	uvalue - Pointer to uninitialized uvalue block
314 *
315 * exit:
316 *	Initializes the uvalue block for use. Returns True (1) if a non-empty
317 *	string was supplied, and False (0).
318 */
319int
320conv_iter_strtol_init(const char *str, conv_strtol_uvalue_t *uvalue)
321{
322	const char	*tail;
323
324	while (isspace(*str))
325		str++;
326	uvalue->csl_str = str;
327	uvalue->csl_found = 0;
328
329	tail = str + strlen(str);
330	while ((tail > str) && isspace(*(tail - 1)))
331		tail--;
332	uvalue->csl_strlen = tail - str;
333
334	return (uvalue->csl_strlen > 0);
335}
336
337/*
338 * conv_iter_strtol() is used with iteration functions to map a string
339 * to the value of its corresponding ELF constant.
340 *
341 * entry:
342 *	str - String supplied by this iteration
343 *	value - Value of ELF constant corresponding to str
344 *	uvalue - Pointer to conv_strtol_uvalue_t block previously
345 *		initialized by a call to conv_iter_strtol_init().
346 */
347conv_iter_ret_t
348conv_iter_strtol(const char *str, uint32_t value, void *uvalue)
349{
350	conv_strtol_uvalue_t *state = (conv_strtol_uvalue_t *)uvalue;
351
352	if ((strlen(str) == state->csl_strlen) &&
353	    (strncasecmp(str, state->csl_str, state->csl_strlen) == 0)) {
354		state->csl_found = 1;
355		state->csl_value = value;
356		return (CONV_ITER_DONE);	/* Found it. Stop now. */
357	}
358
359	return (CONV_ITER_CONT);		/* Keep looking */
360}
361