pahole: Describe expected use of 'default' in the man page
[dwarves.git] / pglobal.c
blob9341244efb3124706ccbe5910901728820dfe9e7
1 /*
2 * SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (C) 2007 Davi E. M. Arnaut <davi@haxent.com.br>
5 */
7 #include <argp.h>
8 #include <malloc.h>
9 #include <search.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
15 #include "dwarves.h"
16 #include "dutil.h"
18 static int verbose;
20 static struct conf_fprintf conf = {
21 .emit_stats = 1,
24 static struct conf_load conf_load = {
25 .conf_fprintf = &conf,
28 struct extvar {
29 struct extvar *next;
30 const char *name;
31 const struct variable *var;
32 const struct cu *cu;
35 struct extfun {
36 struct extfun *next;
37 const char *name;
38 const struct function *fun;
39 const struct cu *cu;
42 static void *tree;
44 static void oom(const char *msg)
46 fprintf(stderr, "pglobal: out of memory (%s)\n", msg);
47 exit(EXIT_FAILURE);
50 static struct extvar *extvar__new(const struct variable *var,
51 const struct cu *cu)
53 struct extvar *gvar = malloc(sizeof(*gvar));
55 if (gvar != NULL) {
56 gvar->next = NULL;
57 gvar->var = var;
58 gvar->cu = cu;
59 gvar->name = variable__name(var);
62 return gvar;
65 static struct extfun *extfun__new(struct function *fun,
66 const struct cu *cu)
68 struct extfun *gfun = malloc(sizeof(*gfun));
70 if (gfun != NULL) {
71 gfun->next = NULL;
72 gfun->fun = fun;
73 gfun->cu = cu;
74 gfun->name = function__name(fun);
77 return gfun;
80 static int extvar__compare(const void *a, const void *b)
82 const struct extvar *ga = a, *gb = b;
83 return strcmp(ga->name, gb->name);
86 static int extfun__compare(const void *a, const void *b)
88 const struct extfun *ga = a, *gb = b;
89 return strcmp(ga->name, gb->name);
92 static void extvar__add(const struct variable *var, const struct cu *cu)
94 struct extvar **nodep, *gvar = extvar__new(var, cu);
96 if (gvar != NULL) {
97 nodep = tsearch(gvar, &tree, extvar__compare);
98 if (nodep == NULL)
99 oom("tsearch");
100 else if (*nodep != gvar) {
101 if (gvar->var->declaration) {
102 gvar->next = (*nodep)->next;
103 (*nodep)->next = gvar;
104 } else {
105 gvar->next = *nodep;
106 *nodep = gvar;
112 static void extfun__add(struct function *fun, const struct cu *cu)
114 struct extfun **nodep, *gfun = extfun__new(fun, cu);
116 if (gfun != NULL) {
117 nodep = tsearch(gfun, &tree, extfun__compare);
118 if (nodep == NULL)
119 oom("tsearch");
120 else if (*nodep != gfun) {
121 gfun->next = (*nodep)->next;
122 (*nodep)->next = gfun;
127 static int cu_extvar_iterator(struct cu *cu, void *cookie __maybe_unused)
129 struct tag *pos;
130 uint32_t id;
132 cu__for_each_variable(cu, id, pos) {
133 struct variable *var = tag__variable(pos);
134 if (var->external)
135 extvar__add(var, cu);
137 return 0;
140 static int cu_extfun_iterator(struct cu *cu, void *cookie __maybe_unused)
142 struct function *pos;
143 uint32_t id;
145 cu__for_each_function(cu, id, pos)
146 if (pos->external)
147 extfun__add(pos, cu);
148 return 0;
151 static inline const struct extvar *node__variable(const void *nodep)
153 return *((const struct extvar **)nodep);
156 static inline const struct extfun *node__function(const void *nodep)
158 return *((const struct extfun **)nodep);
161 static inline struct tag *extvar__tag(const struct extvar *gvar)
163 return (struct tag *)gvar->var;
166 static inline struct tag *extfun__tag(const struct extfun *gfun)
168 return (struct tag *)gfun->fun;
171 static void declaration_action__walk(const void *nodep, const VISIT which,
172 const int depth __maybe_unused)
174 uint32_t count = 0;
175 struct tag *tag;
176 const struct extvar *pos, *gvar = NULL;
178 switch(which) {
179 case preorder:
180 break;
181 case postorder:
182 gvar = node__variable(nodep);
183 break;
184 case endorder:
185 break;
186 case leaf:
187 gvar = node__variable(nodep);
188 break;
191 if (gvar == NULL)
192 return;
194 tag = extvar__tag(gvar);
196 tag__fprintf(tag, gvar->cu, NULL, stdout);
198 for (pos = gvar->next; pos; pos = pos->next)
199 count++;
201 printf("; /* %u */\n\n", count);
204 static void function_action__walk(const void *nodep, const VISIT which,
205 const int depth __maybe_unused)
207 struct tag *tag;
208 const struct extfun *gfun = NULL;
210 switch(which) {
211 case preorder:
212 break;
213 case postorder:
214 gfun = node__function(nodep);
215 break;
216 case endorder:
217 break;
218 case leaf:
219 gfun = node__function(nodep);
220 break;
223 if (gfun == NULL)
224 return;
226 tag = extfun__tag(gfun);
228 tag__fprintf(tag, gfun->cu, NULL, stdout);
230 fputs("\n\n", stdout);
233 static void free_node(void *nodep)
235 void **node = nodep;
236 free(*node);
239 /* Name and version of program. */
240 ARGP_PROGRAM_VERSION_HOOK_DEF = dwarves_print_version;
242 static const struct argp_option pglobal__options[] = {
244 .key = 'v',
245 .name = "variables",
246 .doc = "show global variables",
249 .key = 'f',
250 .name = "functions",
251 .doc = "show global functions",
254 .name = "format_path",
255 .key = 'F',
256 .arg = "FORMAT_LIST",
257 .doc = "List of debugging formats to try"
260 .key = 'V',
261 .name = "verbose",
262 .doc = "be verbose",
265 .name = NULL,
269 static int walk_var, walk_fun;
271 static error_t pglobal__options_parser(int key, char *arg __maybe_unused,
272 struct argp_state *state)
274 switch (key) {
275 case ARGP_KEY_INIT:
276 if (state->child_inputs != NULL)
277 state->child_inputs[0] = state->input;
278 break;
279 case 'v': walk_var = 1; break;
280 case 'f': walk_fun = 1; break;
281 case 'V': verbose = 1; break;
282 case 'F': conf_load.format_path = arg; break;
283 default: return ARGP_ERR_UNKNOWN;
285 return 0;
288 static const char pglobal__args_doc[] = "FILE";
290 static struct argp pglobal__argp = {
291 .options = pglobal__options,
292 .parser = pglobal__options_parser,
293 .args_doc = pglobal__args_doc,
296 int main(int argc, char *argv[])
298 int err, remaining, rc = EXIT_FAILURE;
300 if (argp_parse(&pglobal__argp, argc, argv, 0, &remaining, NULL) ||
301 remaining == argc) {
302 argp_help(&pglobal__argp, stderr, ARGP_HELP_SEE, argv[0]);
303 goto out;
306 if (dwarves__init()) {
307 fputs("pglobal: insufficient memory\n", stderr);
308 goto out;
311 dwarves__resolve_cacheline_size(&conf_load, 0);
313 struct cus *cus = cus__new();
314 if (cus == NULL) {
315 fputs("pglobal: insufficient memory\n", stderr);
316 goto out_dwarves_exit;
319 err = cus__load_files(cus, &conf_load, argv + remaining);
320 if (err != 0) {
321 cus__fprintf_load_files_err(cus, "pglobal", argv + remaining, err, stderr);
322 goto out_cus_delete;
325 if (walk_var) {
326 cus__for_each_cu(cus, cu_extvar_iterator, NULL, NULL);
327 twalk(tree, declaration_action__walk);
328 } else if (walk_fun) {
329 cus__for_each_cu(cus, cu_extfun_iterator, NULL, NULL);
330 twalk(tree, function_action__walk);
333 tdestroy(tree, free_node);
334 rc = EXIT_SUCCESS;
335 out_cus_delete:
336 cus__delete(cus);
337 out_dwarves_exit:
338 dwarves__exit();
339 out:
340 return rc;