Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
dwarf_cfa.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2014 The University of Utah
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include <stdlib.h>
20 #include <stdbool.h>
21 #include <string.h>
22 #include <inttypes.h>
23 #include <assert.h>
24 
25 #include <dwarf.h>
26 #include <gelf.h>
27 #include <elfutils/libebl.h>
28 #include <elfutils/libdw.h>
29 #include <elfutils/libdwfl.h>
30 
31 #include "common.h"
32 #include "clfit.h"
33 #include "alist.h"
34 #include "binfile.h"
35 #include "dwdebug.h"
36 #include "dwdebug_priv.h"
37 
38 #include "memory-access.h"
39 
40 static const unsigned char *__read_encoded(unsigned int encoding,
41  unsigned int wordsize,
42  const unsigned char *readp,
43  const unsigned char *const endp,
44  uint64_t *res,Dwarf *dbg);
46  struct location_ctxt *lctxt,
47  REG reg,REGVAL *o_regval);
48 /*
49  * DWARF register rules.
50  */
51 typedef enum {
52  RRT_UNDEF = 0,
53  RRT_SAME = 1,
56  RRT_REG = 5,
57  RRT_EXPR = 6,
59  RRT_ARCH = 8,
61 
64  union {
65  uint64_t reg;
66  struct {
67  const unsigned char *block;
68  unsigned int len;
69  } block;
70  struct {
71  uint64_t reg;
72  int64_t offset;
73  } offset;
74  };
75 };
76 
77 /*
78  * When we parse the CFA program, we might not have any location_ops to
79  * tell us which platform register is the stack pointer register -- so
80  * we need a special macro to represent the CFA pseudo-register (which
81  * is the stack pointer register value in the previous frame). So,
82  * whenever we load this register in a frame, we must also cache it in
83  * the register table as the stack pointer's value in the previous
84  * frame.
85  */
86 #define DWARF_CFA_REG INT8_MAX
87 
88 /*
89  * Our cached CIE data is small. We don't need length, CIE_id,
90  * address_size (assumed to be the debugfile's wordsize); we do need
91  * segment size; augmentation (split into decoded fields);
92  * code_alignment_factor; data_alignment_factor; return_address_register.
93  */
94 struct dwarf_cfa_cie {
95  ptrdiff_t offset;
96  uint8_t version;
97  uint8_t segment_size;
98  unsigned int code_alignment_factor;
101  unsigned int fde_encoding;
102  unsigned int lsda_encoding;
103  uint64_t personality;
104  char *aug;
105  unsigned int auglen;
106  /* A table of int to struct dwarf_cfa_regrule *. */
107  GHashTable *default_regrules;
108 };
109 
111  ptrdiff_t offset;
115  /* ADDR vma_base; */
116  unsigned char *instructions;
117  unsigned int len;
118 
119  /* A table of int to clmatchone_t. */
120  GHashTable *regrules;
121 };
122 
123 static void dwarf_cfa_fde_free(struct dwarf_cfa_fde *fde) {
124  GHashTableIter iter;
125  gpointer vp,kp;
126  clmatchone_t *cl;
127  struct dwarf_cfa_regrule *rr;
128  Word_t o_index = ADDRMAX;
129 
130  if (fde->regrules) {
131  g_hash_table_iter_init(&iter,fde->regrules);
132  while (g_hash_table_iter_next(&iter,&kp,&vp)) {
133  cl = (clmatchone_t *)vp;
134  while ((rr = (struct dwarf_cfa_regrule *) \
135  clmatchone_find(cl,o_index,&o_index))) {
136  /* Look for a previous index so not to double free. */
137  o_index -= 1;
138  free(rr);
139  }
140  clmatchone_free(*cl);
141  g_hash_table_iter_replace(&iter,NULL);
142  }
143  g_hash_table_destroy(fde->regrules);
144  }
145 
146  free(fde);
147 }
148 
149 static void dwarf_cfa_cie_free(struct dwarf_cfa_cie *cie) {
150  GHashTableIter iter;
151  gpointer vp,kp;
152  struct dwarf_cfa_regrule *rr;
153 
154  if (cie->default_regrules) {
155  g_hash_table_iter_init(&iter,cie->default_regrules);
156  while (g_hash_table_iter_next(&iter,&kp,&vp)) {
157  rr = (struct dwarf_cfa_regrule *)vp;
158  free(rr);
159  g_hash_table_iter_replace(&iter,NULL);
160  }
161  g_hash_table_destroy(cie->default_regrules);
162  }
163 
164  free(cie);
165 }
166 
168  struct dwarf_cfa_cie *cie,
169  struct dwarf_cfa_fde *fde,
170  const unsigned char *buf,unsigned int len,
171  GHashTable *regrules) {
172  /* XXX: we can't get other_byte_order from dbg since we don't have
173  * the struct def for it... so we assume it's not a diff byte order
174  * than the phys host for now.
175  */
176  int obo = 0;
177  const unsigned char *readp = buf;
178  const unsigned char *const endp = readp + len;
179  ADDR pc;
180  /* Dwarf_Word vma_base; */
181  uint64_t op1;
182  int64_t sop1;
183  uint64_t op2;
184  int64_t sop2;
185  uint_fast8_t opcode;
186  struct dwarf_cfa_regrule *rr;
187  struct dwarf_cfa_regrule *last_cfa_rr = NULL;
188  struct dwarf_cfa_regrule *def_rr;
189  int wordsize;
190  struct dwarf_debugfile_info *ddi;
191  GSList *stack = NULL;
192  GHashTable *stackhash;
193  GHashTableIter iter;
194  gpointer kp,vp;
195  struct dwarf_cfa_regrule *tmp_rr;
196  clmatchone_t *cl;
197 
198  ddi = (struct dwarf_debugfile_info *)debugfile->priv;
199 
200  pc = 0;
201  /*
202  if (fde && fde->vma_base)
203  pc = fde->vma_base;
204  */
205  if (fde)
206  pc = fde->initial_location;
207 
208  last_cfa_rr = (struct dwarf_cfa_regrule *) \
209  g_hash_table_lookup(cie->default_regrules,
210  (gpointer)(uintptr_t)DWARF_CFA_REG);
211 
212  inline void __insert_regrule(ADDR pc,uint64_t reg,
213  struct dwarf_cfa_regrule *rr) {
214  clmatchone_t *_cl;
215  struct dwarf_cfa_regrule *_tmp_rr;
216 
217  if (!regrules)
218  return;
219 
220  /*
221  * NB: if we are doing an FDE, we need to create a clmatchone
222  * structure to index based on pc. But, if we're doing CIE,
223  * then each reg has only a single default regrule, so we don't
224  * create clmatchones for those!
225  */
226  if (fde) {
227  _cl = (clmatchone_t *) \
228  g_hash_table_lookup(regrules,(gpointer)(uintptr_t)reg);
229  if (!_cl) {
230  _cl = calloc(1,sizeof(*_cl));
231  *_cl = clmatchone_create();
232  }
233  clmatchone_add(_cl,pc,rr);
234  g_hash_table_insert(regrules,(gpointer)(uintptr_t)reg,_cl);
235  }
236  else {
237  _tmp_rr = (struct dwarf_cfa_regrule *) \
238  g_hash_table_lookup(regrules,(gpointer)(uintptr_t)reg);
239  if (_tmp_rr) {
240  vwarn("r%"PRIu64" already has a default value in CIE 0x%lx;"
241  " will overwrite!\n",reg,(unsigned long)cie->offset);
242  free(_tmp_rr);
243  }
244  g_hash_table_insert(regrules,(gpointer)(uintptr_t)reg,rr);
245  }
246  }
247 
248  while (readp < endp) {
249  opcode = *readp++;
250 
251  switch (opcode) {
252  /*
253  * Padding Instruction.
254  */
255  case DW_CFA_nop:
256  break;
257 
258  /*
259  * Row Creation Instructions.
260  */
261  case DW_CFA_set_loc:
262  switch (cie->fde_encoding & 7) {
263  case 2: wordsize = 2; break;
264  case 3: wordsize = 4; break;
265  case 4: wordsize = 8; break;
266  default: wordsize = debugfile->binfile->arch->wordsize;
267  }
268 
269  const unsigned char *base = readp;
270  if (cie->fde_encoding & DW_EH_PE_signed)
271  op1 = read_sbyte_unaligned_inc(wordsize,obo,readp);
272  else
273  op1 = read_ubyte_unaligned_inc(wordsize,obo,readp);
274 
275  if ((cie->fde_encoding & 0x70) == DW_EH_PE_pcrel)
276  op1 += ddi->frame_sec_addr
277  + (base - (unsigned char *)debugfile->frametab);
278  pc = op1;
279  // XXX overflow check
280  //get_leb128(op1,readp);
281  /*
282  if (fde)
283  vma_base = fde->vma_base;
284  else
285  vma_base = 0;
286  pc = (op1 + vma_base) * cie->code_alignment_factor;
287 
288  if ((cie->fde_encoding & 0x70) == DW_EH_PE_pcrel)
289  fde->initial_location += ddi->frame_sec_addr
290  + (base - (unsigned char *)debugfile->frametab);
291  */
292  vdebug(8,LA_DEBUG,LF_DCFA,"DW_CFA_set_loc 0x%"PRIxADDR"\n",pc);
293  break;
294 
295  case DW_CFA_advance_loc ... (DW_CFA_advance_loc + 0x3f):
296  op1 = opcode & 0x3f;
297  pc += op1 * cie->code_alignment_factor;
299  "DW_CFA_advance_loc %u to 0x%"PRIxADDR"\n",op1,pc);
300  break;
301  case DW_CFA_advance_loc1:
302  pc += *readp * cie->code_alignment_factor;
304  "DW_CFA_advance_loc1 %u to 0x%"PRIxADDR"\n",*readp,pc);
305  ++readp;
306  break;
307  case DW_CFA_advance_loc2:
308  op1 = read_2ubyte_unaligned_inc(obo,readp);
309  pc += op1 * cie->code_alignment_factor;
311  "DW_CFA_advance_loc2 %"PRIu64" to 0x%"PRIxADDR"\n",op1,pc);
312  break;
313  case DW_CFA_advance_loc4:
314  op1 = read_4ubyte_unaligned_inc(obo,readp);
315  pc += op1 * cie->code_alignment_factor;
317  "DW_CFA_advance_loc4 %"PRIu64" to 0x%"PRIxADDR"\n",op1,pc);
318  break;
319  case DW_CFA_MIPS_advance_loc8:
320  op1 = read_8ubyte_unaligned_inc(obo,readp);
321  pc += op1 * cie->code_alignment_factor;
323  "DW_CFA_MIPS_advance_loc8 %"PRIu64" to 0x%"PRIxADDR"\n",
324  op1,pc);
325  break;
326 
327  /*
328  * CFA Definition Instructions.
329  */
330  case DW_CFA_def_cfa:
331  // XXX overflow check
332  get_uleb128(op1,readp);
333  get_uleb128(op2,readp);
335  "DW_CFA_def_cfa r%"PRIu64" at offset %"PRIu64"\n",op1,op2);
336 
337  rr = calloc(1,sizeof(*rr));
338  rr->rrt = RRT_VAL_OFFSET;
339  rr->offset.reg = op1;
340  rr->offset.offset = (int64_t)op2;
341 
342  __insert_regrule(pc,DWARF_CFA_REG,rr);
343  last_cfa_rr = rr;
344 
345  break;
346  case DW_CFA_def_cfa_sf:
347  // XXX overflow check
348  get_uleb128(op1,readp);
349  get_sleb128(sop2,readp);
351  "DW_CFA_def_cfa_sf r%"PRIu64" at offset %"PRId64"\n",
352  op1,sop2 * cie->data_alignment_factor);
353 
354  rr = calloc(1,sizeof(*rr));
355  rr->rrt = RRT_VAL_OFFSET;
356  rr->offset.reg = op1;
357  rr->offset.offset = sop2;
358 
359  __insert_regrule(pc,DWARF_CFA_REG,rr);
360  last_cfa_rr = rr;
361 
362  break;
363  case DW_CFA_def_cfa_register:
364  // XXX overflow check
365  get_uleb128(op1,readp);
366 
367  rr = calloc(1,sizeof(*rr));
368  if (last_cfa_rr && last_cfa_rr->rrt == RRT_VAL_OFFSET) {
369  rr->rrt = RRT_VAL_OFFSET;
370  rr->offset.reg = op1;
371  rr->offset.offset = last_cfa_rr->offset.offset;
372 
374  "DW_CFA_def_cfa_register r%"PRIu64
375  " (current offset %"PRId64")\n",
376  op1,rr->offset.offset);
377  }
378  else {
379  rr->rrt = RRT_VAL_OFFSET;
380  rr->offset.reg = op1;
381  rr->offset.offset = 0;
382 
383  vwarn("DW_CFA_def_cfa_register r%"PRIu64" but no current CFA"
384  " regrule to get last CFA offset; assuming offset 0!\n",
385  op1);
386  }
387 
388  __insert_regrule(pc,DWARF_CFA_REG,rr);
389  last_cfa_rr = rr;
390 
391  break;
392  case DW_CFA_def_cfa_offset:
393  // XXX overflow check
394  get_uleb128(op1,readp);
395 
396  rr = calloc(1,sizeof(*rr));
397  if (last_cfa_rr && last_cfa_rr->rrt == RRT_VAL_OFFSET) {
398  rr->rrt = RRT_VAL_OFFSET;
399  rr->offset.reg = last_cfa_rr->offset.reg;
400  rr->offset.offset = (int64_t)op1;
401 
403  "DW_CFA_def_cfa_offset offset %"PRId64
404  " (current r%"PRIu64")\n",
405  (int64_t)op1,rr->offset.reg);
406  }
407  else {
408  rr->rrt = RRT_VAL_OFFSET;
409  rr->offset.reg = 0;
410  rr->offset.offset = (int64_t)op1;
411 
412  vwarn("DW_CFA_def_cfa_offset offset %"PRIu64" but no current CFA"
413  " regrule to get last CFA offset; assuming reg 0!\n",
414  op1);
415  }
416 
417  __insert_regrule(pc,DWARF_CFA_REG,rr);
418  last_cfa_rr = rr;
419 
420  break;
421  case DW_CFA_def_cfa_offset_sf:
422  // XXX overflow check
423  get_sleb128(sop1,readp);
424  sop1 *= cie->data_alignment_factor;
425 
426  if (last_cfa_rr && last_cfa_rr->rrt == RRT_VAL_OFFSET) {
427  rr = calloc(1,sizeof(*rr));
428  rr->rrt = RRT_VAL_OFFSET;
429  rr->offset.reg = last_cfa_rr->offset.reg;
430  rr->offset.offset = sop1;
431 
433  "DW_CFA_def_cfa_offset_sf offset %"PRId64
434  " (current r%"PRIu64")\n",
435  sop1,rr->offset.reg);
436  }
437  else {
438  vwarn("DW_CFA_def_cfa_offset_sf offset %"PRId64" but no current CFA"
439  " regrule to get last CFA offset; skipping!!\n",
440  sop1);
441  break;
442  }
443 
444  __insert_regrule(pc,DWARF_CFA_REG,rr);
445  last_cfa_rr = rr;
446 
447  break;
448  case DW_CFA_def_cfa_expression:
449  // XXX overflow check
450  get_uleb128(op1,readp); /* Length of DW_FORM_block. */
452  "DW_CFA_def_cfa_expression len %"PRIu64"\n",op1);
453 
454  rr = calloc(1,sizeof(*rr));
455  rr->rrt = RRT_VAL_EXPR;
456  rr->block.block = readp;
457  rr->block.len = op1;
458 
459  __insert_regrule(pc,DWARF_CFA_REG,rr);
460  last_cfa_rr = rr;
461 
462  readp += op1;
463  break;
464 
465  /*
466  * Register Rule Instructions.
467  */
468  case DW_CFA_undefined:
469  // XXX overflow check
470  get_uleb128(op1,readp);
471  vdebug(8,LA_DEBUG,LF_DCFA,"DW_CFA_undefined r%"PRIu64"\n",op1);
472 
473  rr = calloc(1,sizeof(*rr));
474  rr->rrt = RRT_UNDEF;
475 
476  __insert_regrule(pc,op1,rr);
477 
478  break;
479  case DW_CFA_same_value:
480  // XXX overflow check
481  get_uleb128(op1,readp);
482  vdebug(8,LA_DEBUG,LF_DCFA,"DW_CFA_same_value r%"PRIu64"\n",op1);
483 
484  rr = calloc(1,sizeof(*rr));
485  rr->rrt = RRT_SAME;
486 
487  __insert_regrule(pc,op1,rr);
488 
489  break;
490  /*
491  * NB: some DWARF emitters (gcc) do this; I have no idea why.
492  * But they mean DW_CFA_offset. Well, actually, I'm not sure if
493  * they do. There seems to be an 0x90 opcode that is used, and
494  * instead of it meaning an unsigned offset, it seems to be a
495  * signed offset. So -- we try to handle DW_CFA_offset the
496  * unsigned way; and DW_CFA_offset + 1 ... the signed way. Who
497  * knows...
498  */
499  case DW_CFA_offset:
500  // XXX overflow check
501  op1 = opcode & 0x3f;
502  get_uleb128(op2,readp);
503  sop2 = op2 * cie->data_alignment_factor;
504  vdebug(8,LA_DEBUG,LF_DCFA,"DW_CFA_offset r%u at cfa%+"PRId64"\n",
505  op1,sop2);
506 
507  rr = calloc(1,sizeof(*rr));
508  rr->rrt = RRT_OFFSET;
509  rr->offset.reg = DWARF_CFA_REG;
510  rr->offset.offset = sop2;
511 
512  __insert_regrule(pc,op1,rr);
513 
514  break;
515  case (DW_CFA_offset + 1) ... (DW_CFA_offset + 0x3f):
516  // XXX overflow check
517  op1 = opcode & 0x3f;
518  get_uleb128(op2,readp);
519  sop2 = op2 * cie->data_alignment_factor;
520  vdebug(8,LA_DEBUG,LF_DCFA,"DW_CFA_offset r%u at cfa%+"PRId64"\n",
521  op1,(int64_t)sop2);
522 
523  rr = calloc(1,sizeof(*rr));
524  rr->rrt = RRT_OFFSET;
525  rr->offset.reg = DWARF_CFA_REG;
526  rr->offset.offset = sop2;
527 
528  __insert_regrule(pc,op1,rr);
529 
530  break;
531  case DW_CFA_offset_extended:
532  // XXX overflow check
533  get_uleb128(op1,readp);
534  get_uleb128(op2,readp);
535  sop2 = op2 * cie->data_alignment_factor;
537  "DW_CFA_offset_extended r%"PRIu64" at cfa%+"PRId64"\n",
538  op1,sop2);
539 
540  rr = calloc(1,sizeof(*rr));
541  rr->rrt = RRT_OFFSET;
542  rr->offset.reg = DWARF_CFA_REG;
543  rr->offset.offset = sop2;
544 
545  __insert_regrule(pc,op1,rr);
546 
547  break;
548  case DW_CFA_offset_extended_sf:
549  // XXX overflow check
550  get_uleb128(op1,readp);
551  get_sleb128(sop2,readp);
552  sop2 *= cie->data_alignment_factor;
554  "DW_CFA_offset_extended_sf r%"PRIu64" at cfa%+"PRId64"\n",
555  op1,sop2);
556 
557  rr = calloc(1,sizeof(*rr));
558  rr->rrt = RRT_OFFSET;
559  rr->offset.reg = DWARF_CFA_REG;
560  rr->offset.offset = sop2;
561 
562  __insert_regrule(pc,op1,rr);
563 
564  break;
565  /* Obsoleted by DW_CFA_offset_extended_sf. */
566  case DW_CFA_GNU_negative_offset_extended:
567  // XXX overflow check
568  get_uleb128(op1,readp);
569  get_uleb128(op2,readp);
571  "DW_CFA_negative_offset_extended r%"PRIu64" at cfa-%"PRIu64"\n",
572  op1,op2);
573 
574  rr = calloc(1,sizeof(*rr));
575  rr->rrt = RRT_OFFSET;
576  rr->offset.reg = DWARF_CFA_REG;
577  rr->offset.offset = -(int64_t)op2;
578 
579  __insert_regrule(pc,op1,rr);
580 
581  break;
582  case DW_CFA_val_offset:
583  // XXX overflow check
584  get_uleb128(op1,readp);
585  get_uleb128(op2,readp);
586  sop2 = op2 * cie->data_alignment_factor;
588  "DW_CFA_val_offset r%"PRIu64" at offset %"PRId64"\n",
589  op1,sop2);
590 
591  rr = calloc(1,sizeof(*rr));
592  rr->rrt = RRT_VAL_OFFSET;
593  rr->offset.reg = DWARF_CFA_REG;
594  rr->offset.offset = sop2;
595 
596  __insert_regrule(pc,op1,rr);
597 
598  break;
599  case DW_CFA_val_offset_sf:
600  // XXX overflow check
601  get_uleb128(op1,readp);
602  get_sleb128(sop2,readp);
603  sop2 *= cie->data_alignment_factor;
605  "DW_CFA_val_offset_sf r%"PRIu64" at offset %"PRId64"\n",
606  op1,sop2);
607 
608  rr = calloc(1,sizeof(*rr));
609  rr->rrt = RRT_VAL_OFFSET;
610  rr->offset.reg = DWARF_CFA_REG;
611  rr->offset.offset = sop2;
612 
613  __insert_regrule(pc,op1,rr);
614 
615  break;
616  case DW_CFA_register:
617  // XXX overflow check
618  get_uleb128(op1,readp);
619  get_uleb128(op2,readp);
621  "DW_CFA_register r%"PRIu64" in r%"PRIu64"\n",op1,op2);
622 
623  rr = calloc(1,sizeof(*rr));
624  rr->rrt = RRT_REG;
625  rr->reg = op2;
626 
627  __insert_regrule(pc,op1,rr);
628 
629  break;
630  case DW_CFA_expression:
631  // XXX overflow check
632  get_uleb128(op1,readp);
633  get_uleb128(op2,readp); /* Length of DW_FORM_block. */
635  "DW_CFA_expression r%"PRIu64" len %"PRIu64"\n",op1,op2);
636 
637  rr = calloc(1,sizeof(*rr));
638  rr->rrt = RRT_EXPR;
639  rr->block.block = readp;
640  rr->block.len = op2;
641 
642  __insert_regrule(pc,op1,rr);
643 
644  readp += op2;
645  break;
646  case DW_CFA_val_expression:
647  // XXX overflow check
648  get_uleb128(op1,readp);
649  get_uleb128(op2,readp); /* Length of DW_FORM_block. */
651  "DW_CFA_val_expression r%"PRIu64" len %"PRIu64"\n",op1,op2);
652 
653  rr = calloc(1,sizeof(*rr));
654  rr->rrt = RRT_VAL_EXPR;
655  rr->block.block = readp;
656  rr->block.len = op2;
657 
658  __insert_regrule(pc,op1,rr);
659 
660  readp += op2;
661  break;
662  case DW_CFA_restore ... (DW_CFA_restore + 0x3f):
663  op1 = opcode & 0x3f;
664  vdebug(8,LA_DEBUG,LF_DCFA,"DW_CFA_restore r%"PRIu64"\n",op1);
665 
666  rr = calloc(1,sizeof(*rr));
667  def_rr = (struct dwarf_cfa_regrule *) \
668  g_hash_table_lookup(cie->default_regrules,
669  (gpointer)(uintptr_t)op1);
670  if (!def_rr) {
672  "no default regrule for r%"PRIu64"; undefining!\n",op1);
673  rr->rrt = RRT_UNDEF;
674  }
675  else {
676  memcpy(rr,def_rr,sizeof(*rr));
677  }
678 
679  __insert_regrule(pc,op1,rr);
680 
681  break;
682  case DW_CFA_restore_extended:
683  // XXX overflow check
684  get_uleb128(op1,readp);
685  vdebug(8,LA_DEBUG,LF_DCFA,"DW_CFA_restore_extended r%"PRIu64"\n",op1);
686 
687  rr = calloc(1,sizeof(*rr));
688  def_rr = (struct dwarf_cfa_regrule *) \
689  g_hash_table_lookup(cie->default_regrules,
690  (gpointer)(uintptr_t)op1);
691  if (!def_rr) {
693  "no default regrule for r%"PRIu64"; undefining!\n",op1);
694  rr->rrt = RRT_UNDEF;
695  }
696  else {
697  memcpy(rr,def_rr,sizeof(*rr));
698  }
699 
700  __insert_regrule(pc,op1,rr);
701 
702  break;
703 
704  /*
705  * Row State Instructions.
706  */
707  case DW_CFA_remember_state:
708  /*
709  * Create a tmp hashtable; grab the last regrule for each
710  * reg in the current hashtable; and put them into the tmp
711  * hashtable and push that onto an array_list stack. Don't
712  * clone them on push; just clone on pop (restore).
713  */
714  stackhash = g_hash_table_new(g_direct_hash,g_direct_equal);
715  g_hash_table_iter_init(&iter,regrules);
716  while (g_hash_table_iter_next(&iter,&kp,&vp)) {
717  cl = (clmatchone_t *)vp;
718  tmp_rr = (struct dwarf_cfa_regrule *) \
719  clmatchone_find(cl,ADDRMAX,NULL);
720  g_hash_table_insert(stackhash,kp,tmp_rr);
721  }
722  /*
723  * XXX: should we bother with default rules? Probably not,
724  * because they'll still be the default rules; why
725  * duplicate them?
726  */
727 
728  stack = g_slist_prepend(stack,stackhash);
729 
730  vdebug(8,LA_DEBUG,LF_DCFA,"DW_CFA_remember_state (%d registers)\n",
731  g_hash_table_size(stackhash));
732 
733  break;
734  case DW_CFA_restore_state:
735  /*
736  * Ok, pop the latest tmp hashtable off the stack, clone the
737  * regrules, and insert them at the current pc.
738  */
739  if (!stack) {
740  verror("no stack for DW_CFA_restore_state; underflow; ignoring!\n");
741  break;
742  }
743 
744  stackhash = (GHashTable *)g_slist_nth_data(stack,0);
745  stack = g_slist_remove(stack,stackhash);
746 
747  g_hash_table_iter_init(&iter,stackhash);
748  while (g_hash_table_iter_next(&iter,&kp,&vp)) {
749  tmp_rr = (struct dwarf_cfa_regrule *)vp;
750  rr = calloc(1,sizeof(*rr));
751  memcpy(rr,tmp_rr,sizeof(*rr));
752  __insert_regrule(pc,(uint64_t)(uintptr_t)kp,rr);
753  }
754 
755  vdebug(8,LA_DEBUG,LF_DCFA,"DW_CFA_restore_state (%d registers)\n",
756  g_hash_table_size(stackhash));
757 
758  g_hash_table_destroy(stackhash);
759 
760  break;
761 
762  /*
763  * Extra stuff.
764  */
765  case DW_CFA_GNU_args_size:
766  // XXX overflow check
767  get_uleb128(op1,readp);
769  "DW_CFA_args_size %"PRIu64"; ignoring\n",op1);
770  break;
771 
772  /*
773  * And we're done.
774  */
775  default:
776  verror("unrecognized DW_CFA_??? opcode (%u); skipping!!\n",opcode);
777  break;
778  }
779  }
780 
781  return 0;
782 }
783 
785  unsigned char *buf,unsigned int len,Dwarf *dbg) {
786  struct dwarf_debugfile_info *ddi;
787  struct dwarf_cfa_cie *cie = NULL;
788  struct dwarf_cfa_fde *fde;
789  /* XXX: we can't get other_byte_order from dbg since we don't have
790  * the struct def for it... so we assume it's not a diff byte order
791  * than the phys host for now.
792  */
793  int obo = 0;
794 
795  ptrdiff_t offset,cie_offset;
796  Dwarf_Word unit_len;
797  unsigned int hlen;
798  int wordsize;
799  ptrdiff_t start;
800  unsigned char *unit_end;
801  Dwarf_Off cie_id;
802  uint_fast8_t version;
803  unsigned int code_alignment_factor;
804  int data_alignment_factor;
805  unsigned int fde_encoding;
806  unsigned int lsda_encoding;
807  uint_fast8_t segment_size;
808  unsigned int return_address_register;
809  char *aug;
810  unsigned int auglen;
811  uint64_t personality;
812  int rc;
813 
814  ddi = (struct dwarf_debugfile_info *)debugfile->priv;
815 
816  if (!debugfile->frametab) {
817  vwarnopt(8,LA_DEBUG,LF_DCFA,"no cfa info");
818  return 0;
819  }
820 
821  ddi->cfa_fde = clrangesimple_create();
822  ddi->cfa_cie = g_hash_table_new(g_direct_hash,g_direct_equal);
823 
824  /*
825  * Read CIEs/FDEs. Don't run CFA programs for FDEs; do that on demand.
826  */
827  const unsigned char *readp = (unsigned char *)buf;
828  const unsigned char *const end = readp + len;
829 
830  while (readp < end) {
831  if (unlikely(readp + 4 > end)) {
832  invalid_data:
833  verror("invalid CIE/FDE data at offset 0x%lx!\n",
834  (unsigned long)(readp - buf));
835  errno = EINVAL;
836  return -1;
837  }
838 
839  /* Read a CIE/FDE length/id. */
840  offset = readp - (unsigned char *)buf;
841  unit_len = read_4ubyte_unaligned_inc(obo,readp);
842  hlen = 4;
843  if (unlikely(unit_len == 0xffffffff)) {
844  if (unlikely (readp + 8 > end)) {
845  verror("CIE/FDE is too short for length field!\n");
846  goto invalid_data;
847  }
848 
849  unit_len = read_8ubyte_unaligned_inc(obo,readp);
850  hlen = 8;
851  }
852 
853  if (unlikely(unit_len == 0)) {
854  vdebug(8,LA_DEBUG,LF_DCFA,"zero-len CIE at %p\n",offset);
855  continue;
856  }
857 
858  start = readp - (unsigned char *)buf;
859  unit_end = (unsigned char *)readp + unit_len;
860  if (unlikely(unit_end > end || (readp + hlen) > end)) {
861  verror("CIE/FDE len exceeds data!\n");
862  goto invalid_data;
863  }
864 
865  if (hlen == 4) {
866  cie_id = read_4ubyte_unaligned_inc(obo,readp);
867  if (!ddi->is_eh_frame && cie_id == DW_CIE_ID_32)
868  cie_id = DW_CIE_ID_64;
869  }
870  else
871  cie_id = read_8ubyte_unaligned_inc(obo,readp);
872 
873  wordsize = debugfile->binfile->arch->wordsize;
874 
875  /* Read a CIE. */
876  if (cie_id == (ddi->is_eh_frame ? 0 : DW_CIE_ID_64)) {
877  cie = NULL;
878  fde = NULL;
879 
880  version = *readp++;
881  aug = (char *)readp;
882  readp = memchr(readp,'\0',(char *)unit_end - aug);
883  if (unlikely(readp == NULL)) {
884  verror("unterminated augmentation string!\n");
885  goto invalid_cie_data;
886  }
887  ++readp;
888 
889  if (aug[0] != '\0'
890  && aug[0] != 'z'
891  && !(aug[0] == 'e' && aug[1] == 'h')
892  && aug[0] != 'S') {
893  verror("unrecognized augmentation string '%s'; skipping!\n",
894  aug);
895  goto invalid_cie_data;
896  }
897 
898  segment_size = 0;
899  if (version >= 4) {
900  if (unit_end - readp < 5) {
901  verror("invalid version 4 CIE (not long enough for"
902  " wordsize, segment_size, code/data alignment"
903  " factors, return address register)!\n");
904  goto invalid_cie_data;
905  }
906  wordsize = *readp++;
907  segment_size = *readp++;
908 
909  if (!(likely(wordsize == 4 || wordsize == 8))) {
910  verror("bad wordsize %d in CIE 0x%"PRIxPTR"!\n",
911  wordsize,offset);
912  goto invalid_cie_data;
913  }
914  }
915 
916  // XXX Check overflow
917  get_uleb128(code_alignment_factor,readp);
918  // XXX Check overflow
919  get_sleb128(data_alignment_factor,readp);
920 
921  /* In some variant for unwind data there is another field. */
922  if (aug[0] == 'e' && aug[1] == 'h')
923  readp += wordsize;
924 
925  if (unlikely (version == 1))
926  return_address_register = *readp++;
927  else
928  // XXX Check overflow
929  get_uleb128(return_address_register,readp);
930 
932  "CIE 0x%lx length=%"PRIu64" id=%"PRIu64" version=%u"
933  " augmentation='%s' address_size=%u segment_size=%u"
934  " code_factor=%u data_factor=%d return_address_register=%u\n",
935  (unsigned long)offset,(uint64_t)unit_len,(uint64_t)cie_id,
936  version,aug,wordsize,segment_size,code_alignment_factor,
937  data_alignment_factor,return_address_register);
938 
939  fde_encoding = 0;
940  lsda_encoding = 0;
941  personality = 0;
942 
943  if (aug[0] == 'z') {
944  get_uleb128(auglen,readp);
945 
946  if (auglen > (size_t)(end - readp)) {
947  verror("invalid augmentation length %d\n",
948  (int)(end - readp));
949  goto invalid_cie_data;
950  }
951 
952  const char *cp = aug + 1;
953  while (*cp != '\0') {
954  if (*cp == 'R') {
955  fde_encoding = *readp++;
956  }
957  else if (*cp == 'L') {
958  lsda_encoding = *readp++;
959  }
960  else if (*cp == 'P') {
961  /* Personality. This field usually has a relocation
962  attached pointing to __gcc_personality_v0. */
963  unsigned int encoding = *readp++;
964  personality = 0;
965  readp = __read_encoded(encoding,
966  debugfile->binfile->arch->wordsize,
967  readp,readp - 1 + auglen,
968  &personality,dbg);
969  }
970  else {
971  vwarn("unrecognized augmentation substring (%s);"
972  " trying to skip substring (CIE 0x%lx)!\n",
973  (char *)readp,(unsigned long)offset);
974  ++readp;
975  }
976 
977  ++cp;
978  }
979  }
980 
981  /* Cache the CIE. */
982  cie = calloc(1,sizeof(*cie));
983  cie->offset = offset;
984  cie->version = version;
985  cie->segment_size = segment_size;
986  cie->code_alignment_factor = code_alignment_factor;
987  cie->data_alignment_factor = data_alignment_factor;
988  cie->fde_encoding = fde_encoding;
989  cie->lsda_encoding = lsda_encoding;
990  cie->personality = personality;
991  cie->return_address_register = return_address_register;
992  cie->default_regrules =
993  g_hash_table_new(g_direct_hash,g_direct_equal);
994  cie->aug = aug;
995  cie->auglen =
996  memchr(aug,'\0',(size_t)(unit_end - (unsigned char *)aug))
997  - (void *)aug;
998 
999  g_hash_table_insert(ddi->cfa_cie,(gpointer)offset,cie);
1000 
1001  /* Parse the CIE instructions to get default regrules. */
1002  dwarf_cfa_program_interpret(debugfile,cie,NULL,readp,
1003  unit_end - readp,cie->default_regrules);
1004 
1005  readp = unit_end;
1006  continue;
1007 
1008  invalid_cie_data:
1009  verror("invalid CIE (0x%lx) data at offset 0x%lx!\n",
1010  (unsigned long)offset,(unsigned long)(readp - buf));
1011  cie = NULL;
1012  readp = unit_end;
1013  continue;
1014  }
1015  /*
1016  * Parse an FDE once we are in a CIE!
1017  */
1018  else {
1019  cie_offset = (ddi->is_eh_frame) \
1020  ? start - (ptrdiff_t)cie_id : (ptrdiff_t)cie_id;
1021 
1022  cie = (struct dwarf_cfa_cie *) \
1023  g_hash_table_lookup(ddi->cfa_cie,(gpointer)cie_offset);
1024  if (!cie) {
1025  verror("invalid CIE reference 0x%lx in FDE 0x%lx; skipping FDE!\n",
1026  (unsigned long)cie_offset,(unsigned long)offset);
1027  return -1;
1028  }
1029 
1030  fde = calloc(1,sizeof(*fde));
1031  fde->cie = cie;
1032  fde->offset = offset;
1033 
1034  /* Initialize from CIE data. */
1035  lsda_encoding = cie->lsda_encoding;
1036  switch (cie->fde_encoding & 7) {
1037  case 2: wordsize = 2; break;
1038  case 3: wordsize = 4; break;
1039  case 4: wordsize = 8; break;
1040  default: wordsize = debugfile->binfile->arch->wordsize;
1041  }
1042 
1043  const unsigned char *base = readp;
1044  // XXX There are sometimes relocations for this value
1045  if (cie->fde_encoding & DW_EH_PE_signed)
1046  fde->initial_location = (ADDR)
1047  read_sbyte_unaligned_inc(wordsize,obo,readp);
1048  else
1049  fde->initial_location = (ADDR)
1050  read_ubyte_unaligned_inc(wordsize,obo,readp);
1051 
1052  if ((cie->fde_encoding & 0x70) == DW_EH_PE_pcrel)
1053  fde->initial_location += ddi->frame_sec_addr
1054  + (base - (unsigned char *)debugfile->frametab);
1055 
1056  fde->address_range = (ADDR)
1057  read_ubyte_unaligned_inc(wordsize,obo,readp);
1058 
1059  /*
1060  if ((cie->fde_encoding & 0x70) == DW_EH_PE_pcrel) {
1061  fde->vma_base = ((ddi->frame_sec_offset
1062  + (base - (const unsigned char *)debugfile->frametab)
1063  + (uint64_t)fde->initial_location)
1064  & (wordsize == 4
1065  ? UINT64_C(0xffffffff)
1066  : UINT64_C(0xffffffffffffffff)));
1067  }
1068  */
1069 
1071  "FDE 0x%lx length=%"PRIu64" cie=0x%lx id=%"PRIx64
1072  " initial_location=0x%"PRIxADDR" address_range=0x%"PRIxADDR,
1073  (unsigned long)offset,(uint64_t)unit_len,
1074  (unsigned long)cie->offset,(uint64_t)cie_id,
1075  fde->initial_location,fde->address_range);
1076  /*
1077  if (fde->vma_base) {
1078  vdebugc(8,LA_DEBUG,LF_DCFA,
1079  " (vma_base=0x%"PRIx64" vma_range=0x%"PRIx64"\n",
1080  (uint64_t)fde->vma_base,
1081  (uint64_t)(fde->vma_base + fde->address_range));
1082  }
1083  else {
1084  */
1085  vdebugc(8,LA_DEBUG,LF_DCFA,"\n");
1086  /*
1087  }
1088  */
1089 
1090  if (cie->aug[0] == 'z') {
1091  get_uleb128(auglen,readp);
1092 
1093  if (auglen > 0) {
1094  //const char *hdr = "Augmentation data:";
1095  const char *cp = cie->aug + 1;
1096  unsigned int u = 0;
1097  while (*cp != '\0') {
1098  if (*cp == 'L') {
1099  uint64_t lsda_pointer;
1100  const unsigned char *p =
1101  __read_encoded(cie->lsda_encoding,wordsize,
1102  &readp[u],&readp[auglen],
1103  &lsda_pointer,dbg);
1104  u = p - readp;
1105  //printf (gettext ("%-26sLSDA pointer: %#" PRIx64 "\n"),
1106  //hdr, lsda_pointer);
1107  //hdr = "";
1108  }
1109  ++cp;
1110  }
1111 
1112  while (u < auglen) {
1113  //printf (" %-26s%#x\n", hdr, readp[u]);
1114  //hdr = "";
1115  u++;
1116  }
1117  }
1118 
1119  readp += auglen;
1120  }
1121 
1122  fde->instructions = (unsigned char *)readp;
1123  fde->len = unit_end - readp;
1124 
1125  /*
1126  * NB: don't run the FDE programs until we need them.
1127  */
1128  /*/
1129  fde->regrules = g_hash_table_new(g_direct_hash,g_direct_equal);
1130 
1131  dwarf_cfa_program_interpret(debugfile,cie,fde,fde->instructions,
1132  fde->len,fde->regrules);
1133  */
1134 
1135  rc = clrangesimple_add(&ddi->cfa_fde,(Word_t)fde->initial_location,
1136  (Word_t)(fde->initial_location + fde->address_range),
1137  fde);
1138  if (rc == -1) {
1139  verror("error (?) addding FDE for 0x%"PRIxADDR",0x%"PRIxADDR";"
1140  " removing!\n",(ADDR)fde->initial_location,
1141  (ADDR)(fde->initial_location + fde->address_range));
1142  dwarf_cfa_fde_free(fde);
1143  fde = NULL;
1144  }
1145  else if (rc == 1) {
1147  "addr exists while adding FDE for 0x%"PRIxADDR","
1148  "0x%"PRIxADDR"; removing!\n",(ADDR)fde->initial_location,
1149  (ADDR)(fde->initial_location + fde->address_range));
1150  dwarf_cfa_fde_free(fde);
1151  fde = NULL;
1152  }
1153  }
1154 
1155  readp = unit_end;
1156  }
1157 
1158  return 0;
1159 }
1160 
1162  struct dwarf_cfa_fde *fde) {
1163  if (fde->regrules)
1164  return 0;
1165 
1166  fde->regrules = g_hash_table_new(g_direct_hash,g_direct_equal);
1167 
1168  if (dwarf_cfa_program_interpret(debugfile,fde->cie,fde,fde->instructions,
1169  fde->len,fde->regrules)) {
1170  verror("error while decoding FDE 0x%lx (CIE 0x%lx)!\n",
1171  (unsigned long)fde->offset,(unsigned long)fde->cie->offset);
1172  return -1;
1173  }
1174 
1175  return 0;
1176 }
1177 
1178 struct dwarf_cfa_regrule *
1180  struct dwarf_cfa_regrule *rr;
1181  clmatchone_t *cl;
1182 
1183  cl = g_hash_table_lookup(fde->regrules,(gpointer)(uintptr_t)reg);
1184  if (cl) {
1185  if ((rr = clmatchone_find(cl,obj_addr,NULL)))
1186  return rr;
1187  }
1188 
1189  rr = (struct dwarf_cfa_regrule *) \
1190  g_hash_table_lookup(fde->cie->default_regrules,(gpointer)(uintptr_t)reg);
1191  return rr;
1192 }
1193 
1194 static int dwarf_cfa_fde_run_regrule(struct debugfile *debugfile,
1195  struct dwarf_cfa_fde *fde,
1196  struct dwarf_cfa_regrule *rr,
1197  struct location_ctxt *lctxt,
1198  REG reg,REGVAL *o_regval) {
1199  REGVAL rv;
1200  ADDR addr;
1201  ADDR word;
1202  loctype_t ltrc;
1203  struct location loc;
1204  int rc;
1205  struct symbol *symbol;
1206  struct location_ops *lops;
1207  char *sname;
1208 
1209  if (!lctxt || !lctxt->ops) {
1210  verror("could not get location ops for current frame %d!\n",
1211  lctxt->current_frame);
1212  errno = EINVAL;
1213  return -1;
1214  }
1215  lops = lctxt->ops;
1216 
1217  if (!lops->getsymbol) {
1218  verror("no location_ops->getsymbol for current frame %d!\n",
1219  lctxt->current_frame);
1220  errno = EINVAL;
1221  return -1;
1222  }
1223  symbol = lops->getsymbol(lctxt);
1224  if (symbol)
1225  sname = symbol_get_name(symbol);
1226 
1227  switch (rr->rrt) {
1228  case RRT_UNDEF:
1229  return 1;
1230  case RRT_SAME:
1231  /*
1232  * Temporarily adjust lctxt->current_frame. This sucks a bit
1233  * cause we're not tail-recursive, but it's not a big deal.
1234  */
1235  if (!lops->setcurrentframe) {
1236  verror("no location_ops->setcurrentframe for current frame %d!\n",
1237  lctxt->current_frame);
1238  errno = EINVAL;
1239  return -1;
1240  }
1241  if (lops->setcurrentframe(lctxt,lctxt->current_frame - 1)) {
1242  verror("failed to setcurrentframe from %d to %d!\n",
1243  lctxt->current_frame,lctxt->current_frame - 1);
1244  errno = EINVAL;
1245  return -1;
1246  }
1247  rc = location_ctxt_read_reg(lctxt,reg,o_regval);
1248  if (lops->setcurrentframe(lctxt,lctxt->current_frame + 1)) {
1249  verror("failed to setcurrentframe from %d to %d!\n",
1250  lctxt->current_frame,lctxt->current_frame + 1);
1251  errno = EINVAL;
1252  return -1;
1253  }
1254  return rc;
1255  case RRT_OFFSET:
1256  /*
1257  * We actually enhance the DWARF offset(N) register rule to not
1258  * only load the CFA register -- but potentially any register.
1259  * This makes things easier. But we do then have to
1260  * special-case the CFA register, because it's a pseudo-reg we
1261  * have to compute.
1262  *
1263  * Get the current frame's offset.reg value, add the offset, and
1264  * load that address.
1265  */
1266  if (rr->offset.reg == DWARF_CFA_REG) {
1267  rc = dwarf_cfa_read_saved_reg(debugfile,lctxt,(REG)rr->offset.reg,&rv);
1268  if (rc) {
1269  verror("could not read CFA pseudo-reg %"PRIu64" value"
1270  " to read reg %"PRIiREG"!\n",rr->offset.reg,reg);
1271  return -1;
1272  }
1273  }
1274  else {
1275  rc = location_ctxt_read_reg(lctxt,rr->offset.reg,&rv);
1276  if (rc) {
1277  verror("could not read reg %"PRIu64" value"
1278  " to read reg %"PRIiREG"!\n",rr->offset.reg,reg);
1279  return -1;
1280  }
1281  }
1282  addr = rv + rr->offset.offset;
1283  if (lops->readword(lctxt,addr,&word)) {
1284  verror("could not read addr 0x%"PRIxADDR" to read reg %d"
1285  " in frame %d!\n",
1286  addr,reg,lctxt->current_frame);
1287  return -1;
1288  }
1289  if (o_regval)
1290  *o_regval = (REGVAL)word;
1291  return 0;
1292  case RRT_VAL_OFFSET:
1293  /*
1294  * Get the current frame's offset.reg value, add the offset, and
1295  * return it as the value. Same comment as for the RRT_OFFSET
1296  * case as far as enlarging the val_offset(N) operation to
1297  * handle any register, not just the CFA pseudo register.
1298  */
1299  rc = location_ctxt_read_reg(lctxt,rr->offset.reg,&rv);
1300  if (rc) {
1301  if (rr->offset.reg == DWARF_CFA_REG)
1302  verror("could not read CFA pseudo-reg %"PRIu64" value"
1303  " to read reg %"PRIiREG"!\n",rr->offset.reg,reg);
1304  else
1305  verror("could not read reg %"PRIu64" value"
1306  " to read reg %"PRIiREG"!\n",rr->offset.reg,reg);
1307  return -1;
1308  }
1309  rv += rr->offset.offset;
1310  if (o_regval)
1311  *o_regval = (REGVAL)rv;
1312  return 0;
1313  case RRT_REG:
1314  /*
1315  * Get rr->reg's value to return as the value of @reg.
1316  */
1317  rc = location_ctxt_read_reg(lctxt,rr->reg,&rv);
1318  if (rc) {
1319  verror("could not read reg %"PRIu64" value"
1320  " as the value for reg %"PRIiREG"!\n",rr->reg,reg);
1321  return -1;
1322  }
1323  if (o_regval)
1324  *o_regval = (REGVAL)rv;
1325  return 0;
1326  case RRT_EXPR:
1327  /*
1328  * Run the DWARF expr block; load the regval from the resulting
1329  * address.
1330  */
1331  memset(&loc,0,sizeof(loc));
1332  ltrc = dwarf_location_resolve(rr->block.block,rr->block.len,
1333  lctxt,symbol,&loc);
1334  if (ltrc != LOCTYPE_ADDR) {
1335  if ((int)ltrc < 0)
1336  verror("error evaluating DWARF expr for frame %d (symbol %s):"
1337  " %d!\n",
1338  lctxt->current_frame,sname,ltrc);
1339  else
1340  verror("error evaluating DWARF expr for frame %d (symbol %s):"
1341  " unexpected expr result %d!\n",
1342  lctxt->current_frame,sname,ltrc);
1343  return -1;
1344  }
1345  addr = LOCATION_ADDR(&loc);
1346  if (lops->readword(lctxt,addr,&word)) {
1347  verror("could not read addr 0x%"PRIxADDR" to read reg %d"
1348  " in frame %d!\n",
1349  addr,reg,lctxt->current_frame);
1350  return -1;
1351  }
1352  if (o_regval)
1353  *o_regval = (REGVAL)word;
1354  return 0;
1355  case RRT_VAL_EXPR:
1356  /*
1357  * Run the DWARF expr block; the result is the register's value.
1358  */
1359  memset(&loc,0,sizeof(loc));
1360  ltrc = dwarf_location_resolve(rr->block.block,rr->block.len,
1361  lctxt,symbol,&loc);
1362  if (ltrc != LOCTYPE_ADDR && ltrc != LOCTYPE_IMPLICIT_WORD) {
1363  if ((int)ltrc < 0)
1364  verror("error evaluating DWARF expr for frame %d (symbol %s):"
1365  " %d!\n",
1366  lctxt->current_frame,sname,ltrc);
1367  else
1368  verror("error evaluating DWARF expr for frame %d (symbol %s):"
1369  " unexpected expr result %d!\n",
1370  lctxt->current_frame,sname,ltrc);
1371  return -1;
1372  }
1373  else if (ltrc == LOCTYPE_ADDR)
1374  rv = LOCATION_ADDR(&loc);
1375  else if (ltrc == LOCTYPE_IMPLICIT_WORD)
1376  rv = LOCATION_WORD(&loc);
1377 
1378  if (o_regval)
1379  *o_regval = rv;
1380  return 0;
1381  default:
1382  verror("unknown DWARF CFA register rule %d; BUG!\n",rr->rrt);
1383  errno = EINVAL;
1384  return -1;
1385  }
1386 }
1387 
1388 /*
1389  * If the caller asks for this platform's stack pointer register value,
1390  * we instead compute CFA!
1391  */
1392 int dwarf_cfa_read_saved_reg(struct debugfile *debugfile,
1393  struct location_ctxt *lctxt,
1394  REG reg,REGVAL *o_regval) {
1395  struct dwarf_debugfile_info *ddi;
1396  struct dwarf_cfa_fde *fde;
1397  struct dwarf_cfa_cie *cie;
1398  struct symbol *symbol;
1399  REG ipreg;
1400  ADDR ip;
1401  struct dwarf_cfa_regrule *rr;
1402  ADDR retval;
1403  int rc;
1404  struct location_ops *lops;
1405  REG spreg = -1;
1406  int was_sp = 0;
1407  struct scope *scope;
1408  char *sname = NULL;
1409  ADDR saddr = 0;
1410 
1411  if (!lctxt || !lctxt->ops) {
1412  verror("no location ops for current frame %d!\n",lctxt->current_frame);
1413  errno = EINVAL;
1414  return -1;
1415  }
1416  lops = lctxt->ops;
1417 
1418  if (!debugfile->priv) {
1419  errno = EINVAL;
1420  return -1;
1421  }
1422 
1423  ddi = (struct dwarf_debugfile_info *)debugfile->priv;
1424  if (!ddi || !ddi->cfa_fde || !ddi->cfa_cie) {
1425  errno = EINVAL;
1426  return -1;
1427  }
1428 
1429  if (lops->getsymbol)
1430  symbol = lops->getsymbol(lctxt);
1431  else
1432  symbol = NULL;
1433  if (symbol) {
1434  saddr = symbol->addr;
1435  sname = symbol_get_name(symbol);
1436  }
1437 
1438  /*
1439  * NB: don't just search our parent if this is an inline instance;
1440  * there *might* be an FDE for it. We have the check below
1441  * (!fde && symbol) to catch this case.
1442  */
1443 #if 0
1444  if (symbol && symbol->isinlineinstance
1445  && symbol->scope->symbol && SYMBOL_IS_FUNC(symbol->scope->symbol)) {
1447  "using symbol %s instead of inline instance of %s for CFA\n",
1448  symbol_get_name(symbol->scope->symbol),sname);
1449  symbol = symbol->scope->symbol;
1450  }
1451  else if (symbol && symbol->isinlineinstance) {
1452  vwarn("inlined %s not in parent func; BUG?!\n",sname);
1453  }
1454 #endif
1455 
1456  if (!lops || !lops->getregno || lops->getregno(lctxt,CREG_SP,&spreg)) {
1457  vwarn("could not check CREG_SP for equivalence with DWARF CFA reg;"
1458  " things might break!\n");
1459  }
1460  else if (reg == spreg) {
1462  "reading CFA pseudo-reg to get SP value in current frame %d\n",
1463  lctxt->current_frame);
1464  reg = DWARF_CFA_REG;
1465  was_sp = 1;
1466  }
1467 
1468  /*
1469  * Figure out what IP is in the current frame, and unrelocate it so
1470  * we can use it.
1471  */
1472  if (!lops || !lops->getregno) {
1473  verror("could not get debuginfo IP reg number!\n");
1474  errno = EINVAL;
1475  return -1;
1476  }
1477  lops->getregno(lctxt,CREG_IP,&ipreg);
1478  if (lops->readreg(lctxt,ipreg,&ip)) {
1479  verror("could not read IP reg in frame %d!\n",lctxt->current_frame);
1480  return -1;
1481  }
1482  if (lops && lops->unrelocate && lops->unrelocate(lctxt,ip,&ip)) {
1483  verror("could not unrelocate real IP 0x%"PRIxADDR"!\n",ip);
1484  return -1;
1485  }
1486 
1487  /*
1488  * Just look it up based on the frame's IP address.
1489  */
1490  fde = NULL;
1491  rc = clrangesimple_find(&ddi->cfa_fde,(Word_t)ip,NULL,NULL,(void **)&fde);
1492  if (rc < 0) {
1493  verror("error looking up DWARF CFA FDE for IP 0x%"PRIxADDR","
1494  " symbol '%s' at addr 0x%"PRIxADDR"!\n",
1495  ip,sname,saddr);
1496  return -1;
1497  }
1498 
1499  if (!fde && symbol) {
1500  /*
1501  * Try to handle the case where the symbol is an inlined
1502  * instance. In this case, the FDE info might be at the address
1503  * of the inlined decl source. So keep looking up the scope
1504  * chain, trying to find an FDE that matches us.
1505  */
1506  scope = symbol->scope;
1507  while (scope) {
1508  if (!scope->range)
1509  continue;
1510 
1511  rc = clrangesimple_find(&ddi->cfa_fde,(Word_t)scope->range->start,
1512  NULL,NULL,(void **)&fde);
1513  if (fde) {
1514  if (scope->symbol) {
1516  "found DWARF CFA FDE at addr 0x%"PRIxADDR" symbol '%s'"
1517  " containing symbol '%s' addr 0x%"PRIxADDR";"
1518  " probably inlined\n",
1519  scope->range->start,symbol_get_name(scope->symbol),
1520  sname,saddr);
1521  }
1522  else {
1524  "found DWARF CFA FDE at scope addr 0x%"PRIxADDR
1525  " containing symbol '%s' addr 0x%"PRIxADDR";"
1526  " probably inlined\n",
1527  scope->range->start,sname,saddr);
1528  }
1529  break;
1530  }
1531 
1532  scope = scope->parent;
1533  }
1534  }
1535 
1536  if (!fde) {
1537  verror("no DWARF CFA FDE for IP 0x%"PRIxADDR","
1538  " symbol '%s' at addr 0x%"PRIxADDR"!\n",
1539  ip,sname,saddr);
1540  errno = ESRCH;
1541  return -1;
1542  }
1543 
1544  cie = fde->cie;
1545 
1546  /*
1547  * If the FDE hasn't been decoded, decode it now.
1548  */
1549  if (dwarf_cfa_fde_decode(debugfile,fde)) {
1550  verror("error while decoding DWARF CFA FDE for symbol '%s'"
1551  " at addr 0x%"PRIxADDR"!\n",
1552  sname,saddr);
1553  errno = EFAULT;
1554  return -1;
1555  }
1556 
1557  /*
1558  * If it doesn't have a regrule for the retaddr register number,
1559  * bail successfully.
1560  */
1561  rr = dwarf_cfa_fde_lookup_regrule(fde,reg,ip);
1562  if (!rr) {
1564  "could not find DWARF CFA regrule for reg %d at"
1565  " obj addr 0x%"PRIxADDR"\n",
1566  reg,ip);
1567  errno = EADDRNOTAVAIL;
1568  return -1;
1569  }
1570 
1571  /*
1572  * Otherwise, execute the regrule!
1573  */
1574  rc = dwarf_cfa_fde_run_regrule(debugfile,fde,rr,lctxt,reg,&retval);
1575  if (rc) {
1576  verror("could not load register %d in FDE 0x%lx CIE 0x%lx!\n",
1577  reg,(unsigned long)fde->offset,(unsigned long)cie->offset);
1578  errno = EFAULT;
1579  return -1;
1580  }
1581 
1582  if (reg == DWARF_CFA_REG) {
1584  "read CFA pseudo-reg value 0x%"PRIxADDR" in current frame %d\n",
1585  retval,lctxt->current_frame);
1586  }
1587 
1588  if (was_sp) {
1590  "read CFA pseudo-reg to get SP value in current frame %d;"
1591  " SP is 0x%"PRIxADDR"\n",
1592  lctxt->current_frame,retval);
1593  }
1594 
1595  if (o_regval)
1596  *o_regval = retval;
1597  return 0;
1598 }
1599 
1600 /*
1601  * Read the return address value from the current frame.
1602  *
1603  * We have to find the CFA decoding for the current frame's symbol; find
1604  * its return address register number; if it doesn't have one, return 0
1605  * AND set o_retaddr to NULL; if it has one, then read the current
1606  * frame's IP and find the rule for the return address number for that
1607  * IP. Then execute the rule and save the value in o_retaddr.
1608  */
1609 int dwarf_cfa_read_retaddr(struct debugfile *debugfile,
1610  struct location_ctxt *lctxt,ADDR *o_retaddr) {
1611  struct dwarf_debugfile_info *ddi;
1612  struct dwarf_cfa_fde *fde;
1613  struct dwarf_cfa_cie *cie;
1614  struct symbol *symbol;
1615  REG ipreg;
1616  ADDR ip;
1617  struct dwarf_cfa_regrule *rr;
1618  ADDR retval;
1619  int rc;
1620  struct location_ops *lops;
1621  struct scope *scope;
1622  char *sname;
1623  ADDR saddr;
1624 
1625  if (!lctxt || !lctxt->ops) {
1626  verror("no location_ops for current frame %d!\n",lctxt->current_frame);
1627  errno = EINVAL;
1628  return -1;
1629  }
1630  lops = lctxt->ops;
1631 
1632  if (!debugfile->priv) {
1633  errno = EINVAL;
1634  return -1;
1635  }
1636  ddi = (struct dwarf_debugfile_info *)debugfile->priv;
1637  if (!ddi->cfa_fde || !ddi->cfa_cie) {
1638  errno = EINVAL;
1639  return -1;
1640  }
1641 
1642  if (lops->getsymbol)
1643  symbol = lops->getsymbol(lctxt);
1644  else
1645  symbol = NULL;
1646  if (!symbol) {
1647  vwarnopt(9,LA_DEBUG,LF_DCFA,"failed to getsymbol for current frame %d!\n",
1648  lctxt->current_frame);
1649  }
1650  else {
1651  sname = symbol_get_name(symbol);
1652  saddr = symbol->addr;
1653  }
1654 
1655  /*
1656  * This strategy does not work for handling inlines; see below for
1657  * the one that does.
1658  */
1659  /*
1660  if (symbol->isinlineinstance
1661  && symbol->scope->symbol && SYMBOL_IS_FUNC(symbol->scope->symbol)) {
1662  vdebug(5,LA_DEBUG,LF_DCFA,
1663  "using symbol %s instead of inline instance of %s for CFA\n",
1664  symbol_get_name(symbol->scope->symbol),symbol_get_name(symbol));
1665  symbol = symbol->scope->symbol;
1666  }
1667  else if (symbol->isinlineinstance) {
1668  vwarn("inlined %s not in parent func; BUG?!\n",symbol_get_name(symbol));
1669  }
1670  */
1671 
1672  /*
1673  * Figure out what IP is in the current frame, and unrelocate it so
1674  * we can use it.
1675  */
1676  if (!lops->getregno) {
1677  verror("could not get debuginfo IP reg number!\n");
1678  errno = EINVAL;
1679  return -1;
1680  }
1681  lops->getregno(lctxt,CREG_IP,&ipreg);
1682  if (location_ctxt_read_reg(lctxt,ipreg,&ip)) {
1683  verror("IP register value not in current frame %d; BUG!\n",
1684  lctxt->current_frame);
1685  errno = EINVAL;
1686  return -1;
1687  }
1688  if (lops->unrelocate && lops->unrelocate(lctxt,ip,&ip)) {
1689  verror("could not unrelocate real IP 0x%"PRIxADDR"!\n",ip);
1690  return -1;
1691  }
1692 
1693  /*
1694  * Just look it up based on the frame's IP address.
1695  */
1696  fde = NULL;
1697  rc = clrangesimple_find(&ddi->cfa_fde,(Word_t)ip,NULL,NULL,(void **)&fde);
1698  if (rc < 0) {
1699  if (symbol)
1700  verror("error looking up DWARF CFA FDE for IP 0x%"PRIxADDR","
1701  " symbol '%s' at addr 0x%"PRIxADDR"!\n",
1702  ip,sname,saddr);
1703  else
1704  verror("error looking up DWARF CFA FDE for IP 0x%"PRIxADDR"!\n",ip);
1705  return -1;
1706  }
1707 
1708  if (!fde) {
1709  /*
1710  * Try to handle the case where the symbol is an inlined
1711  * instance. In this case, the FDE info might be at the address
1712  * of the inlined decl source. So keep looking up the scope
1713  * chain, trying to find an FDE that matches us.
1714  */
1715  scope = symbol->scope;
1716  while (scope) {
1717  if (!scope->range)
1718  continue;
1719 
1720  rc = clrangesimple_find(&ddi->cfa_fde,(Word_t)scope->range->start,
1721  NULL,NULL,(void **)&fde);
1722  if (fde) {
1723  if (scope->symbol) {
1725  "found DWARF CFA FDE at addr 0x%"PRIxADDR" symbol '%s'"
1726  " containing symbol '%s' addr 0x%"PRIxADDR";"
1727  " probably inlined\n",
1728  scope->range->start,symbol_get_name(scope->symbol),
1729  sname,saddr);
1730  }
1731  else {
1733  "found DWARF CFA FDE at scope addr 0x%"PRIxADDR
1734  " containing symbol '%s' addr 0x%"PRIxADDR";"
1735  " probably inlined\n",
1736  scope->range->start,sname,saddr);
1737  }
1738  break;
1739  }
1740 
1741  scope = scope->parent;
1742  }
1743  }
1744 
1745  if (!fde) {
1746  verror("no DWARF CFA FDE for IP 0x%"PRIxADDR","
1747  " symbol '%s' at addr 0x%"PRIxADDR"!\n",
1748  ip,sname,saddr);
1749  errno = ESRCH;
1750  return -1;
1751  }
1752 
1753  cie = fde->cie;
1754 
1755  /*
1756  * If the FDE hasn't been decoded, decode it now.
1757  */
1758  if (dwarf_cfa_fde_decode(debugfile,fde)) {
1759  verror("error while decoding DWARF CFA FDE for symbol '%s'"
1760  " at addr 0x%"PRIxADDR"!\n",
1761  sname,saddr);
1762  return -1;
1763  }
1764 
1765  /*
1766  * If it doesn't have a regrule for the retaddr register number,
1767  * bail successfully.
1768  */
1770  if (!rr) {
1771  verror("could not find DWARF CFA regrule for retaddr reg %d at"
1772  " obj addr 0x%"PRIxADDR"\n",
1773  cie->return_address_register,ip);
1774  return -1;
1775  }
1776 
1777  /*
1778  * Otherwise, execute the regrule!
1779  */
1780  rc = dwarf_cfa_fde_run_regrule(debugfile,fde,rr,lctxt,
1781  cie->return_address_register,&retval);
1782  if (rc) {
1783  verror("could not load return address register %d"
1784  " in FDE 0x%lx CIE 0x%lx!\n",
1785  cie->return_address_register,(unsigned long)fde->offset,
1786  (unsigned long)cie->offset);
1787  return -1;
1788  }
1789 
1790  if (o_retaddr)
1791  *o_retaddr = retval;
1792  return 0;
1793 }
1794 
1795 static void __dwarf_cfa_dtor(Word_t start,Word_t end,void *data,void *dtor_data) {
1796  struct dwarf_cfa_fde *fde;
1797 
1798  fde = (struct dwarf_cfa_fde *)data;
1799  dwarf_cfa_fde_free(fde);
1800 }
1801 
1802 int dwarf_unload_cfa(struct debugfile *debugfile) {
1803  struct dwarf_debugfile_info *ddi;
1804  GHashTableIter iter;
1805  gpointer kp, vp;
1806  struct dwarf_cfa_cie *cie;
1807 
1808  if (!debugfile->priv)
1809  return 0;
1810 
1811  ddi = (struct dwarf_debugfile_info *)debugfile->priv;
1812 
1813  if (ddi->cfa_fde) {
1814  clrangesimple_free(ddi->cfa_fde,__dwarf_cfa_dtor,NULL);
1815  ddi->cfa_fde = NULL;
1816  }
1817 
1818  if (ddi->cfa_cie) {
1819  g_hash_table_iter_init(&iter,ddi->cfa_cie);
1820  while (g_hash_table_iter_next(&iter,&kp,&vp)) {
1821  cie = (struct dwarf_cfa_cie *)vp;
1822  dwarf_cfa_cie_free(cie);
1823  g_hash_table_iter_replace(&iter,NULL);
1824  }
1825  g_hash_table_destroy(ddi->cfa_cie);
1826  ddi->cfa_cie = NULL;
1827  }
1828 
1829  return 0;
1830 }
1831 
1832 /*
1833  * Taken from elfutils/src/readelf.c and slightly modified.
1834  */
1835 static const unsigned char *__read_encoded(unsigned int encoding,
1836  unsigned int wordsize,
1837  const unsigned char *readp,
1838  const unsigned char *const endp,
1839  uint64_t *res,Dwarf *dbg) {
1840  /* XXX: we can't get other_byte_order from dbg since we don't have
1841  * the struct def for it... so we assume it's not a diff byte order
1842  * than the phys host for now.
1843  */
1844  int obo = 0;
1845 
1846  if ((encoding & 0xf) == DW_EH_PE_absptr)
1847  encoding = (wordsize == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
1848 
1849  switch (encoding & 0xf) {
1850  case DW_EH_PE_uleb128:
1851  // XXX buffer overrun check
1852  get_uleb128(*res,readp);
1853  break;
1854  case DW_EH_PE_sleb128:
1855  // XXX buffer overrun check
1856  get_sleb128(*res,readp);
1857  break;
1858  case DW_EH_PE_udata2:
1859  if (readp + 2 > endp)
1860  goto invalid;
1861  *res = read_2ubyte_unaligned_inc(obo,readp);
1862  break;
1863  case DW_EH_PE_udata4:
1864  if (readp + 4 > endp)
1865  goto invalid;
1866  *res = read_4ubyte_unaligned_inc(obo,readp);
1867  break;
1868  case DW_EH_PE_udata8:
1869  if (readp + 8 > endp)
1870  goto invalid;
1871  *res = read_8ubyte_unaligned_inc(obo,readp);
1872  break;
1873  case DW_EH_PE_sdata2:
1874  if (readp + 2 > endp)
1875  goto invalid;
1876  *res = read_2sbyte_unaligned_inc(obo,readp);
1877  break;
1878  case DW_EH_PE_sdata4:
1879  if (readp + 4 > endp)
1880  goto invalid;
1881  *res = read_4sbyte_unaligned_inc(obo,readp);
1882  break;
1883  case DW_EH_PE_sdata8:
1884  if (readp + 8 > endp)
1885  goto invalid;
1886  *res = read_8sbyte_unaligned_inc(obo,readp);
1887  break;
1888  default:
1889  invalid:
1890  verror("invalid encoding '%*s' at %p!\n",
1891  (int)(uintptr_t)(endp - readp),readp,readp);
1892  }
1893 
1894  return readp;
1895 }
#define LOCATION_ADDR(loc)
Definition: dwdebug_priv.h:622
unsigned int code_alignment_factor
Definition: dwarf_cfa.c:98
Definition: log.h:133
#define vwarnopt(level, area, flags, format,...)
Definition: log.h:37
int64_t offset
Definition: dwarf_cfa.c:72
void clrangesimple_free(clrangesimple_t clr, clrangesimple_free_dtor dtor, void *dtor_data)
Definition: clfit.c:804
GHashTable * cfa_cie
Definition: dwdebug_priv.h:280
#define unlikely(expr)
Definition: debugpred.h:101
clrangesimple_t clrangesimple_create(void)
Definition: clfit.c:648
GHashTable * default_regrules
Definition: dwarf_cfa.c:107
void * clmatchone_find(clmatchone_t *clf, Word_t index, Word_t *o_index)
Definition: clfit.c:977
struct location_ops * ops
Definition: dwdebug_priv.h:744
unsigned int fde_encoding
Definition: dwarf_cfa.c:101
ADDR initial_location
Definition: dwarf_cfa.c:113
ptrdiff_t offset
Definition: dwarf_cfa.c:111
void * p
#define PRIiREG
Definition: common.h:94
Definition: arch.h:74
ADDR addr
Definition: dwdebug_priv.h:916
struct dwarf_cfa_cie * cie
Definition: dwarf_cfa.c:112
#define read_2sbyte_unaligned_inc(obo, Addr)
#define likely(expr)
Definition: debugpred.h:102
#define read_ubyte_unaligned_inc(Nbytes, obo, Addr)
ADDR start
Definition: dwdebug_priv.h:437
#define get_uleb128(var, addr)
Definition: memory-access.h:67
int clmatchone_add(clmatchone_t *clf, Word_t index, void *data)
Definition: clfit.c:934
#define DWARF_CFA_REG
Definition: dwarf_cfa.c:86
#define verror(format,...)
Definition: log.h:30
int location_ctxt_read_reg(struct location_ctxt *lctxt, REG reg, REGVAL *o_regval)
Definition: location.c:632
int dwarf_unload_cfa(struct debugfile *debugfile)
Definition: dwarf_cfa.c:1802
#define vwarn(format,...)
Definition: log.h:33
#define LOCATION_WORD(loc)
Definition: dwdebug_priv.h:626
#define ADDRMAX
Definition: common.h:74
void free(void *ptr)
Definition: debugserver.c:207
unsigned int auglen
Definition: dwarf_cfa.c:105
int dwarf_cfa_read_retaddr(struct debugfile *debugfile, struct location_ctxt *lctxt, ADDR *o_retaddr)
Definition: dwarf_cfa.c:1609
dwarf_cfa_regrule_t rrt
Definition: dwarf_cfa.c:63
struct range * range
Definition: dwdebug_priv.h:471
GHashTable * regrules
Definition: dwarf_cfa.c:120
Definition: log.h:69
struct arch * arch
Definition: binfile.h:216
void clmatchone_free(clmatchone_t clf)
Definition: clfit.c:994
ptrdiff_t offset
Definition: dwarf_cfa.c:95
struct symbol *(* getsymbol)(struct location_ctxt *lctxt)
Definition: dwdebug_priv.h:681
uint64_t reg
Definition: dwarf_cfa.c:65
uint64_t personality
Definition: dwarf_cfa.c:103
unsigned char * instructions
Definition: dwarf_cfa.c:116
int data_alignment_factor
Definition: dwarf_cfa.c:99
#define read_4sbyte_unaligned_inc(obo, Addr)
ADDR address_range
Definition: dwarf_cfa.c:114
clrangesimple_t cfa_fde
Definition: dwdebug_priv.h:281
unsigned int return_address_register
Definition: dwarf_cfa.c:100
#define read_8ubyte_unaligned_inc(obo, Addr)
uint8_t segment_size
Definition: dwarf_cfa.c:97
char * aug
Definition: dwarf_cfa.c:104
int len
Definition: dumptarget.c:52
int(* readreg)(struct location_ctxt *lctxt, REG regno, REGVAL *regval)
Definition: dwdebug_priv.h:687
#define vdebug(devel, areas, flags, format,...)
Definition: log.h:302
struct scope * parent
Definition: dwdebug_priv.h:476
int dwarf_load_cfa(struct debugfile *debugfile, unsigned char *buf, unsigned int len, Dwarf *dbg)
Definition: dwarf_cfa.c:784
loctype_t dwarf_location_resolve(const unsigned char *data, unsigned int len, struct location_ctxt *lctxt, struct symbol *symbol, struct location *o_loc)
Definition: dwarf_expr.c:213
int(* setcurrentframe)(struct location_ctxt *lctxt, int frame)
Definition: dwdebug_priv.h:673
struct dwarf_cfa_regrule * dwarf_cfa_fde_lookup_regrule(struct dwarf_cfa_fde *fde, REG reg, ADDR obj_addr)
Definition: dwarf_cfa.c:1179
int dwarf_cfa_read_saved_reg(struct debugfile *debugfile, struct location_ctxt *lctxt, REG reg, REGVAL *o_regval)
Definition: dwarf_cfa.c:1392
#define vdebugc(devel, areas, flags, format,...)
Definition: log.h:303
unsigned int wordsize
Definition: arch.h:121
void * calloc(size_t nmemb, size_t size)
Definition: debugserver.c:200
const unsigned char * block
Definition: dwarf_cfa.c:67
struct binfile * binfile
Definition: dwdebug.h:808
char * frametab
Definition: dwdebug.h:865
int dwarf_cfa_program_interpret(struct debugfile *debugfile, struct dwarf_cfa_cie *cie, struct dwarf_cfa_fde *fde, const unsigned char *buf, unsigned int len, GHashTable *regrules)
Definition: dwarf_cfa.c:167
int(* unrelocate)(struct location_ctxt *lctxt, ADDR real_addr, ADDR *obj_addr)
Definition: dwdebug_priv.h:705
uint32_t REGVAL
Definition: common.h:66
unsigned int len
Definition: dwarf_cfa.c:117
#define get_sleb128(var, addr)
Definition: memory-access.h:98
#define read_4ubyte_unaligned_inc(obo, Addr)
int8_t REG
Definition: common.h:93
int dwarf_cfa_fde_decode(struct debugfile *debugfile, struct dwarf_cfa_fde *fde)
Definition: dwarf_cfa.c:1161
struct scope * scope
Definition: dwdebug_priv.h:806
uint32_t ADDR
Definition: common.h:64
void * priv
Definition: dwdebug.h:800
int clrangesimple_add(clrangesimple_t *clr, Word_t start, Word_t end, void *data)
Definition: clfit.c:652
clmatchone_t clmatchone_create(void)
Definition: clfit.c:924
#define read_2ubyte_unaligned_inc(obo, Addr)
#define PRIxADDR
Definition: common.h:67
int(* getregno)(struct location_ctxt *lctxt, common_reg_t reg, REG *o_reg)
Definition: dwdebug_priv.h:709
unsigned int len
Definition: dwarf_cfa.c:68
uint8_t version
Definition: dwarf_cfa.c:96
#define read_8sbyte_unaligned_inc(obo, Addr)
unsigned int lsda_encoding
Definition: dwarf_cfa.c:102
char * symbol_get_name(struct symbol *symbol)
Definition: debug.c:2587
dwarf_cfa_regrule_t
Definition: dwarf_cfa.c:51
int clrangesimple_find(clrangesimple_t *clr, Word_t index, Word_t *start, Word_t *end, void **data)
Definition: clfit.c:713
unsigned int isinlineinstance
Definition: dwdebug_priv.h:839
#define read_sbyte_unaligned_inc(Nbytes, obo, Addr)
Pvoid_t clmatchone_t
Definition: clfit.h:136
#define SYMBOL_IS_FUNC(sym)
int(* readword)(struct location_ctxt *lctxt, ADDR real_addr, ADDR *pval)
Definition: dwdebug_priv.h:702
loctype_t
Definition: dwdebug.h:234
Definition: arch.h:76
struct symbol * symbol
Definition: dwdebug_priv.h:463