xref: /linux/scripts/gendwarfksyms/dwarf.c (revision 0c1c76274e88c420779c3aea077f9812bd16edaa)
1f2856884SSami Tolvanen // SPDX-License-Identifier: GPL-2.0
2f2856884SSami Tolvanen /*
3f2856884SSami Tolvanen  * Copyright (C) 2024 Google LLC
4f2856884SSami Tolvanen  */
5f2856884SSami Tolvanen 
65b7780e8SSami Tolvanen #include <inttypes.h>
75b7780e8SSami Tolvanen #include <stdarg.h>
8f2856884SSami Tolvanen #include "gendwarfksyms.h"
9f2856884SSami Tolvanen 
105b7780e8SSami Tolvanen #define DEFINE_GET_ATTR(attr, type)                                    \
115b7780e8SSami Tolvanen 	static bool get_##attr##_attr(Dwarf_Die *die, unsigned int id, \
125b7780e8SSami Tolvanen 				      type *value)                     \
135b7780e8SSami Tolvanen 	{                                                              \
145b7780e8SSami Tolvanen 		Dwarf_Attribute da;                                    \
155b7780e8SSami Tolvanen 		return dwarf_attr(die, id, &da) &&                     \
165b7780e8SSami Tolvanen 		       !dwarf_form##attr(&da, value);                  \
175b7780e8SSami Tolvanen 	}
185b7780e8SSami Tolvanen 
195b7780e8SSami Tolvanen DEFINE_GET_ATTR(udata, Dwarf_Word)
205b7780e8SSami Tolvanen 
21f2856884SSami Tolvanen static bool get_ref_die_attr(Dwarf_Die *die, unsigned int id, Dwarf_Die *value)
22f2856884SSami Tolvanen {
23f2856884SSami Tolvanen 	Dwarf_Attribute da;
24f2856884SSami Tolvanen 
25f2856884SSami Tolvanen 	/* dwarf_formref_die returns a pointer instead of an error value. */
26f2856884SSami Tolvanen 	return dwarf_attr(die, id, &da) && dwarf_formref_die(&da, value);
27f2856884SSami Tolvanen }
28f2856884SSami Tolvanen 
29f2856884SSami Tolvanen #define DEFINE_GET_STRING_ATTR(attr)                         \
30f2856884SSami Tolvanen 	static const char *get_##attr##_attr(Dwarf_Die *die) \
31f2856884SSami Tolvanen 	{                                                    \
32f2856884SSami Tolvanen 		Dwarf_Attribute da;                          \
33f2856884SSami Tolvanen 		if (dwarf_attr(die, DW_AT_##attr, &da))      \
34f2856884SSami Tolvanen 			return dwarf_formstring(&da);        \
35f2856884SSami Tolvanen 		return NULL;                                 \
36f2856884SSami Tolvanen 	}
37f2856884SSami Tolvanen 
38f2856884SSami Tolvanen DEFINE_GET_STRING_ATTR(name)
39f2856884SSami Tolvanen DEFINE_GET_STRING_ATTR(linkage_name)
40f2856884SSami Tolvanen 
41f2856884SSami Tolvanen static const char *get_symbol_name(Dwarf_Die *die)
42f2856884SSami Tolvanen {
43f2856884SSami Tolvanen 	const char *name;
44f2856884SSami Tolvanen 
45f2856884SSami Tolvanen 	/* rustc uses DW_AT_linkage_name for exported symbols */
46f2856884SSami Tolvanen 	name = get_linkage_name_attr(die);
47f2856884SSami Tolvanen 	if (!name)
48f2856884SSami Tolvanen 		name = get_name_attr(die);
49f2856884SSami Tolvanen 
50f2856884SSami Tolvanen 	return name;
51f2856884SSami Tolvanen }
52f2856884SSami Tolvanen 
53f2856884SSami Tolvanen static bool match_export_symbol(struct state *state, Dwarf_Die *die)
54f2856884SSami Tolvanen {
55f2856884SSami Tolvanen 	Dwarf_Die *source = die;
56f2856884SSami Tolvanen 	Dwarf_Die origin;
57f2856884SSami Tolvanen 
58f2856884SSami Tolvanen 	/* If the DIE has an abstract origin, use it for type information. */
59f2856884SSami Tolvanen 	if (get_ref_die_attr(die, DW_AT_abstract_origin, &origin))
60f2856884SSami Tolvanen 		source = &origin;
61f2856884SSami Tolvanen 
62f2856884SSami Tolvanen 	state->sym = symbol_get(get_symbol_name(die));
63f2856884SSami Tolvanen 
64f2856884SSami Tolvanen 	/* Look up using the origin name if there are no matches. */
65f2856884SSami Tolvanen 	if (!state->sym && source != die)
66f2856884SSami Tolvanen 		state->sym = symbol_get(get_symbol_name(source));
67f2856884SSami Tolvanen 
68f2856884SSami Tolvanen 	state->die = *source;
69f2856884SSami Tolvanen 	return !!state->sym;
70f2856884SSami Tolvanen }
71f2856884SSami Tolvanen 
72f2856884SSami Tolvanen /*
73f2856884SSami Tolvanen  * Type string processing
74f2856884SSami Tolvanen  */
75*0c1c7627SSami Tolvanen static void process(struct die *cache, const char *s)
76f2856884SSami Tolvanen {
77f2856884SSami Tolvanen 	s = s ?: "<null>";
78f2856884SSami Tolvanen 
79f2856884SSami Tolvanen 	if (dump_dies)
80f2856884SSami Tolvanen 		fputs(s, stderr);
81*0c1c7627SSami Tolvanen 
82*0c1c7627SSami Tolvanen 	die_map_add_string(cache, s);
83f2856884SSami Tolvanen }
84f2856884SSami Tolvanen 
855b7780e8SSami Tolvanen #define MAX_FMT_BUFFER_SIZE 128
865b7780e8SSami Tolvanen 
87*0c1c7627SSami Tolvanen static void process_fmt(struct die *cache, const char *fmt, ...)
885b7780e8SSami Tolvanen {
895b7780e8SSami Tolvanen 	char buf[MAX_FMT_BUFFER_SIZE];
905b7780e8SSami Tolvanen 	va_list args;
915b7780e8SSami Tolvanen 
925b7780e8SSami Tolvanen 	va_start(args, fmt);
935b7780e8SSami Tolvanen 
945b7780e8SSami Tolvanen 	if (checkp(vsnprintf(buf, sizeof(buf), fmt, args)) >= sizeof(buf))
955b7780e8SSami Tolvanen 		error("vsnprintf overflow: increase MAX_FMT_BUFFER_SIZE");
965b7780e8SSami Tolvanen 
97*0c1c7627SSami Tolvanen 	process(cache, buf);
985b7780e8SSami Tolvanen 	va_end(args);
995b7780e8SSami Tolvanen }
1005b7780e8SSami Tolvanen 
1015b7780e8SSami Tolvanen #define MAX_FQN_SIZE 64
1025b7780e8SSami Tolvanen 
1035b7780e8SSami Tolvanen /* Get a fully qualified name from DWARF scopes */
1045b7780e8SSami Tolvanen static char *get_fqn(Dwarf_Die *die)
1055b7780e8SSami Tolvanen {
1065b7780e8SSami Tolvanen 	const char *list[MAX_FQN_SIZE];
1075b7780e8SSami Tolvanen 	Dwarf_Die *scopes = NULL;
1085b7780e8SSami Tolvanen 	bool has_name = false;
1095b7780e8SSami Tolvanen 	char *fqn = NULL;
1105b7780e8SSami Tolvanen 	char *p;
1115b7780e8SSami Tolvanen 	int count = 0;
1125b7780e8SSami Tolvanen 	int len = 0;
1135b7780e8SSami Tolvanen 	int res;
1145b7780e8SSami Tolvanen 	int i;
1155b7780e8SSami Tolvanen 
1165b7780e8SSami Tolvanen 	res = checkp(dwarf_getscopes_die(die, &scopes));
1175b7780e8SSami Tolvanen 	if (!res) {
1185b7780e8SSami Tolvanen 		list[count] = get_name_attr(die);
1195b7780e8SSami Tolvanen 
1205b7780e8SSami Tolvanen 		if (!list[count])
1215b7780e8SSami Tolvanen 			return NULL;
1225b7780e8SSami Tolvanen 
1235b7780e8SSami Tolvanen 		len += strlen(list[count]);
1245b7780e8SSami Tolvanen 		count++;
1255b7780e8SSami Tolvanen 
1265b7780e8SSami Tolvanen 		goto done;
1275b7780e8SSami Tolvanen 	}
1285b7780e8SSami Tolvanen 
1295b7780e8SSami Tolvanen 	for (i = res - 1; i >= 0 && count < MAX_FQN_SIZE; i--) {
1305b7780e8SSami Tolvanen 		if (dwarf_tag(&scopes[i]) == DW_TAG_compile_unit)
1315b7780e8SSami Tolvanen 			continue;
1325b7780e8SSami Tolvanen 
1335b7780e8SSami Tolvanen 		list[count] = get_name_attr(&scopes[i]);
1345b7780e8SSami Tolvanen 
1355b7780e8SSami Tolvanen 		if (list[count]) {
1365b7780e8SSami Tolvanen 			has_name = true;
1375b7780e8SSami Tolvanen 		} else {
1385b7780e8SSami Tolvanen 			list[count] = "<anonymous>";
1395b7780e8SSami Tolvanen 			has_name = false;
1405b7780e8SSami Tolvanen 		}
1415b7780e8SSami Tolvanen 
1425b7780e8SSami Tolvanen 		len += strlen(list[count]);
1435b7780e8SSami Tolvanen 		count++;
1445b7780e8SSami Tolvanen 
1455b7780e8SSami Tolvanen 		if (i > 0) {
1465b7780e8SSami Tolvanen 			list[count++] = "::";
1475b7780e8SSami Tolvanen 			len += 2;
1485b7780e8SSami Tolvanen 		}
1495b7780e8SSami Tolvanen 	}
1505b7780e8SSami Tolvanen 
1515b7780e8SSami Tolvanen 	free(scopes);
1525b7780e8SSami Tolvanen 
1535b7780e8SSami Tolvanen 	if (count == MAX_FQN_SIZE)
1545b7780e8SSami Tolvanen 		warn("increase MAX_FQN_SIZE: reached the maximum");
1555b7780e8SSami Tolvanen 
1565b7780e8SSami Tolvanen 	/* Consider the DIE unnamed if the last scope doesn't have a name */
1575b7780e8SSami Tolvanen 	if (!has_name)
1585b7780e8SSami Tolvanen 		return NULL;
1595b7780e8SSami Tolvanen done:
1605b7780e8SSami Tolvanen 	fqn = xmalloc(len + 1);
1615b7780e8SSami Tolvanen 	*fqn = '\0';
1625b7780e8SSami Tolvanen 
1635b7780e8SSami Tolvanen 	p = fqn;
1645b7780e8SSami Tolvanen 	for (i = 0; i < count; i++)
1655b7780e8SSami Tolvanen 		p = stpcpy(p, list[i]);
1665b7780e8SSami Tolvanen 
1675b7780e8SSami Tolvanen 	return fqn;
1685b7780e8SSami Tolvanen }
1695b7780e8SSami Tolvanen 
170*0c1c7627SSami Tolvanen static void update_fqn(struct die *cache, Dwarf_Die *die)
1715b7780e8SSami Tolvanen {
172*0c1c7627SSami Tolvanen 	if (!cache->fqn)
173*0c1c7627SSami Tolvanen 		cache->fqn = get_fqn(die) ?: "";
174*0c1c7627SSami Tolvanen }
175*0c1c7627SSami Tolvanen 
176*0c1c7627SSami Tolvanen static void process_fqn(struct die *cache, Dwarf_Die *die)
177*0c1c7627SSami Tolvanen {
178*0c1c7627SSami Tolvanen 	update_fqn(cache, die);
179*0c1c7627SSami Tolvanen 	if (*cache->fqn)
180*0c1c7627SSami Tolvanen 		process(cache, " ");
181*0c1c7627SSami Tolvanen 	process(cache, cache->fqn);
1825b7780e8SSami Tolvanen }
1835b7780e8SSami Tolvanen 
1845b7780e8SSami Tolvanen #define DEFINE_PROCESS_UDATA_ATTRIBUTE(attribute)                          \
185*0c1c7627SSami Tolvanen 	static void process_##attribute##_attr(struct die *cache,          \
186*0c1c7627SSami Tolvanen 					       Dwarf_Die *die)             \
1875b7780e8SSami Tolvanen 	{                                                                  \
1885b7780e8SSami Tolvanen 		Dwarf_Word value;                                          \
1895b7780e8SSami Tolvanen 		if (get_udata_attr(die, DW_AT_##attribute, &value))        \
190*0c1c7627SSami Tolvanen 			process_fmt(cache, " " #attribute "(%" PRIu64 ")", \
191*0c1c7627SSami Tolvanen 				    value);                                \
1925b7780e8SSami Tolvanen 	}
1935b7780e8SSami Tolvanen 
1945b7780e8SSami Tolvanen DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment)
1955b7780e8SSami Tolvanen DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size)
1965b7780e8SSami Tolvanen DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding)
1975b7780e8SSami Tolvanen 
198f2856884SSami Tolvanen bool match_all(Dwarf_Die *die)
199f2856884SSami Tolvanen {
200f2856884SSami Tolvanen 	return true;
201f2856884SSami Tolvanen }
202f2856884SSami Tolvanen 
203*0c1c7627SSami Tolvanen int process_die_container(struct state *state, struct die *cache,
204*0c1c7627SSami Tolvanen 			  Dwarf_Die *die, die_callback_t func,
205*0c1c7627SSami Tolvanen 			  die_match_callback_t match)
206f2856884SSami Tolvanen {
207f2856884SSami Tolvanen 	Dwarf_Die current;
208f2856884SSami Tolvanen 	int res;
209f2856884SSami Tolvanen 
210f2856884SSami Tolvanen 	res = checkp(dwarf_child(die, &current));
211f2856884SSami Tolvanen 	while (!res) {
212f2856884SSami Tolvanen 		if (match(&current)) {
213f2856884SSami Tolvanen 			/* <0 = error, 0 = continue, >0 = stop */
214*0c1c7627SSami Tolvanen 			res = checkp(func(state, cache, &current));
215f2856884SSami Tolvanen 			if (res)
216f2856884SSami Tolvanen 				return res;
217f2856884SSami Tolvanen 		}
218f2856884SSami Tolvanen 
219f2856884SSami Tolvanen 		res = checkp(dwarf_siblingof(&current, &current));
220f2856884SSami Tolvanen 	}
221f2856884SSami Tolvanen 
222f2856884SSami Tolvanen 	return 0;
223f2856884SSami Tolvanen }
224f2856884SSami Tolvanen 
225*0c1c7627SSami Tolvanen static int process_type(struct state *state, struct die *parent,
226*0c1c7627SSami Tolvanen 			Dwarf_Die *die);
2275b7780e8SSami Tolvanen 
228*0c1c7627SSami Tolvanen static void process_type_attr(struct state *state, struct die *cache,
229*0c1c7627SSami Tolvanen 			      Dwarf_Die *die)
2305b7780e8SSami Tolvanen {
2315b7780e8SSami Tolvanen 	Dwarf_Die type;
2325b7780e8SSami Tolvanen 
2335b7780e8SSami Tolvanen 	if (get_ref_die_attr(die, DW_AT_type, &type)) {
234*0c1c7627SSami Tolvanen 		check(process_type(state, cache, &type));
2355b7780e8SSami Tolvanen 		return;
2365b7780e8SSami Tolvanen 	}
2375b7780e8SSami Tolvanen 
2385b7780e8SSami Tolvanen 	/* Compilers can omit DW_AT_type -- print out 'void' to clarify */
239*0c1c7627SSami Tolvanen 	process(cache, "base_type void");
2405b7780e8SSami Tolvanen }
2415b7780e8SSami Tolvanen 
242*0c1c7627SSami Tolvanen static void process_base_type(struct state *state, struct die *cache,
243*0c1c7627SSami Tolvanen 			      Dwarf_Die *die)
2445b7780e8SSami Tolvanen {
245*0c1c7627SSami Tolvanen 	process(cache, "base_type");
246*0c1c7627SSami Tolvanen 	process_fqn(cache, die);
247*0c1c7627SSami Tolvanen 	process_byte_size_attr(cache, die);
248*0c1c7627SSami Tolvanen 	process_encoding_attr(cache, die);
249*0c1c7627SSami Tolvanen 	process_alignment_attr(cache, die);
250*0c1c7627SSami Tolvanen }
251*0c1c7627SSami Tolvanen 
252*0c1c7627SSami Tolvanen static void process_cached(struct state *state, struct die *cache,
253*0c1c7627SSami Tolvanen 			   Dwarf_Die *die)
254*0c1c7627SSami Tolvanen {
255*0c1c7627SSami Tolvanen 	struct die_fragment *df;
256*0c1c7627SSami Tolvanen 	Dwarf_Die child;
257*0c1c7627SSami Tolvanen 
258*0c1c7627SSami Tolvanen 	list_for_each_entry(df, &cache->fragments, list) {
259*0c1c7627SSami Tolvanen 		switch (df->type) {
260*0c1c7627SSami Tolvanen 		case FRAGMENT_STRING:
261*0c1c7627SSami Tolvanen 			process(NULL, df->data.str);
262*0c1c7627SSami Tolvanen 			break;
263*0c1c7627SSami Tolvanen 		case FRAGMENT_DIE:
264*0c1c7627SSami Tolvanen 			if (!dwarf_die_addr_die(dwarf_cu_getdwarf(die->cu),
265*0c1c7627SSami Tolvanen 						(void *)df->data.addr, &child))
266*0c1c7627SSami Tolvanen 				error("dwarf_die_addr_die failed");
267*0c1c7627SSami Tolvanen 			check(process_type(state, NULL, &child));
268*0c1c7627SSami Tolvanen 			break;
269*0c1c7627SSami Tolvanen 		default:
270*0c1c7627SSami Tolvanen 			error("empty die_fragment");
271*0c1c7627SSami Tolvanen 		}
272*0c1c7627SSami Tolvanen 	}
2735b7780e8SSami Tolvanen }
2745b7780e8SSami Tolvanen 
2755b7780e8SSami Tolvanen #define PROCESS_TYPE(type)                                \
2765b7780e8SSami Tolvanen 	case DW_TAG_##type##_type:                        \
277*0c1c7627SSami Tolvanen 		process_##type##_type(state, cache, die); \
2785b7780e8SSami Tolvanen 		break;
2795b7780e8SSami Tolvanen 
280*0c1c7627SSami Tolvanen static int process_type(struct state *state, struct die *parent, Dwarf_Die *die)
2815b7780e8SSami Tolvanen {
282*0c1c7627SSami Tolvanen 	struct die *cache;
2835b7780e8SSami Tolvanen 	int tag = dwarf_tag(die);
2845b7780e8SSami Tolvanen 
285*0c1c7627SSami Tolvanen 	/*
286*0c1c7627SSami Tolvanen 	 * If we have the DIE already cached, use it instead of walking
287*0c1c7627SSami Tolvanen 	 * through DWARF.
288*0c1c7627SSami Tolvanen 	 */
289*0c1c7627SSami Tolvanen 	cache = die_map_get(die, DIE_COMPLETE);
290*0c1c7627SSami Tolvanen 
291*0c1c7627SSami Tolvanen 	if (cache->state == DIE_COMPLETE) {
292*0c1c7627SSami Tolvanen 		process_cached(state, cache, die);
293*0c1c7627SSami Tolvanen 		die_map_add_die(parent, cache);
294*0c1c7627SSami Tolvanen 		return 0;
295*0c1c7627SSami Tolvanen 	}
296*0c1c7627SSami Tolvanen 
2975b7780e8SSami Tolvanen 	switch (tag) {
2985b7780e8SSami Tolvanen 	PROCESS_TYPE(base)
2995b7780e8SSami Tolvanen 	default:
3005b7780e8SSami Tolvanen 		debug("unimplemented type: %x", tag);
3015b7780e8SSami Tolvanen 		break;
3025b7780e8SSami Tolvanen 	}
3035b7780e8SSami Tolvanen 
304*0c1c7627SSami Tolvanen 	/* Update cache state and append to the parent (if any) */
305*0c1c7627SSami Tolvanen 	cache->tag = tag;
306*0c1c7627SSami Tolvanen 	cache->state = DIE_COMPLETE;
307*0c1c7627SSami Tolvanen 	die_map_add_die(parent, cache);
308*0c1c7627SSami Tolvanen 
3095b7780e8SSami Tolvanen 	return 0;
3105b7780e8SSami Tolvanen }
3115b7780e8SSami Tolvanen 
312f2856884SSami Tolvanen /*
313f2856884SSami Tolvanen  * Exported symbol processing
314f2856884SSami Tolvanen  */
315f2856884SSami Tolvanen static void process_symbol(struct state *state, Dwarf_Die *die,
316f2856884SSami Tolvanen 			   die_callback_t process_func)
317f2856884SSami Tolvanen {
318f2856884SSami Tolvanen 	debug("%s", state->sym->name);
319*0c1c7627SSami Tolvanen 	check(process_func(state, NULL, die));
320f2856884SSami Tolvanen 	if (dump_dies)
321f2856884SSami Tolvanen 		fputs("\n", stderr);
322f2856884SSami Tolvanen }
323f2856884SSami Tolvanen 
324*0c1c7627SSami Tolvanen static int __process_subprogram(struct state *state, struct die *cache,
325*0c1c7627SSami Tolvanen 				Dwarf_Die *die)
326f2856884SSami Tolvanen {
327*0c1c7627SSami Tolvanen 	process(cache, "subprogram");
328f2856884SSami Tolvanen 	return 0;
329f2856884SSami Tolvanen }
330f2856884SSami Tolvanen 
331f2856884SSami Tolvanen static void process_subprogram(struct state *state, Dwarf_Die *die)
332f2856884SSami Tolvanen {
333f2856884SSami Tolvanen 	process_symbol(state, die, __process_subprogram);
334f2856884SSami Tolvanen }
335f2856884SSami Tolvanen 
336*0c1c7627SSami Tolvanen static int __process_variable(struct state *state, struct die *cache,
337*0c1c7627SSami Tolvanen 			      Dwarf_Die *die)
338f2856884SSami Tolvanen {
339*0c1c7627SSami Tolvanen 	process(cache, "variable ");
340*0c1c7627SSami Tolvanen 	process_type_attr(state, cache, die);
341f2856884SSami Tolvanen 	return 0;
342f2856884SSami Tolvanen }
343f2856884SSami Tolvanen 
344f2856884SSami Tolvanen static void process_variable(struct state *state, Dwarf_Die *die)
345f2856884SSami Tolvanen {
346f2856884SSami Tolvanen 	process_symbol(state, die, __process_variable);
347f2856884SSami Tolvanen }
348f2856884SSami Tolvanen 
349*0c1c7627SSami Tolvanen static int process_exported_symbols(struct state *unused, struct die *cache,
350*0c1c7627SSami Tolvanen 				    Dwarf_Die *die)
351f2856884SSami Tolvanen {
352f2856884SSami Tolvanen 	int tag = dwarf_tag(die);
353f2856884SSami Tolvanen 
354f2856884SSami Tolvanen 	switch (tag) {
355f2856884SSami Tolvanen 	/* Possible containers of exported symbols */
356f2856884SSami Tolvanen 	case DW_TAG_namespace:
357f2856884SSami Tolvanen 	case DW_TAG_class_type:
358f2856884SSami Tolvanen 	case DW_TAG_structure_type:
359f2856884SSami Tolvanen 		return check(process_die_container(
360*0c1c7627SSami Tolvanen 			NULL, cache, die, process_exported_symbols, match_all));
361f2856884SSami Tolvanen 
362f2856884SSami Tolvanen 	/* Possible exported symbols */
363f2856884SSami Tolvanen 	case DW_TAG_subprogram:
364f2856884SSami Tolvanen 	case DW_TAG_variable: {
365f2856884SSami Tolvanen 		struct state state;
366f2856884SSami Tolvanen 
367f2856884SSami Tolvanen 		if (!match_export_symbol(&state, die))
368f2856884SSami Tolvanen 			return 0;
369f2856884SSami Tolvanen 
370f2856884SSami Tolvanen 		if (tag == DW_TAG_subprogram)
371f2856884SSami Tolvanen 			process_subprogram(&state, &state.die);
372f2856884SSami Tolvanen 		else
373f2856884SSami Tolvanen 			process_variable(&state, &state.die);
374f2856884SSami Tolvanen 
375f2856884SSami Tolvanen 		return 0;
376f2856884SSami Tolvanen 	}
377f2856884SSami Tolvanen 	default:
378f2856884SSami Tolvanen 		return 0;
379f2856884SSami Tolvanen 	}
380f2856884SSami Tolvanen }
381f2856884SSami Tolvanen 
382f2856884SSami Tolvanen void process_cu(Dwarf_Die *cudie)
383f2856884SSami Tolvanen {
384*0c1c7627SSami Tolvanen 	check(process_die_container(NULL, NULL, cudie, process_exported_symbols,
385f2856884SSami Tolvanen 				    match_all));
386f2856884SSami Tolvanen }
387