]> sourceware.org Git - systemtap.git/blob - loc2c-test.c
Define __NR_epoll_wait if not defined (PR17462)
[systemtap.git] / loc2c-test.c
1 /* Simple test program for loc2c code.
2
3 This takes the standard libdwfl switches to select what address space
4 you are talking about, same as for e.g. eu-addr2line (see --help). */
5
6 #include <config.h>
7 #include <assert.h>
8 #include <inttypes.h>
9 #include <sys/types.h>
10 #include <stdio.h>
11 #include <stdio_ext.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <error.h>
15 #if ENABLE_NLS
16 #include <locale.h>
17 #endif
18 #include <argp.h>
19 #include <elfutils/libdwfl.h>
20 #include <elfutils/version.h>
21 #include <dwarf.h>
22 #include <obstack.h>
23 #include <unistd.h>
24 #include <stdarg.h>
25 #include "loc2c.h"
26
27 #define _(msg) msg
28
29 /* Using this structure in the callback (to handle_function) allows us
30 to print out the function's address */
31 struct dwfunc
32 {
33 Dwfl *dwfl;
34 Dwarf_Die *cu;
35 Dwarf_Addr dwbias;
36 char * funcname;
37 uintmax_t pc;
38 bool matchdebug;
39 };
40
41 static void __attribute__ ((noreturn, format (printf, 2, 3)))
42 fail (void *arg __attribute__ ((unused)), const char *fmt, ...)
43 {
44 va_list ap;
45
46 fprintf (stderr, "%s: ", program_invocation_short_name);
47
48 va_start (ap, fmt);
49 vfprintf (stderr, _(fmt), ap);
50 va_end (ap);
51
52 fprintf (stderr, "\n");
53
54 exit (2);
55 }
56
57 static const Dwarf_Op *
58 get_location (Dwarf_Addr dwbias, Dwarf_Addr pc, Dwarf_Attribute *loc_attr,
59 size_t *len)
60 {
61 Dwarf_Op *expr;
62
63 switch (dwarf_getlocation_addr (loc_attr, pc - dwbias, &expr, len, 1))
64 {
65 case 1: /* Should always happen. */
66 if (*len == 0)
67 goto inaccessible;
68 break;
69
70 default: /* Shouldn't happen. */
71 case -1:
72 fail (NULL, _("dwarf_getlocation_addr (form %#x): %s"),
73 dwarf_whatform (loc_attr), dwarf_errmsg (-1));
74 return NULL;
75
76 case 0: /* Shouldn't happen. */
77 inaccessible:
78 fail (NULL, _("not accessible at this address"));
79 return NULL;
80 }
81
82 return expr;
83 }
84
85 #define obstack_chunk_alloc malloc
86 #define obstack_chunk_free free
87
88 static void
89 handle_fields (struct obstack *pool,
90 struct location *head, struct location *tail,
91 Dwarf_Addr cubias, Dwarf_Die *vardie, Dwarf_Addr pc,
92 char **fields)
93 {
94 Dwarf_Attribute attr_mem;
95
96 if (dwarf_attr_integrate (vardie, DW_AT_type, &attr_mem) == NULL)
97 error (2, 0, _("cannot get type of variable: %s"),
98 dwarf_errmsg (-1));
99
100 bool store = false;
101 Dwarf_Die die_mem, *die = vardie;
102 while (*fields != NULL)
103 {
104 if (!strcmp (*fields, "="))
105 {
106 store = true;
107 if (fields[1] != NULL)
108 error (2, 0, _("extra fields after ="));
109 break;
110 }
111
112 die = dwarf_formref_die (&attr_mem, &die_mem);
113
114 const int typetag = dwarf_tag (die);
115 switch (typetag)
116 {
117 case DW_TAG_typedef:
118 case DW_TAG_const_type:
119 case DW_TAG_volatile_type:
120 case DW_TAG_restrict_type:
121 /* Just iterate on the referent type. */
122 break;
123
124 case DW_TAG_pointer_type:
125 if (**fields == '+')
126 goto subscript;
127 /* A "" field means explicit pointer dereference and we consume it.
128 Otherwise the next field implicitly gets the dereference. */
129 if (**fields == '\0')
130 ++fields;
131 c_translate_pointer (pool, 1, cubias, die, &tail);
132 break;
133
134 case DW_TAG_array_type:
135 if (**fields == '+')
136 {
137 subscript:;
138 char *endp = *fields + 1;
139 uintmax_t idx = strtoumax (*fields + 1, &endp, 0);
140 if (endp == NULL || endp == *fields || *endp != '\0')
141 c_translate_array (pool, 1, cubias, die, &tail,
142 *fields + 1, 0);
143 else
144 c_translate_array (pool, 1, cubias, die, &tail,
145 NULL, idx);
146 ++fields;
147 }
148 else
149 error (2, 0, _("bad field for array type: %s"), *fields);
150 break;
151
152 case DW_TAG_structure_type:
153 case DW_TAG_union_type:
154 switch (dwarf_child (die, &die_mem))
155 {
156 case 1: /* No children. */
157 error (2, 0, _("empty struct %s"),
158 dwarf_diename (die) ?: "<anonymous>");
159 break;
160 case -1: /* Error. */
161 default: /* Shouldn't happen */
162 error (2, 0, _("%s %s: %s"),
163 typetag == DW_TAG_union_type ? "union" : "struct",
164 dwarf_diename (die) ?: "<anonymous>",
165 dwarf_errmsg (-1));
166 break;
167
168 case 0:
169 break;
170 }
171 while (dwarf_tag (die) != DW_TAG_member
172 || ({ const char *member = dwarf_diename (die);
173 member == NULL || strcmp (member, *fields); }))
174 if (dwarf_siblingof (die, &die_mem) != 0)
175 error (2, 0, _("field name %s not found"), *fields);
176
177 if (dwarf_attr_integrate (die, DW_AT_data_member_location,
178 &attr_mem) == NULL)
179 {
180 /* Union members don't usually have a location,
181 but just use the containing union's location. */
182 if (typetag != DW_TAG_union_type)
183 error (2, 0, _("no location for field %s: %s"),
184 *fields, dwarf_errmsg (-1));
185 }
186 else
187 {
188 /* We expect a block or a constant. */
189 size_t locexpr_len = 0;
190 const Dwarf_Op *locexpr;
191 locexpr = get_location (cubias, pc, &attr_mem, &locexpr_len);
192 c_translate_location (pool, NULL, NULL, NULL,
193 1, cubias, pc, &attr_mem,
194 locexpr, locexpr_len,
195 &tail, NULL, NULL);
196 }
197 ++fields;
198 break;
199
200 case DW_TAG_base_type:
201 error (2, 0, _("field %s vs base type %s"),
202 *fields, dwarf_diename (die) ?: "<anonymous type>");
203 break;
204
205 case -1:
206 error (2, 0, _("cannot find type: %s"), dwarf_errmsg (-1));
207 break;
208
209 default:
210 error (2, 0, _("%s: unexpected type tag %#x"),
211 dwarf_diename (die) ?: "<anonymous type>",
212 dwarf_tag (die));
213 break;
214 }
215
216 /* Now iterate on the type in DIE's attribute. */
217 if (dwarf_attr_integrate (die, DW_AT_type, &attr_mem) == NULL)
218 error (2, 0, _("cannot get type of field: %s"), dwarf_errmsg (-1));
219 }
220
221 /* Fetch the type DIE corresponding to the final location to be accessed.
222 It must be a base type or a typedef for one. */
223
224 Dwarf_Die typedie_mem;
225 Dwarf_Die *typedie;
226 int typetag;
227 while (1)
228 {
229 typedie = dwarf_formref_die (&attr_mem, &typedie_mem);
230 if (typedie == NULL)
231 error (2, 0, _("cannot get type of field: %s"), dwarf_errmsg (-1));
232 typetag = dwarf_tag (typedie);
233 if (typetag != DW_TAG_typedef &&
234 typetag != DW_TAG_const_type &&
235 typetag != DW_TAG_volatile_type &&
236 typetag != DW_TAG_restrict_type)
237 break;
238 if (dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem) == NULL)
239 error (2, 0, _("cannot get type of field: %s"), dwarf_errmsg (-1));
240 }
241
242 switch (typetag)
243 {
244 case DW_TAG_base_type:
245 if (store)
246 c_translate_store (pool, 1, cubias, die, typedie, &tail, "value");
247 else
248 c_translate_fetch (pool, 1, cubias, die, typedie, &tail, "value");
249 break;
250
251 case DW_TAG_pointer_type:
252 case DW_TAG_reference_type:
253 if (store)
254 error (2, 0, _("store not supported for pointer type"));
255 c_translate_pointer (pool, 1, cubias, typedie, &tail);
256 c_translate_addressof (pool, 1, cubias, die, typedie, &tail, "value");
257 break;
258
259 default:
260 if (store)
261 error (2, 0, _("store supported only for base type"));
262 else
263 error (2, 0, _("fetch supported only for base type or pointer"));
264 break;
265 }
266
267 printf ("#define PROBEADDR %#" PRIx64 "ULL\n", pc);
268
269 puts (store
270 ? "static void set_value(struct pt_regs *regs, intptr_t value)\n{"
271 : "static void print_value(struct pt_regs *regs)\n"
272 "{\n"
273 " intptr_t value;");
274
275 unsigned int stack_depth;
276 bool deref = c_emit_location (stdout, head, 1, &stack_depth);
277
278 obstack_free (pool, NULL);
279
280 printf (" /* max expression stack depth %u */\n", stack_depth);
281
282 puts (store ? " return;" :
283 " printk (\" ---> %ld\\n\", (unsigned long) value);\n"
284 " return;");
285
286 if (deref)
287 puts ("\n"
288 " deref_fault:\n"
289 " printk (\" => BAD ACCESS\\n\");");
290
291 puts ("}");
292 }
293
294 static void
295 handle_variable (Dwarf_Die *lscopes, int lnscopes, int out,
296 Dwarf_Addr cubias, Dwarf_Die *vardie, Dwarf_Addr pc,
297 Dwarf_Op *cfa_ops, char **fields)
298 {
299 struct obstack pool;
300 obstack_init (&pool);
301
302 /* Figure out the appropriate frame base for accessing this variable.
303 * XXX not handling nested functions
304 */
305 Dwarf_Attribute fb_attr_mem, *fb_attr = NULL;
306 int inner;
307 /* We start out walking the "lexical scopes" as returned by
308 * as returned by dwarf_getscopes for the address, starting with the
309 * 'out' scope that the variable was found in.
310 */
311 Dwarf_Die *scopes = lscopes;
312 int nscopes = lnscopes;
313 for (inner = out; inner < nscopes && fb_attr == NULL; ++inner)
314 {
315 switch (dwarf_tag (&scopes[inner]))
316 {
317 default:
318 continue;
319 case DW_TAG_subprogram:
320 case DW_TAG_entry_point:
321 fb_attr = dwarf_attr_integrate (&scopes[inner],
322 DW_AT_frame_base,
323 &fb_attr_mem);
324 break;
325 case DW_TAG_inlined_subroutine:
326 /* Unless we already are going through the "pyshical die tree",
327 * we now need to start walking the die tree where this
328 * subroutine is inlined to find the appropriate frame base. */
329 if (out != -1)
330 {
331 nscopes = dwarf_getscopes_die (&scopes[inner], &scopes);
332 if (nscopes == -1)
333 error (2, 0, _("cannot get die scopes inlined_subroutine: %s"),
334 dwarf_errmsg (-1));
335 inner = 0; // zero is current scope, for look will increase.
336 out = -1;
337 }
338 break;
339 }
340 }
341
342 struct location *head, *tail = NULL;
343
344 Dwarf_Attribute attr_mem;
345 if (dwarf_attr_integrate (vardie, DW_AT_const_value, &attr_mem) != NULL)
346 /* There is no location expression, but a constant value instead. */
347 head = tail = c_translate_constant (&pool, &fail, NULL, NULL,
348 1, cubias, &attr_mem);
349 else
350 {
351 if (dwarf_attr_integrate (vardie, DW_AT_location, &attr_mem) == NULL)
352 error (2, 0, _("cannot get location of variable: %s"),
353 dwarf_errmsg (-1));
354
355 size_t locexpr_len = 0;
356 const Dwarf_Op *locexpr = get_location (cubias, pc,
357 &attr_mem, &locexpr_len);
358
359 head = c_translate_location (&pool, &fail, NULL, NULL,
360 1, cubias, pc, &attr_mem,
361 locexpr, locexpr_len,
362 &tail, fb_attr, cfa_ops);
363 }
364
365 handle_fields (&pool, head, tail, cubias, vardie, pc, fields);
366 }
367
368 static void
369 paddr (const char *prefix, Dwarf_Addr addr, Dwfl_Line *line)
370 {
371 const char *src;
372 int lineno, linecol;
373 if (line != NULL
374 && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
375 NULL, NULL)) != NULL)
376 {
377 if (linecol != 0)
378 printf ("%s%#" PRIx64 " (%s:%d:%d)",
379 prefix, addr, src, lineno, linecol);
380 else
381 printf ("%s%#" PRIx64 " (%s:%d)",
382 prefix, addr, src, lineno);
383 }
384 else
385 printf ("%s%#" PRIx64, prefix, addr);
386 }
387
388 static void
389 print_type (Dwarf_Die *typedie, char space)
390 {
391 if (typedie == NULL)
392 printf ("%c<no type>", space);
393 else
394 {
395 const char *name = dwarf_diename (typedie);
396 if (name != NULL)
397 printf ("%c%s", space, name);
398 else
399 {
400 Dwarf_Attribute attr_mem;
401 Dwarf_Die die_mem;
402 Dwarf_Die *die = dwarf_formref_die
403 (dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem), &die_mem);
404 int tag = dwarf_tag (typedie);
405 switch (tag)
406 {
407 case DW_TAG_pointer_type:
408 print_type (die, space);
409 putchar ('*');
410 break;
411 case DW_TAG_array_type:
412 print_type (die, space);
413 printf ("[]");
414 break;
415 case DW_TAG_const_type:
416 print_type (die, space);
417 printf (" const");
418 break;
419 case DW_TAG_volatile_type:
420 print_type (die, space);
421 printf (" volatile");
422 break;
423 case DW_TAG_restrict_type:
424 print_type (die, space);
425 printf (" restrict");
426 break;
427 default:
428 printf ("%c<unknown %#x>", space, tag);
429 break;
430 }
431 }
432 }
433 }
434
435 static void
436 print_vars (unsigned int indent, Dwarf_Die *die)
437 {
438 Dwarf_Die child;
439 Dwarf_Attribute attr_mem;
440 Dwarf_Die typedie_mem;
441 Dwarf_Die *typedie;
442 if (dwarf_child (die, &child) == 0)
443 do
444 switch (dwarf_tag (&child))
445 {
446 case DW_TAG_variable:
447 case DW_TAG_formal_parameter:
448 printf ("%*s%-30s[%6" PRIx64 "]", indent, "",
449 dwarf_diename (&child),
450 (uint64_t) dwarf_dieoffset (&child));
451 typedie = dwarf_formref_die
452 (dwarf_attr_integrate (&child, DW_AT_type, &attr_mem),
453 &typedie_mem);
454 print_type (typedie, '\t');
455 puts ("");
456 break;
457 default:
458 break;
459 }
460 while (dwarf_siblingof (&child, &child) == 0);
461 }
462
463 static int
464 handle_function (Dwarf_Die *funcdie, void *arg)
465 {
466 struct dwfunc *a = arg;
467 Dwarf_Addr entrypc;
468 int result;
469 int i = 0;
470 Dwarf_Addr *bkpts = NULL;
471 if (arg == NULL)
472 error (2, 0, "Error, dwfl structure empty");
473 const char *name = dwarf_diename (funcdie);
474 if (name == NULL)
475 error (2, 0, "Error, dwarf_diename returned NULL from Dwarf_die");
476 if (dwarf_entrypc (funcdie, &entrypc) == 0)
477 {
478 entrypc += a->dwbias;
479 result = dwarf_entry_breakpoints (funcdie, &bkpts);
480 if (a->funcname == NULL)
481 {
482 printf ("%-35s %#.16" PRIx64, name, entrypc);
483 /* error check the result is greater than 0 */
484 if (result > 0)
485 {
486 /* the formatting changes as a looka-head if we
487 need different ending whitespace chars the
488 location is a combination of the address +
489 the offset (bias) */
490 for (i = 0; i < result; i++)
491 printf (" %#.16" PRIx64 "%s", bkpts[i] + a->dwbias,
492 i == result - 1 ? "\n" : "");
493 free (bkpts);
494 }
495 }
496 else if (a->funcname != NULL && (!strcmp (a->funcname, name)))
497 {
498 if (!a->matchdebug)
499 {
500 entrypc += a->dwbias;
501 a->pc = entrypc;
502 free (bkpts);
503 return DWARF_CB_ABORT;
504 }
505 else if (result == 1 && a->matchdebug)
506 {
507 a->pc = (bkpts[0] + a->dwbias);
508 free (bkpts);
509 return DWARF_CB_ABORT;
510 }
511 else if (result > 1 && a->matchdebug)
512 {
513 printf ("Function: %-35s has multiple breakpoints: ", name);
514 for (i = 0; i < result; i++)
515 printf (" %#.16" PRIx64 "%s", bkpts[i] + a->dwbias,
516 i == result - 1 ? "\n" : "");
517 free (bkpts);
518 return DWARF_CB_ABORT;
519 }
520 else
521 {
522 error (2, 0, "Error, dwarf_entry_breakpoints returned an error( %s )\n",
523 dwarf_errmsg (result));
524 }
525 }
526 }
527 return 0;
528 }
529
530 #define INDENT 4
531
532 int
533 main (int argc, char **argv)
534 {
535 /* We use no threads here which can interfere with handling a stream. */
536 (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
537
538 #if ENABLE_NLS
539 /* Set locale. */
540 (void) setlocale (LC_ALL, "");
541 #endif
542
543 const struct argp_child argp_children[] =
544 {
545 { .argp = dwfl_standard_argp () },
546 { .argp = NULL }
547 };
548 const struct argp argp =
549 {
550 .children = argp_children,
551 .args_doc = "ADDRESS\n\
552 FUNCTIONNAME\n\
553 ADDRESS VARIABLE [FIELD...]\n\
554 FUNCTIONNAME VARIABLE [FIELD...]\n\
555 ADDRESS VARIABLE [FIELD...] =",
556 .doc = "Process DWARF locations visible with PC at ADDRESS.\v\
557 ADDRESS must be in %i format (i.e. \"0x...\").\n\
558 FUNCTIONNAME must be exact or prepended with '@' character to specify \
559 breakpoint entry.\n\
560 In the first and second form, display the scope entries containing \
561 ADDRESS or FUNCTIONNAME, and the variables/parameters visible there, \
562 with their type names. Hex numbers within \"[...]\" are DIE offsets.\n\
563 In the third and fourth form, emit a C code fragment to access a \
564 variable. Each FIELD argument is the name of a member of an aggregate \
565 type (or pointer to one);\
566 \"+INDEX\" to index into an array type (or offset a pointer type);\
567 or \"\" (an empty argument) to dereference a pointer type.\n\
568 In the fifth form, the access is a store rather than a fetch."
569
570 };
571 Dwfl *dwfl = NULL;
572 int argi;
573 (void) argp_parse (&argp, argc, argv, 0, &argi, &dwfl);
574 assert (dwfl != NULL);
575 struct dwfunc a = { .dwfl = dwfl, .funcname = NULL,
576 .pc = 0, .matchdebug = 0 };
577 if (argi == argc)
578 {
579 printf ("%-35s %-18s %s\n",
580 "Function", "Address", "Debug Entry Address(s)");
581 while ((a.cu = dwfl_nextcu(a.dwfl, a.cu, &a.dwbias)) != NULL)
582 dwarf_getfuncs (a.cu, &handle_function, &a.dwfl, 0);
583 return 0;
584 }
585
586 char *endp;
587 uintmax_t pc = strtoumax (argv[argi], &endp, 0);
588 if (endp == argv[argi])
589 {
590 a.funcname = argv[argi];
591 /* We need to check and adjust for a possible '@' character */
592 if (a.funcname[0] == '@')
593 {
594 a.funcname++;
595 a.matchdebug = 1;
596 }
597
598 while ((a.cu = dwfl_nextcu(a.dwfl, a.cu, &a.dwbias)) != NULL)
599 dwarf_getfuncs (a.cu, &handle_function, &a.dwfl, 0);
600 /* If a.pc isn't set, that means the function specified wasn't found */
601 if (!a.pc)
602 error (EXIT_FAILURE, 0, "function: '%s' not found\n", argv[argi]);
603 pc = a.pc;
604 }
605
606 Dwarf_Addr cubias;
607 Dwarf_Die *cudie = dwfl_addrdie (dwfl, pc, &cubias);
608 if (cudie == NULL)
609 error (EXIT_FAILURE, 0, "dwfl_addrdie: %s", dwfl_errmsg (-1));
610
611 Dwarf_Die *scopes;
612 int n = dwarf_getscopes (cudie, pc - cubias, &scopes);
613 if (n < 0)
614 error (EXIT_FAILURE, 0, "dwarf_getscopes: %s", dwarf_errmsg (-1));
615 else if (n == 0)
616 error (EXIT_FAILURE, 0, "%#" PRIx64 ": not in any scope\n", pc);
617
618 if (++argi == argc)
619 {
620 unsigned int indent = 0;
621 while (n-- > 0)
622 {
623 Dwarf_Die *const die = &scopes[n];
624
625 indent += INDENT;
626 printf ("%*s[%6" PRIx64 "] %s (%#x)", indent, "",
627 dwarf_dieoffset (die),
628 dwarf_diename (die) ?: "<unnamed>",
629 dwarf_tag (die));
630
631 Dwarf_Addr lowpc, highpc;
632 if (dwarf_lowpc (die, &lowpc) == 0
633 && dwarf_highpc (die, &highpc) == 0)
634 {
635 lowpc += cubias;
636 highpc += cubias;
637 Dwfl_Line *loline = dwfl_getsrc (dwfl, lowpc);
638 Dwfl_Line *hiline = dwfl_getsrc (dwfl, highpc);
639 paddr (": ", lowpc, loline);
640 if (highpc != lowpc)
641 paddr (" .. ", lowpc, hiline == loline ? NULL : hiline);
642 }
643 puts ("");
644
645 print_vars (indent + INDENT, die);
646 }
647 }
648 else
649 {
650 char *spec = argv[argi++];
651
652 if (!strcmp (spec, "return"))
653 {
654 int i;
655 for (i = 0; i < n; ++i)
656 if (dwarf_tag (&scopes[i]) == DW_TAG_subprogram)
657 {
658 const Dwarf_Op *locexpr;
659 int locexpr_len = dwfl_module_return_value_location
660 (dwfl_addrmodule (dwfl, pc), &scopes[i], &locexpr);
661 if (locexpr_len < 0)
662 error (EXIT_FAILURE, 0,
663 "dwfl_module_return_value_location: %s",
664 dwfl_errmsg (-1));
665 struct obstack pool;
666 obstack_init (&pool);
667 struct location *head, *tail = NULL;
668 head = c_translate_location (&pool, &fail, NULL, NULL,
669 1, cubias, pc, NULL,
670 locexpr, locexpr_len,
671 &tail, NULL, NULL);
672 handle_fields (&pool, head, tail, cubias, &scopes[i], pc,
673 &argv[argi]);
674 free (scopes);
675 dwfl_end (dwfl);
676 return 0;
677 }
678 error (EXIT_FAILURE, 0, "no subprogram to have a return value!");
679 }
680
681 int lineno = 0, colno = 0, shadow = 0;
682 char *at = strchr (spec, '@');
683 if (at != NULL)
684 {
685 *at++ = '\0';
686 if (sscanf (at, "%*[^:]:%i:%i", &lineno, &colno) < 1)
687 lineno = 0;
688 }
689 else
690 {
691 int len;
692 if (sscanf (spec, "%*[^+]%n+%i", &len, &shadow) == 2)
693 spec[len] = '\0';
694 }
695
696 Dwarf_Die vardie;
697 int out = dwarf_getscopevar (scopes, n, spec, shadow, at, lineno, colno,
698 &vardie);
699 if (out == -2)
700 error (0, 0, "no match for %s (+%d, %s:%d:%d)",
701 spec, shadow, at, lineno, colno);
702 else if (out < 0)
703 error (0, 0, "dwarf_getscopevar: %s (+%d, %s:%d:%d): %s",
704 spec, shadow, at, lineno, colno, dwarf_errmsg (-1));
705 else
706 {
707 Dwarf_Op *cfa_ops = NULL;
708
709 size_t cfa_nops;
710 Dwarf_Addr bias;
711 Dwfl_Module *module = dwfl_addrmodule (dwfl, pc);
712 if (module != NULL)
713 {
714 // Try debug_frame first, then fall back on eh_frame.
715 Dwarf_CFI *cfi = dwfl_module_dwarf_cfi (module, &bias);
716 if (cfi != NULL)
717 {
718 Dwarf_Frame *frame = NULL;
719 if (dwarf_cfi_addrframe (cfi, pc - bias, &frame) == 0)
720 dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops);
721 }
722 if (cfa_ops == NULL)
723 {
724 cfi = dwfl_module_eh_cfi (module, &bias);
725 if (cfi != NULL)
726 {
727 Dwarf_Frame *frame = NULL;
728 if (dwarf_cfi_addrframe (cfi, pc - bias, &frame) == 0)
729 dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops);
730 }
731 }
732 }
733
734 handle_variable (scopes, n, out, cubias, &vardie, pc, cfa_ops,
735 &argv[argi]);
736 }
737 }
738
739 free (scopes);
740
741 dwfl_end (dwfl);
742
743 return 0;
744 }
745
746 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.076032 seconds and 5 git commands to generate.