9804 hal-set-property should support --direct option
[unleashed.git] / usr / src / cmd / dis / dis_list.c
blob46b3ccd9db185d7d39438c7fcff900076bd25d50
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <stddef.h>
30 #include <stdlib.h>
31 #include <string.h>
33 #include "dis_target.h"
34 #include "dis_list.h"
35 #include "dis_util.h"
38 * List support functions.
40 * Support routines for managing lists of sections and functions. We first
41 * process the command line arguments into lists of strings. For each target,
42 * we resolve these strings against the set of available sections and/or
43 * functions to arrive at the set of objects to disassemble.
45 * We export two types of lists, namelists and resolvelists. The first is used
46 * to record names given as command line options. The latter is used to
47 * maintain the data objects specific to a given target.
50 typedef struct unresolved_name {
51 const char *un_name; /* name of function or object */
52 int un_value; /* user-supplied data */
53 int un_mark; /* internal counter */
54 uu_list_node_t un_node; /* uulist node */
55 } unresolved_name_t;
57 typedef struct resolved_name {
58 void *rn_data; /* section or function data */
59 int rn_value; /* user-supplied data */
60 uu_list_node_t rn_node; /* uulist node */
61 } resolved_name_t;
63 static uu_list_pool_t *unresolved_pool;
64 static uu_list_pool_t *resolved_pool;
65 static int current_mark = 0;
67 static void
68 initialize_pools(void)
70 unresolved_pool = uu_list_pool_create(
71 "unresolved_pool", sizeof (unresolved_name_t),
72 offsetof(unresolved_name_t, un_node), NULL, 0);
73 resolved_pool = uu_list_pool_create(
74 "resolved_pool", sizeof (resolved_name_t),
75 offsetof(resolved_name_t, rn_node), NULL, 0);
77 if (unresolved_pool == NULL ||
78 resolved_pool == NULL)
79 die("out of memory");
83 * Returns an empty list of unresolved names.
85 dis_namelist_t *
86 dis_namelist_create(void)
88 uu_list_t *listp;
91 * If this is the first request to create a list, initialize the list
92 * pools.
94 if (unresolved_pool == NULL)
95 initialize_pools();
97 if ((listp = uu_list_create(unresolved_pool, NULL, 0)) == NULL)
98 die("out of memory");
100 return (listp);
104 * Adds the given name to the unresolved list. 'value' is an arbitrary value
105 * which is preserved for this entry, even when resolved against a target. This
106 * allows the caller to associate similar behavior (such as the difference
107 * between -d, -D, and -s) without having to create multiple lists.
109 void
110 dis_namelist_add(dis_namelist_t *list, const char *name, int value)
112 unresolved_name_t *node;
114 node = safe_malloc(sizeof (unresolved_name_t));
116 node->un_name = name;
117 node->un_value = value;
118 node->un_mark = 0;
120 (void) uu_list_insert_before(list, NULL, node);
124 * Internal callback structure used
126 typedef struct cb_data {
127 int cb_mark;
128 uu_list_t *cb_source;
129 uu_list_t *cb_resolved;
130 } cb_data_t;
133 * For each section, walk the list of unresolved names and resolve those that
134 * correspond to real functions. We mark functions as we see them, and re-walk
135 * the list a second time to warn about functions we didn't find.
137 * This is an O(n * m) algorithm, but we typically search for only a single
138 * function.
140 /* ARGSUSED */
141 static void
142 walk_sections(dis_tgt_t *tgt, dis_scn_t *scn, void *data)
144 cb_data_t *cb = data;
145 unresolved_name_t *unp;
146 uu_list_walk_t *walk;
148 if ((walk = uu_list_walk_start(cb->cb_source, UU_DEFAULT)) == NULL)
149 die("out of memory");
151 while ((unp = uu_list_walk_next(walk)) != NULL) {
152 if (strcmp(unp->un_name, dis_section_name(scn)) == 0) {
153 resolved_name_t *resolved;
156 * Mark the current node as seen
158 unp->un_mark = cb->cb_mark;
161 * Add the data to the resolved list
163 resolved = safe_malloc(sizeof (resolved_name_t));
165 resolved->rn_data = dis_section_copy(scn);
166 resolved->rn_value = unp->un_value;
168 (void) uu_list_insert_before(cb->cb_resolved, NULL,
169 resolved);
173 uu_list_walk_end(walk);
177 * Take a list of unresolved names and create a resolved list of sections. We
178 * rely on walk_sections() to do the dirty work. After resolving the sections,
179 * we check for any unmarked names and warn the user about missing sections.
181 dis_scnlist_t *
182 dis_namelist_resolve_sections(dis_namelist_t *namelist, dis_tgt_t *tgt)
184 uu_list_t *listp;
185 cb_data_t cb;
186 unresolved_name_t *unp;
187 uu_list_walk_t *walk;
190 * Walk all sections in the target, calling walk_sections() for each
191 * one.
193 if ((listp = uu_list_create(resolved_pool, NULL, UU_DEFAULT)) == NULL)
194 die("out of memory");
196 cb.cb_mark = ++current_mark;
197 cb.cb_source = namelist;
198 cb.cb_resolved = listp;
200 dis_tgt_section_iter(tgt, walk_sections, &cb);
203 * Walk all elements of the unresolved list, and report any that we
204 * didn't mark in the process.
206 if ((walk = uu_list_walk_start(namelist, UU_DEFAULT)) == NULL)
207 die("out of memory");
209 while ((unp = uu_list_walk_next(walk)) != NULL) {
210 if (unp->un_mark != current_mark)
211 warn("failed to find section '%s' in '%s'",
212 unp->un_name, dis_tgt_name(tgt));
215 uu_list_walk_end(walk);
217 return (listp);
221 * Similar to walk_sections(), but for functions.
223 /* ARGSUSED */
224 static void
225 walk_functions(dis_tgt_t *tgt, dis_func_t *func, void *data)
227 cb_data_t *cb = data;
228 unresolved_name_t *unp;
229 uu_list_walk_t *walk;
231 if ((walk = uu_list_walk_start(cb->cb_source, UU_DEFAULT)) == NULL)
232 die("out of memory");
234 while ((unp = uu_list_walk_next(walk)) != NULL) {
235 if (strcmp(unp->un_name, dis_function_name(func)) == 0) {
236 resolved_name_t *resolved;
238 unp->un_mark = cb->cb_mark;
240 resolved = safe_malloc(sizeof (resolved_name_t));
242 resolved->rn_data = dis_function_copy(func);
243 resolved->rn_value = unp->un_value;
245 (void) uu_list_insert_before(cb->cb_resolved, NULL,
246 resolved);
250 uu_list_walk_end(walk);
254 * Take a list of unresolved names and create a resolved list of functions. We
255 * rely on walk_functions() to do the dirty work. After resolving the
256 * functions, * we check for any unmarked names and warn the user about missing
257 * functions.
259 dis_funclist_t *
260 dis_namelist_resolve_functions(dis_namelist_t *namelist, dis_tgt_t *tgt)
262 uu_list_t *listp;
263 uu_list_walk_t *walk;
264 unresolved_name_t *unp;
265 cb_data_t cb;
267 if ((listp = uu_list_create(resolved_pool, NULL, UU_DEFAULT)) == NULL)
268 die("out of memory");
270 cb.cb_mark = ++current_mark;
271 cb.cb_source = namelist;
272 cb.cb_resolved = listp;
274 dis_tgt_function_iter(tgt, walk_functions, &cb);
277 * Walk unresolved list and report any missing functions.
279 if ((walk = uu_list_walk_start(namelist, UU_DEFAULT)) == NULL)
280 die("out of memory");
282 while ((unp = uu_list_walk_next(walk)) != NULL) {
283 if (unp->un_mark != current_mark)
284 warn("failed to find function '%s' in '%s'",
285 unp->un_name, dis_tgt_name(tgt));
288 uu_list_walk_end(walk);
290 return (listp);
294 * Returns true if the given list is empty.
297 dis_namelist_empty(dis_namelist_t *list)
299 return (uu_list_numnodes(list) == 0);
302 static void
303 free_list(uu_list_t *list)
305 uu_list_walk_t *walk;
306 void *data;
308 if ((walk = uu_list_walk_start(list, UU_WALK_ROBUST)) == NULL)
309 die("out of memory");
311 while ((data = uu_list_walk_next(walk)) != NULL) {
312 uu_list_remove(list, data);
313 free(data);
316 uu_list_walk_end(walk);
318 uu_list_destroy(list);
322 * Destroy a list of sections. First, walk the list and free the associated
323 * section data. Pass the list onto to free_list() to clean up the rest of the
324 * list.
326 void
327 dis_scnlist_destroy(dis_scnlist_t *list)
329 uu_list_walk_t *walk;
330 resolved_name_t *data;
332 if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL)
333 die("out of memory");
335 while ((data = uu_list_walk_next(walk)) != NULL)
336 dis_section_free(data->rn_data);
338 uu_list_walk_end(walk);
340 free_list(list);
344 * Destroy a list of functions. First, walk the list and free the associated
345 * function data. Pass the list onto to free_list() to clean up the rest of the
346 * list.
348 void
349 dis_funclist_destroy(dis_funclist_t *list)
351 uu_list_walk_t *walk;
352 resolved_name_t *data;
354 if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL)
355 die("out of memory");
357 while ((data = uu_list_walk_next(walk)) != NULL)
358 dis_function_free(data->rn_data);
360 uu_list_walk_end(walk);
362 free_list(list);
366 * Destroy a lis tof unresolved names.
368 void
369 dis_namelist_destroy(dis_namelist_t *list)
371 free_list(list);
375 * Iterate over a resolved list of sections.
377 void
378 dis_scnlist_iter(uu_list_t *list, void (*func)(dis_scn_t *, int, void *),
379 void *arg)
381 uu_list_walk_t *walk;
382 resolved_name_t *data;
384 if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL)
385 die("out of memory");
387 while ((data = uu_list_walk_next(walk)) != NULL)
388 func(data->rn_data, data->rn_value, arg);
390 uu_list_walk_end(walk);
394 * Iterate over a resolved list of functions.
396 void
397 dis_funclist_iter(uu_list_t *list, void (*func)(dis_func_t *, int, void *),
398 void *arg)
400 uu_list_walk_t *walk;
401 resolved_name_t *data;
403 if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL)
404 die("out of memory");
406 while ((data = uu_list_walk_next(walk)) != NULL)
407 func(data->rn_data, data->rn_value, arg);
409 uu_list_walk_end(walk);