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]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
33 #include "dis_target.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 */
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 */
63 static uu_list_pool_t
*unresolved_pool
;
64 static uu_list_pool_t
*resolved_pool
;
65 static int current_mark
= 0;
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
)
83 * Returns an empty list of unresolved names.
86 dis_namelist_create(void)
91 * If this is the first request to create a list, initialize the list
94 if (unresolved_pool
== NULL
)
97 if ((listp
= uu_list_create(unresolved_pool
, NULL
, 0)) == NULL
)
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.
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
;
120 (void) uu_list_insert_before(list
, NULL
, node
);
124 * Internal callback structure used
126 typedef struct cb_data
{
128 uu_list_t
*cb_source
;
129 uu_list_t
*cb_resolved
;
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
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
,
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.
182 dis_namelist_resolve_sections(dis_namelist_t
*namelist
, dis_tgt_t
*tgt
)
186 unresolved_name_t
*unp
;
187 uu_list_walk_t
*walk
;
190 * Walk all sections in the target, calling walk_sections() for each
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
);
221 * Similar to walk_sections(), but for functions.
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
,
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
260 dis_namelist_resolve_functions(dis_namelist_t
*namelist
, dis_tgt_t
*tgt
)
263 uu_list_walk_t
*walk
;
264 unresolved_name_t
*unp
;
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
);
294 * Returns true if the given list is empty.
297 dis_namelist_empty(dis_namelist_t
*list
)
299 return (uu_list_numnodes(list
) == 0);
303 free_list(uu_list_t
*list
)
305 uu_list_walk_t
*walk
;
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
);
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
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
);
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
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
);
366 * Destroy a lis tof unresolved names.
369 dis_namelist_destroy(dis_namelist_t
*list
)
375 * Iterate over a resolved list of sections.
378 dis_scnlist_iter(uu_list_t
*list
, void (*func
)(dis_scn_t
*, int, void *),
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.
397 dis_funclist_iter(uu_list_t
*list
, void (*func
)(dis_func_t
*, int, void *),
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
);