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
location.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, 2012, 2013, 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 <errno.h>
21 
22 #include "dwdebug.h"
23 #include "dwdebug_priv.h"
24 
25 static void loclistloc_free(struct loclistloc *loclist) {
26  struct loclistloc *last = NULL;
27 
28  while (loclist) {
29  location_free(loclist->loc);
30  last = loclist;
31  loclist = loclist->next;
32  free(last);
33  }
34 }
35 
39 struct location *location_create(void) {
40  struct location *location = \
41  (struct location *)calloc(1,sizeof(*location));
42  location->loctype = LOCTYPE_UNKNOWN;
43  return location;
44 }
45 
48  l->loctype = LOCTYPE_ADDR;
49  l->l.addr = addr;
50  return 0;
51  }
52  return -1;
53 }
54 
56  if (LOCATION_IS_UNKNOWN(l) || LOCATION_IS_REG(l)) {
57  l->loctype = LOCTYPE_REG;
58  l->l.reg = reg;
59  return 0;
60  }
61  return -1;
62 }
63 
67  l->l.reg = reg;
68  return 0;
69  }
70  return -1;
71 }
72 
76 #if 0
77  if (reg > ((1 << LOCATION_REMAINING_BITS) - 1)) {
78  verror("regoffset reg %d too big!\n",reg);
79  return -1;
80  }
81 #endif
82  l->extra = reg;
83  l->l.offset = offset;
84  return 0;
85  }
86  return -1;
87 }
88 
92  l->l.offset = offset;
93  return 0;
94  }
95  return -1;
96 }
97 
101  l->l.offset = offset;
102  return 0;
103  }
104  return -1;
105 }
106 
107 int location_set_loclist(struct location *l,struct loclistloc *list) {
110  if (l->l.loclist && !l->nofree)
111  loclistloc_free(l->l.loclist);
112  l->nofree = 0;
113  l->l.loclist = list;
114  return 0;
115  }
116  return -1;
117 }
118 
122  loc->l.word = word;
123  return 0;
124  }
125  return -1;
126 }
127 
128 int location_set_implicit_data(struct location *loc,char *data,int len,
129  int nocopy) {
130  if (LOCATION_IS_UNKNOWN(loc) || LOCATION_IS_RUNTIME(loc)) {
131  if (len < 0)
132  return -1;
133 #if __WORDSIZE == 4
134  if (data && len > 0 && len > ((1 << LOCATION_REMAINING_BITS) - 1)) {
135  verror("implicit data len %d too big!\n",len);
136  return -1;
137  }
138 #endif
140 
141  if (loc->l.data)
142  free(loc->l.data);
143  if (data) {
144  if (!nocopy) {
145  loc->nofree = 0;
146  loc->l.data = malloc(len);
147  memcpy(loc->l.data,data,len);
148  }
149  else {
150  loc->nofree = 1;
151  loc->l.data = data;
152  }
153  loc->extra = len;
154  }
155  else {
156  loc->l.data = NULL;
157  loc->extra = 0;
158  }
159  return 0;
160  }
161  return -1;
162 }
163 
164 int location_set_runtime(struct location *l,char *data,int len,int nocopy) {
166  if (len < 0)
167  return -1;
168 #if __WORDSIZE == 4
169  if (data && len > 0 && len > ((1 << LOCATION_REMAINING_BITS) - 1)) {
170  verror("runtime data len %d too big!\n",len);
171  return -1;
172  }
173 #endif
175 
176  if (l->l.data)
177  free(l->l.data);
178  if (data) {
179  if (!nocopy) {
180  l->nofree = 0;
181  l->l.data = malloc(len);
182  memcpy(l->l.data,data,len);
183  }
184  else {
185  l->nofree = 1;
186  l->l.data = data;
187  }
188  l->extra = len;
189  }
190  else {
191  l->l.data = NULL;
192  l->extra = 0;
193  }
194  return 0;
195  }
196  return -1;
197 }
198 
200  ADDR start,ADDR end,struct location *rloc,
201  int *action) {
202  struct loclistloc *l, *lastl, *newl;
203 
204  if (!(LOCATION_IS_UNKNOWN(loc) || LOCATION_IS_LOCLIST(loc))) {
205  verror("location is not a loclist!\n");
206  return -1;
207  }
208 
209  loc->loctype = LOCTYPE_LOCLIST;
210 
211  /*
212  * We maintain location->loclist as a sorted list by start.
213  *
214  * So we look for any items that have @start, and update end if
215  * necessary; else we insert a new loclistloc at the right place.
216  */
217  if (!loc->l.loclist) {
218  loc->l.loclist = (struct loclistloc *)calloc(1,sizeof(*loc->l.loclist));
219  loc->l.loclist->start = start;
220  loc->l.loclist->end = end;
221  loc->l.loclist->loc = rloc;
222  loc->l.loclist->next = NULL;
223 
224  if (action)
225  *action = 1;
226 
228  "init loclist(0x%"PRIxADDR",0x%"PRIxADDR")\n",
229  start,end);
230 
231  return 0;
232  }
233  else {
234  lastl = NULL;
235  l = loc->l.loclist;
236  while (l) {
237  if (l->start == start) {
238  if (l->end != end) {
239  vwarn("inconsistent loclist range(0x%"PRIxADDR",0x%"PRIxADDR")"
240  " (new end 0x%"PRIxADDR"); updating!\n",
241  l->start,l->end,end);
242 
243  l->end = end;
244 
245  if (action)
246  *action = 2;
247 
248  return 0;
249  }
250  else {
252  "loclist range(0x%"PRIxADDR",0x%"PRIxADDR") matched;"
253  " not updating; freeing \"new\" location!\n",
254  start,end);
255 
256  location_free(rloc);
257 
258  if (action)
259  *action = 0;
260 
261  return 0;
262  }
263  }
264  else if (l->start > start) {
265  /* Insert a new one between lastl and l */
266  newl = (struct loclistloc *)calloc(1,sizeof(*newl));
267  newl->start = start;
268  newl->end = end;
269  newl->loc = rloc;
270  newl->next = l;
271  if (lastl)
272  lastl->next = newl;
273  else
274  loc->l.loclist = newl;
275 
276  if (action)
277  *action = 1;
278 
280  "added loclist range (0x%"PRIxADDR",0x%"PRIxADDR")\n",
281  start,end);
282 
283  return 0;
284  }
285  else {
286  lastl = l;
287  l = l->next;
288  }
289  }
290 
291  /* If we get here, we need to add one at the tail. */
292  newl = (struct loclistloc *)calloc(1,sizeof(*newl));
293  newl->start = start;
294  newl->end = end;
295  newl->loc = rloc;
296  newl->next = NULL;
297  lastl->next = newl;
298 
299  if (action)
300  *action = 1;
301 
303  "added loclist range (0x%"PRIxADDR",0x%"PRIxADDR")\n",
304  start,end);
305 
306  return 0;
307  }
308 }
309 
310 /*
311  * All copies are full and deep.
312  */
314  struct location *retval;
315  struct loclistloc *old, *new, *lastnew = NULL;
316 
317  retval = location_create();
318  retval->loctype = location->loctype;
319  retval->extra = location->extra;
320 
321  if (LOCATION_IS_RUNTIME(location)) {
322  retval->l.data = malloc(location->extra);
323  memcpy(&retval->l.data,&location->l.data,location->extra);
324  }
325  else if (LOCATION_IS_LOCLIST(location)) {
326  old = location->l.loclist;
327  while (old) {
328  new = calloc(1,sizeof(*new));
329  new->start = old->start;
330  new->end = old->end;
331  new->loc = location_copy(old->loc);
332  if (lastnew)
333  lastnew = new;
334  else
335  retval->l.loclist = new;
336 
337  lastnew = new;
338  old = old->next;
339  }
340  }
341  else
342  memcpy(&retval->l,&location->l,sizeof(location->l));
343 
344  return retval;
345 }
346 
348  if (location->loctype == LOCTYPE_RUNTIME
349  || location->loctype == LOCTYPE_IMPLICIT_DATA) {
350  if (location->l.data && !location->nofree)
351  free(location->l.data);
352  }
353  else if (location->loctype == LOCTYPE_LOCLIST) {
354  if (location->l.loclist)
355  loclistloc_free(location->l.loclist);
356  }
357 }
358 
360  location_internal_free(location);
361  free(location);
362 }
363 
364 void loclistloc_dump(struct loclistloc *list,struct dump_info *ud) {
365  int i;
366  struct dump_info udn = {
367  .stream = ud->stream,
368  .prefix = "",
369  .detail = ud->detail,
370  .meta = ud->meta,
371  };
372 
373  fprintf(ud->stream,"%sLIST(",ud->prefix);
374  i = 0;
375  while (list) {
376  if (i > 0)
377  fprintf(ud->stream,",");
378  fprintf(ud->stream,"[0x%" PRIxADDR ",0x%" PRIxADDR,
379  list->start,list->end);
380  if (list->loc) {
381  fprintf(ud->stream,"->");
382  location_dump(list->loc,&udn);
383  }
384  fprintf(ud->stream,"]");
385 
386  ++i;
387  list = list->next;
388  }
389  fprintf(ud->stream,")");
390 }
391 
392 void location_dump(struct location *location,struct dump_info *ud) {
393  int i;
394  struct dump_info udn = {
395  .stream = ud->stream,
396  .prefix = "",
397  .detail = ud->detail,
398  .meta = ud->meta,
399  };
400 
401  switch(location->loctype) {
402  case LOCTYPE_ADDR:
403  fprintf(ud->stream,"0x%" PRIxADDR,location->l.addr);
404  break;
405  case LOCTYPE_REG:
406  fprintf(ud->stream,"R%d",location->l.reg);
407  break;
408  case LOCTYPE_REG_ADDR:
409  fprintf(ud->stream,"*R%d",location->l.reg);
410  break;
411  case LOCTYPE_REG_OFFSET:
412  fprintf(ud->stream,"R%hhd%+"PRIiOFFSET,
413  (REG)location->extra,location->l.offset);
414  break;
416  fprintf(ud->stream,"FB%+"PRIiOFFSET,location->l.offset);
417  break;
419  fprintf(ud->stream,"%+"PRIiOFFSET,
420  location->l.offset);
421  break;
423  fprintf(ud->stream,"IMPLICITWORD(0x%"PRIxADDR")",location->l.word);
424  break;
426  fprintf(ud->stream,"IMPLICITDATA(%d,",(int)location->extra);
427  for (i = 0; i < (int)location->extra; ++i)
428  fprintf(ud->stream,"%hhx",location->l.data[i]);
429  fprintf(ud->stream,")");
430  break;
431  case LOCTYPE_RUNTIME:
432  fprintf(ud->stream,"RUNTIMEDATA(%d,",(int)location->extra);
433  for (i = 0; i < (int)location->extra; ++i)
434  fprintf(ud->stream,"%hhx",location->l.data[i]);
435  fprintf(ud->stream,")");
436  break;
437  case LOCTYPE_LOCLIST:
438  loclistloc_dump(location->l.loclist,&udn);
439  break;
440  case LOCTYPE_UNKNOWN:
441  default:
442  break;
443  }
444 }
445 
446 
447 
448 
449 
450 
451 #if 0
452 OFFSET location_resolve_offset(struct location *location,
453  struct array_list *symbol_chain,
454  struct symbol **top_symbol_saveptr,
455  int *chain_top_symbol_idx_saveptr) {
456  int chlen;
457  int i;
458  OFFSET totaloffset;
459  struct symbol *symbol;
460  struct symbol *tdatatype;
461 
462  if (!LOCATION_IS_M_OFFSET(location)) {
463  verror("location type %s is not a member offset!",
464  LOCTYPE(location->loctype));
465  errno = EINVAL;
466  return 0;
467  }
468 
469  /*
470  * XXX: the assumption is that our @location arg is the same
471  * location as in the last symbol in @symbol_chain!
472  */
473  if (!symbol_chain) {
474  verror("cannot resolve MEMBER_OFFSET without containing symbol_chain!\n");
475  errno = EINVAL;
476  return 0;
477  }
478 
479  chlen = array_list_len(symbol_chain);
480  symbol = array_list_item(symbol_chain,chlen - 1);
481 
482  if (!SYMBOL_IS_FULL_VAR(symbol) || !symbol->ismember) {
483  verror("deepest symbol (%s) in chain is not member; cannot resolve"
484  " MEMBER_OFFSET location!\n",symbol_get_name(symbol));
485  errno = EINVAL;
486  return 0;
487  }
488 
489  /*
490  * Calculate the total offset, i.e. for nested S/Us.
491  */
492  totaloffset = 0;
493  for (i = chlen - 1; i > -1; --i) {
494  symbol = array_list_item(symbol_chain,i);
495  tdatatype = symbol_get_datatype(symbol);
496  if (i < (chlen - 1)
497  && SYMBOL_IS_VAR(symbol)
498  && tdatatype
499  && SYMBOL_IST_STUN(tdatatype)) {
500  /* In this case, when symbol is a var with a type like
501  * const|vol *+ [typedef+] struct, we still allow this var
502  * to be our top enclosing symbol, because we're going to
503  * use the pointer in combination with the offset.
504  */
505  if (top_symbol_saveptr)
506  *top_symbol_saveptr = symbol;
507  if (chain_top_symbol_idx_saveptr)
508  *chain_top_symbol_idx_saveptr = i;
509  break;
510  }
511  else if (SYMBOL_IS_FULL_VAR(symbol)
512  && symbol_is_member(symbol)
513  && SYMBOLX_VAR_LOC(symbol)
515  totaloffset += LOCATION_OFFSET(SYMBOLX_VAR_LOC(symbol));
516  continue;
517  }
518  else if (SYMBOL_IS_VAR(symbol)
519  && SYMBOL_IST_STUN(tdatatype)) {
520  if (top_symbol_saveptr)
521  *top_symbol_saveptr = symbol;
522  if (chain_top_symbol_idx_saveptr)
523  *chain_top_symbol_idx_saveptr = i;
524  break;
525  }
526  else if (SYMBOL_IST_STUN(symbol)) {
527  /* In this case, don't save the top symbol, because it's not
528  * a var and thus it has no address. Callers who need that
529  * must notice an error in this case; callers who just want
530  * the offset from the top enclosing STUN type don't need it.
531  */
532  break;
533  }
534  else {
535  verror("invalid chain member (%s,%s) for nested S/U member (%d)!\n",
536  symbol_get_name(symbol),SYMBOL_TYPE(symbol->type),i);
537  errno = EINVAL;
538  return 0;
539  }
540  }
541 
542  return totaloffset;
543 }
544 #endif
545 
546 loctype_t symbol_resolve_location(struct symbol *symbol,
547  struct location_ctxt *lctxt,
548  struct location *o_loc) {
549  struct location_ops *lops = NULL;
550  ADDR addr;
551 
552  if (SYMBOLX_VAR_LOC(symbol))
553  return location_resolve(SYMBOLX_VAR_LOC(symbol),lctxt,symbol,o_loc);
554  else if (symbol->has_addr) {
555  if (lctxt && lctxt->ops)
556  lops = lctxt->ops;
557  addr = symbol->addr;
558  if (lops && lops->relocate) {
559  if (lops->relocate(lctxt,addr,&addr)) {
560  verror("failed to reclocate 0x%"PRIxADDR"!\n",addr);
561  return -LOCTYPE_ADDR;
562  }
563  }
564  if (o_loc)
565  location_set_addr(o_loc,addr);
566  return LOCTYPE_ADDR;
567  }
568  else {
569  vwarnopt(7,LA_DEBUG,LF_DLOC,"no location for ");
571  errno = EINVAL;
572  return LOCTYPE_UNKNOWN;
573  }
574 }
575 
576 int location_ctxt_read_retaddr(struct location_ctxt *lctxt,ADDR *o_retaddr) {
577  struct debugfile *debugfile;
578  ADDR retaddr = 0;
579 
580  if (!lctxt || !lctxt->ops || !lctxt->ops->getdebugfile) {
581  verror("no location_ops->getdebugfile!\n");
582  errno = EINVAL;
583  return -1;
584  }
585 
586  /* Find our debugfile. */
587  debugfile = lctxt->ops->getdebugfile(lctxt);
588  if (!debugfile) {
589  vwarnopt(11,LA_DEBUG,LF_DLOC,"could not find debugfile!\n");
590  errno = EINVAL;
591  return -1;
592  }
593 
594  /* Use the CFA API function to read a register. */
595  if (!debugfile->ops || !debugfile->ops->frame_read_retaddr) {
596  verror("debugfile does not support unwinding!\n");
597  errno = ENOTSUP;
598  return -1;
599  }
600  else if (debugfile->ops->frame_read_retaddr(debugfile,lctxt,&retaddr)) {
601  verror("failed to read return address in frame %d!\n",
602  lctxt->current_frame);
603  if (!errno)
604  errno = EFAULT;
605  return -1;
606  }
607 
608  /*
609  * The value is already "relocated" according to location_ops.
610  */
611 
612  if (o_retaddr)
613  *o_retaddr = retaddr;
614  return 0;
615 }
616 
617 /*
618  * Read a register -- either directly via @lops->readreg if !@lctxt
619  * || @lctxt->curent_frame == 0 -- or via the register frame cache in
620  * @lctxt (which is populated by interpreting CFA data).
621  *
622  * We want the location_ops owner to cache for frame 0. Well, there are
623  * pros and cons. If they cache, and then another user changes values,
624  * our whole location context could be messed up. On the other hand, if
625  * we want location_ctxt_writereg to make sense... hm. Not sure what to
626  * do yet. For now just don't cache.
627  *
628  * This function is only used internally because we provide
629  * location_ctxt_read_retaddr for the location_ops owner, so that they
630  * know what code owns the previous stack frame, and can then unwind it.
631  */
632 int location_ctxt_read_reg(struct location_ctxt *lctxt,REG reg,REGVAL *o_regval) {
633  struct debugfile *debugfile;
634  int rc;
635  REGVAL rv;
636  struct symbol *symbol;
637  struct symbol *root;
638 
639  if (!lctxt || !lctxt->ops || !lctxt->ops->readreg) {
640  verror("no location_ops->readreg for current frame %d!\n",
641  lctxt->current_frame);
642  errno = EINVAL;
643  return -1;
644  }
645 
646  /* First try to read it from the target (either CPU or cache). */
647  rc = lctxt->ops->readreg(lctxt,reg,o_regval);
648  if (rc == 0)
649  return 0;
650  /*
651  * If we get any other errors other than it not being in the cache
652  * (EADDRNOTAVAIL) , we don't try to read CFA.
653  */
654  else if (errno != EADDRNOTAVAIL) {
655  verror("could not read reg %d in frame %d: %s (%d)!\n",
656  reg,lctxt->current_frame,strerror(errno),errno);
657  return rc;
658  }
659 
660  /*
661  * Otherwise, use CFA data from the *next* frame to find
662  * callee-saved register values.
663  */
664  if (!lctxt || !lctxt->ops || !lctxt->ops->setcurrentframe) {
665  verror("no location_ops->setcurrentframe!\n");
666  errno = EINVAL;
667  return -1;
668  }
669  else if (!lctxt->ops->getsymbol) {
670  verror("no location_ops->getsymbol!\n");
671  errno = EINVAL;
672  return -1;
673  }
674 
675  if (lctxt->ops->setcurrentframe(lctxt,lctxt->current_frame - 1)) {
676  verror("could not set current frame from %d to %d (next)!\n",
677  lctxt->current_frame,lctxt->current_frame - 1);
678  errno = EBADSLT;
679  return -1;
680  }
681 
682  /* Find our debugfile. */
683  symbol = lctxt->ops->getsymbol(lctxt);
684  if (!symbol) {
685  vwarn("could not find symbol for current (well, \"next\") frame %d!\n",
686  lctxt->current_frame);
687  errno = EINVAL;
688  goto prev_frame_load_err_try_next_next;
689  }
690  root = symbol_find_root(symbol);
691  if (!root) {
692  verror("could not find root symbol for symbol '%s'!\n",
693  symbol_get_name(symbol));
694  errno = EINVAL;
695  goto prev_frame_load_err;
696  }
697  SYMBOL_RX_ROOT(root,srd);
698  debugfile = srd->debugfile;
699  if (!debugfile) {
700  verror("could not find debugfile for root symbol '%s'!\n",
701  symbol_get_name(root));
702  errno = EINVAL;
703  goto prev_frame_load_err;
704  }
705 
706  /* Use the CFA API function to read a register. */
707  if (!debugfile->ops || !debugfile->ops->frame_read_saved_reg) {
708  verror("debugfile does not support unwinding!\n");
709  errno = ENOTSUP;
710  goto prev_frame_load_err;
711  }
712 
713  if (debugfile->ops->frame_read_saved_reg(debugfile,lctxt,reg,&rv)) {
715  "could not read reg %"PRIiREG" in frame %d!\n",
716  reg,lctxt->current_frame);
717  if (!errno)
718  errno = EFAULT;
719  goto prev_frame_load_err;
720  }
721 
722  /*
723  * Stop using the current_frame - 1; re-get the current_frame so
724  * that we cache the result in the correct frame.
725  */
726  success:
727  if (lctxt->ops->setcurrentframe(lctxt,lctxt->current_frame + 1)) {
728  verror("could not set current frame from %d to %d (next)!\n",
729  lctxt->current_frame,lctxt->current_frame + 1);
730  errno = EBADSLT;
731  return -1;
732  }
733 
734  /* Put it in our cache. */
735  if (lctxt->ops->cachereg)
736  lctxt->ops->cachereg(lctxt,reg,rv);
737 
738  /*
739  * Return!
740  */
741  if (o_regval)
742  *o_regval = rv;
743 
744  return 0;
745 
746  prev_frame_load_err_try_next_next:
747  if (lctxt->current_frame > 0) {
749  "checking cache in (next next) frame %d because no CFI data\n",
750  lctxt->current_frame);
751  rc = location_ctxt_read_reg(lctxt,reg,o_regval);
752  if (rc) {
753  verror("could not read reg %"PRIiREG" in (next next) frame %d!\n",
754  reg,lctxt->current_frame);
755  goto prev_frame_load_err;
756  }
757  else goto success;
758  }
759 
760  prev_frame_load_err:
761  /*
762  * Stop using the current_frame - 1; re-get the current_frame so
763  * that we cache the result in the correct frame.
764  */
765  if (lctxt->ops->setcurrentframe(lctxt,lctxt->current_frame + 1)) {
766  verror("could not set current frame from %d to %d (next)!\n",
767  lctxt->current_frame,lctxt->current_frame + 1);
768  errno = EBADSLT;
769  return -1;
770  }
771  return -1;
772 }
773 
774 int location_ctxt_writereg(struct location_ctxt *lctxt,REG reg,REGVAL regval) {
775  int rc;
776 
777  if (!lctxt || lctxt->current_frame == 0) {
778  errno = 0;
779  if (!lctxt->ops || !lctxt->ops->readreg) {
780  errno = EINVAL;
781  return -1;
782  }
783  rc = lctxt->ops->writereg(lctxt,reg,regval);
784  if (rc) {
785  verror("could not write 0x%"PRIxREGVAL" to reg %d!\n",regval,reg);
786  return rc;
787  }
788  }
789  else {
790  /*
791  * Use CFA data to write a register.
792  */
793  return -1;
794  }
795 
796  /*
797  * Return!
798  */
799  return 0;
800 }
801 
803  struct location_ctxt *lctxt;
804 
805  lctxt = calloc(1,sizeof(*lctxt));
806  lctxt->ops = ops;
807  lctxt->priv = priv;
808 
809  return lctxt;
810 }
811 
812 void location_ctxt_free(struct location_ctxt *lctxt) {
813  free(lctxt);
814 }
815 
816 /*
817  * Resolves a location -- which may be as simple as a fixed address, or
818  * complex as a series of operations produced by a compiler's DWARF
819  * emitter.
820  *
821  * We need a location_ops so we can read registers, memory, and
822  * relocate/unrelocate addresses (i.e., from object to real and vice
823  * versa).
824  */
825 loctype_t location_resolve(struct location *loc,struct location_ctxt *lctxt,
826  struct symbol *symbol,struct location *o_loc) {
827  REGVAL regval;
828  struct symbol *parent;
829  ADDR ip,obj_ip;
830  ADDR addr;
831  REG reg;
832  OFFSET offset;
833  loctype_t rc;
834  struct loclistloc *loclistloc;
835  int found;
836  char *rtbuf;
837  unsigned int rtlen;
838  struct location tloc;
839  struct location_ops *lops = NULL;
840 
841  if (lctxt && lctxt->ops)
842  lops = lctxt->ops;
843 
844  switch (loc->loctype) {
845  case LOCTYPE_UNKNOWN:
846  vwarn("cannot resolve LOCTYPE_UNKNOWN");
847  if (symbol) {
848  vwarnc(" for ");
849  WARNDUMPSYMBOL_NL(symbol);
850  }
851  else
852  vwarnc("\n");
853  errno = EINVAL;
854  return LOCTYPE_UNKNOWN;
855  case LOCTYPE_REG:
856  errno = 0;
857  if (o_loc)
858  location_set_reg(o_loc,LOCATION_REG(loc));
859  return LOCTYPE_REG;
860  case LOCTYPE_ADDR:
861  errno = 0;
862  addr = LOCATION_ADDR(loc);
863  if (lops && lops->relocate) {
864  if (lops->relocate(lctxt,addr,&addr)) {
865  verror("failed to reclocate 0x%"PRIxADDR"!\n",addr);
866  return -LOCTYPE_ADDR;
867  }
868  }
869  if (o_loc)
870  location_set_addr(o_loc,addr);
871  return LOCTYPE_ADDR;
872  case LOCTYPE_REG_ADDR:
873  errno = 0;
874  if (location_ctxt_read_reg(lctxt,LOCATION_REG(loc),&regval)) {
875  verror("could not read address from reg %d!\n",
876  LOCATION_REG(loc));
877  return -LOCTYPE_REG_ADDR;
878  }
879  else {
880  if (o_loc)
881  location_set_addr(o_loc,regval);
882  return LOCTYPE_REG_ADDR;
883  }
884  break;
885  case LOCTYPE_REG_OFFSET:
886  LOCATION_GET_REGOFFSET(loc,reg,offset);
887  errno = 0;
888  if (location_ctxt_read_reg(lctxt,reg,&regval)) {
889  verror("could not read address from reg %d!\n",reg);
890  return -LOCTYPE_REG_OFFSET;
891  }
892  else {
893  if (o_loc)
894  location_set_addr(o_loc,(ADDR)(regval + offset));
895  return LOCTYPE_ADDR;
896  }
897  break;
899  if (!symbol) {
900  verror("cannot calc frame_base; no symbol supplied!\n");
901  errno = EINVAL;
902  return -LOCTYPE_FBREG_OFFSET;
903  }
904  /*
905  * To determine the value of the frame base pseudo register, we
906  * must find @symbol's containing function.
907  *
908  * NB: but, if the immediate parent function is inlineinstance,
909  * keep checking up the inlineinstance hierarchy for a valid
910  * fbloc!
911  */
912  parent = symbol;
913  while ((parent = symbol_find_parent(parent))) {
914  if (SYMBOL_IS_FUNC(parent)) {
915  SYMBOL_RX_FUNC(parent,pf);
916  if (pf && pf->fbloc)
917  /* Ok, we have one. */
918  break;
919  else if ((!pf || !pf->fbloc) && parent->isinlineinstance)
920  /* Let it look for fbloc in *its* parent! */
921  ;
922  else
923  /* Otherwise, this function just doesn't have an fbloc! */
924  /* Hm, that would seem to indicate a bug, if true... */
925  break;
926  }
927  }
928  if (!parent || !SYMBOL_IS_FUNC(parent)) {
930  "cannot calc frame_base; no parent function contains ");
932  errno = EINVAL;
933  return -LOCTYPE_FBREG_OFFSET;
934  }
935 
936  SYMBOL_RX_FUNC(parent,pf);
937  if (!pf || !pf->fbloc) {
939  "cannot calc frame_base; no frame base in parent function of ");
941  errno = EINVAL;
942  return -LOCTYPE_FBREG_OFFSET;
943  }
944 
945  /* Resolve the parent's fbloc; load it; and apply the offset! */
946  memset(&tloc,0,sizeof(tloc));
947  rc = location_resolve(pf->fbloc,lctxt,symbol,&tloc);
948  if (rc == LOCTYPE_REG) {
949  reg = LOCATION_REG(&tloc);
950  if (location_ctxt_read_reg(lctxt,reg,&regval)) {
951  verror("cannot read reg %"PRIiREG" to get frame_base value\n",
952  reg);
953  return -LOCTYPE_FBREG_OFFSET;
954  }
955  else
956  addr = regval;
957  }
958  else if (rc != LOCTYPE_ADDR) {
959  verror("cannot get frame base value: %s (%s)\n",
960  strerror(errno),LOCTYPE(rc));
961  return -LOCTYPE_FBREG_OFFSET;
962  }
963  else
964  addr = LOCATION_ADDR(&tloc);
965 
967  "frame_base 0x%"PRIxADDR",fboffset %"PRIiOFFSET"\n",
968  addr,LOCATION_OFFSET(loc));
969 
970  if (o_loc)
971  location_set_addr(o_loc,(ADDR)(addr + LOCATION_OFFSET(loc)));
972 
973  return LOCTYPE_ADDR;
974  case LOCTYPE_LOCLIST:
975  if (!lops || !lops->readipreg || !lops->unrelocate) {
976  errno = EINVAL;
977  return -LOCTYPE_LOCLIST;
978  }
979  else if (lops->readipreg(lctxt,&ip)) {
980  verror("could not read IP reg!\n");
981  return -LOCTYPE_REG_OFFSET;
982  }
983 
984  /*
985  * We load ip, convert it to obj_ip, scan the location list for
986  * a match, and run the matching location op recursively via
987  * location_resolve!
988  */
989  errno = 0;
990  if (lops->unrelocate(lctxt,ip,&obj_ip)) {
991  verror("could not convert IP 0x%"PRIxADDR" to obj addr!\n",ip);
992  errno = EFAULT;
993  return -LOCTYPE_LOCLIST;
994  }
995 
996  vdebug(5,LA_DEBUG,LF_DLOC,"ip 0x%"PRIxADDR"; obj_ip 0x%"PRIxADDR"\n",
997  ip,obj_ip);
998 
999  loclistloc = LOCATION_LOCLIST(loc);
1000  found = 0;
1001  while (loclistloc) {
1002  if (loclistloc->start <= obj_ip && obj_ip < loclistloc->end) {
1003  found = 1;
1004  break;
1005  }
1006  loclistloc = loclistloc->next;
1007  }
1008  if (!found) {
1010  "could not match obj_ip 0x%"PRIxADDR" in loclist!\n",
1011  obj_ip);
1012  errno = EADDRNOTAVAIL;
1013  return -LOCTYPE_LOCLIST;
1014  }
1015 
1016  return location_resolve(loclistloc->loc,lctxt,symbol,o_loc);
1017  case LOCTYPE_MEMBER_OFFSET:
1018  errno = 0;
1019  if (o_loc)
1021  return LOCTYPE_MEMBER_OFFSET;
1022  case LOCTYPE_IMPLICIT_WORD:
1023  errno = 0;
1024  if (o_loc)
1026  return LOCTYPE_IMPLICIT_WORD;
1027  case LOCTYPE_IMPLICIT_DATA:
1028  LOCATION_GET_DATA(loc,rtbuf,rtlen);
1029  errno = 0;
1030  if (o_loc)
1031  location_set_implicit_data(o_loc,rtbuf,rtlen,!loc->nofree);
1032  return LOCTYPE_IMPLICIT_DATA;
1033  case LOCTYPE_RUNTIME:
1034  LOCATION_GET_DATA(loc,rtbuf,rtlen);
1035  return dwarf_location_resolve((const unsigned char *)rtbuf,rtlen,
1036  lctxt,symbol,o_loc);
1037  default:
1038  vwarn("unknown location type %d\n",loc->loctype);
1039  errno = EINVAL;
1040  return LOCTYPE_UNKNOWN;
1041  }
1042 
1043  /* never reached */
1044  return -1;
1045 }
1046 
1047 int symbol_resolve_bounds(struct symbol *symbol,struct location_ctxt *lctxt,
1048  ADDR *o_start,ADDR *o_end,int *is_noncontiguous,
1049  ADDR *o_alt_start,ADDR *o_alt_end) {
1050  uint8_t as = 0,ae = 0;
1051  ADDR start = 0,end = 0,alt_start = 0,alt_end = 0;
1052  loctype_t rc;
1053  struct scope *scope;
1054  struct location o_loc;
1055  struct location_ops *lops = NULL;
1056 
1057  if (SYMBOL_IS_TYPE(symbol)) {
1058  errno = EINVAL;
1059  return -1;
1060  }
1061 
1062  if (!lctxt || !lctxt->ops) {
1063  verror("no location ops for current frame %d!\n",lctxt->current_frame);
1064  errno = EINVAL;
1065  return -1;
1066  }
1067  lops = lctxt->ops;
1068 
1069  memset(&o_loc,0,sizeof(o_loc));
1070 
1071  /*
1072  * Any non-type symbol should have a base address. If a symbol has
1073  * a fixed base address, it is in symbol->addr, and we use that.
1074  * Otherwise, we error unless it's a VAR that has a location; then
1075  * we try to resolve that.
1076  *
1077  * Only root and function symbols have alternate bounds; for root
1078  * symbols, alt_start == entry_pc; for function symbols, alt_start
1079  * == prologue_end || alt_start == entry_pc, alt_end == epilogue_begin.
1080  */
1081  if (SYMBOL_IS_ROOT(symbol)) {
1082  SYMBOL_RX_ROOT(symbol,sr);
1083  if (sr) {
1084  if (sr->scope && sr->scope->range && !sr->scope->range->next) {
1085  start = sr->scope->range->start;
1086  end = sr->scope->range->end;
1087  }
1088  if (sr->has_entry_pc) {
1089  as = 1;
1090  alt_start = sr->entry_pc;
1091  }
1092  }
1093 
1094  if (!start || (symbol->has_addr && start != symbol->addr))
1095  start = symbol->addr;
1096  if (!end)
1097  end = start + symbol_get_bytesize(symbol);
1098  }
1099  else if (SYMBOL_IS_FUNC(symbol)) {
1100  int trc = -1;
1101  scope = symbol_read_owned_scope(symbol);
1102  if (scope)
1103  trc = scope_get_overall_range(scope,&start,&end,is_noncontiguous);
1104  SYMBOL_RX_FUNC(symbol,sf);
1105  if (sf) {
1106  if (sf->prologue_guessed || sf->prologue_known) {
1107  as = 1;
1108  alt_start = sf->prologue_end;
1109  }
1110  else if (sf->has_entry_pc) {
1111  as = 1;
1112  alt_start = sf->entry_pc;
1113  }
1114  if (sf->epilogue_known) {
1115  ae = 1;
1116  alt_end = sf->epilogue_begin;
1117  }
1118  }
1119 
1120  if (!start && symbol->has_addr) {
1121  trc = 0;
1122  start = symbol->addr;
1123  }
1124  if (!end && start)
1125  end = start + symbol_get_bytesize(symbol);
1126 
1127  if (trc && !as && !ae) {
1128  return -1;
1129  }
1130  }
1131  else if (SYMBOL_IS_BLOCK(symbol)) {
1132  scope = symbol_read_owned_scope(symbol);
1133  if (scope)
1134  scope_get_overall_range(scope,&start,&end,is_noncontiguous);
1135 
1136  if (!start || (symbol->has_addr && start != symbol->addr))
1137  start = symbol->addr;
1138  if (!end)
1139  end = start + symbol_get_bytesize(symbol);
1140  }
1141  else if (SYMBOL_IS_LABEL(symbol)) {
1142  if (!symbol->has_addr)
1143  return -1;
1144  start = symbol->addr;
1145  /* Labels should not have a length! */
1146  end = start + symbol_get_bytesize(symbol);
1147  }
1148  else if (SYMBOL_IS_VAR(symbol)) {
1149  /* If it doesn't have a base address, resolve its location! */
1150  if (symbol->has_addr) {
1151  start = symbol->addr;
1152  end = start + symbol_get_bytesize(symbol);
1153  }
1154  else if (SYMBOLX_VAR_LOC(symbol)) {
1155  rc = location_resolve(SYMBOLX_VAR_LOC(symbol),lctxt,symbol,&o_loc);
1156  if (rc != LOCTYPE_ADDR)
1157  return -1;
1158  start = LOCATION_ADDR(&o_loc);
1159  end = start + symbol_get_bytesize(symbol);
1160  }
1161  }
1162  else {
1163  errno = EINVAL;
1164  return -1;
1165  }
1166 
1167  if (o_start) {
1168  if (lops && lops->relocate)
1169  lops->relocate(lctxt,start,o_start);
1170  else
1171  *o_start = start;
1172  }
1173 
1174  if (o_end) {
1175  if (lops && lops->relocate)
1176  lops->relocate(lctxt,end,o_end);
1177  else
1178  *o_end = end;
1179  }
1180  if (as && o_alt_start) {
1181  if (lops && lops->relocate)
1182  lops->relocate(lctxt,alt_start,o_alt_start);
1183  else
1184  *o_start = start;
1185  }
1186  if (ae && o_alt_end) {
1187  if (lops && lops->relocate)
1188  lops->relocate(lctxt,alt_end,o_alt_end);
1189  else
1190  *o_alt_end = alt_end;
1191  }
1192 
1193  return 0;
1194 }
1195 
1196 ADDR __autoload_pointers(struct symbol *datatype,ADDR addr,
1197  struct location_ctxt *lctxt,
1198  struct symbol **datatype_saveptr) {
1199  ADDR paddr = addr;
1200  int nptrs = 0;
1201  struct location_ops *lops;
1202 
1203  lops = lctxt->ops;
1204 
1205  while (SYMBOL_IST_PTR(datatype)) {
1207  "loading ptr at 0x%"PRIxADDR"\n",paddr);
1208 
1209  if (!lops || !lops->readword) {
1210  verror("no location ops to autoload ptr 0x%"PRIxADDR
1211  " for datatype %s",
1212  addr,symbol_get_name(datatype));
1213  errno = EINVAL;
1214  return 0;
1215  }
1216 
1217  if (lops->readword(lctxt,paddr,&paddr)) {
1218  verror("could not load ptr 0x%"PRIxADDR"\n",paddr);
1219  if (!errno)
1220  errno = EFAULT;
1221  goto errout;
1222  }
1223 
1224  ++nptrs;
1226  "loaded next ptr value 0x%"PRIxADDR" (#%d)\n",
1227  paddr,nptrs);
1228 
1229  /* Skip past the pointer we just loaded. */
1230  datatype = symbol_get_datatype(datatype);
1231  }
1232 
1233  errno = 0;
1234  if (datatype_saveptr)
1235  *datatype_saveptr = datatype;
1236  return paddr;
1237 
1238  errout:
1239  return 0;
1240 }
1241 
1242 /*
1243  * NB: perhaps following a chain of symbols is something best left in
1244  * the target library (because then NULL-ptr exceptions, out of bounds
1245  * accesses, etc, can be better handled). But, we do it here, because
1246  * we defined lsymbols here. Perhaps we shouldn't... I'm not sure any
1247  * more. It's useful to have them (i.e., to lookup member functions)...
1248  *
1249  * Anyway, this function can return LOCTYPE_UNKNOWN, -LOCTYPE_X (on
1250  * error); or LOCTYPE_ADDR, LOCTYPE_REG, LOCTYPE_IMPLICIT_* on success.
1251  *
1252  * If the first symbol is a containing type (i.e., struct/union/class)
1253  * or a pointer, you must provide a base address in @base_addr. If you
1254  * don't, we cannot compute the address of any further members (in this
1255  * case, if the type was a pointer, you will get a errno of EFAULT
1256  * unless there is actually something at 0x0; if the type was a
1257  * container, your address simply will be incorrect, and there won't be
1258  * an error). If the first symbol is a namespace type, or is not a
1259  * type, then you need not provide a base address.
1260  *
1261  * If you provide @lops->(relocate,unrelocate), then base_addr should be
1262  * a real address. Otherwise, it should be an obj address. This should
1263  * be obvious after a bit of thought; it is the only way to ensure
1264  * address consistency between obj and real.
1265  */
1267  struct location_ctxt *lctxt,
1268  struct location *o_loc) {
1269 
1270  /*
1271  * There are a number of special cases. Sometimes we don't need to
1272  * resolve every symbol on the chain -- this is true if the final
1273  * symbol is not a local var nor a member.
1274  */
1275  ADDR retval = base_addr;
1276  struct symbol *symbol;
1277  struct symbol *datatype;
1278  int llen;
1279  int i;
1281  struct symbol *tdatatype;
1282  REG reg = -1;
1283  struct location tloc;
1284 
1285  llen = lsymbol_len(lsymbol);
1286 
1287  /*
1288  * If the last symbol is a function, we only want to return its
1289  * base address. So shortcut, and do that.
1290  *
1291  * XXX: eventually, do we only want to do this if this function and
1292  * its parents are currently in scope? Perhaps... I can see both
1293  * sides. After all, in the binary form of the program, one
1294  * function isn't really nested in another; all functions always
1295  * have fixed, known code locations -- although of course the
1296  * compiler is free to assume that the function might not be
1297  * callable outside the function it was declared in (and thus do
1298  * optimizations that make an outside call fail). So perhaps even a
1299  * debugging entity might not be able to call a nested function, if
1300  * that's ever meaningful. Oh well... don't restrict for now!
1301  */
1302  symbol = lsymbol_last_symbol(lsymbol);
1303  if (SYMBOL_IS_FUNC(symbol) || SYMBOL_IS_LABEL(symbol)
1304  || SYMBOL_IS_BLOCK(symbol)) {
1305  if (symbol_resolve_bounds(symbol,lctxt,&retval,NULL,NULL,NULL,NULL)) {
1306  verror("could not resolve base addr for function %s!\n",
1307  symbol_get_name(symbol));
1308  goto errout;
1309  }
1310 
1311  vdebug(12,LA_DEBUG,LF_DLOC,"function %s at 0x%"PRIxADDR"\n",
1312  symbol_get_name(symbol),retval);
1313  /* Skip the loop, we're done. */
1314  i = llen;
1315  /* Resolve datatype just to conform to expected behavior of this
1316  * function; caller might want it.
1317  */
1318  datatype = symbol_get_datatype(symbol);
1319 
1320  rc = LOCTYPE_ADDR;
1321  }
1322  /*
1323  * If the final symbol on the chain is in a register, we skip
1324  * immediately to handling it; there is no need to handle anything
1325  * prior to it.
1326  */
1327  else if (SYMBOL_IS_VAR(symbol)) {
1328  rc = symbol_resolve_location(symbol,lctxt,NULL);
1329  if (rc == LOCTYPE_REG)
1330  i = llen - 1;
1331  else
1332  i = 0;
1333  }
1334  else {
1335  i = 0;
1336  }
1337 
1338  /*
1339  * We traverse through the lsymbol, loading nested chunks. If the
1340  * end of the chain is a function, we return its base address.
1341  * Otherwise, we do nothing for functions (they may be used to
1342  * resolve the location of variables, however -- i.e., computing the
1343  * dwarf frame_base virtual register). Otherwise, for variables, if
1344  * their types are pointers, we load the pointer, and keep loading
1345  * the chain according to the next type. If the last var is a
1346  * pointer, and the AUTO_DEREF flag is set (or if the AUTO_STRING
1347  * flag is set, and the final type is a char type), we deref the
1348  * pointer(s) and return the value of the last pointer. If it is
1349  * not a pointer, we return the computed address of the last var.
1350  */
1351  while (i < llen) {
1352  symbol = lsymbol_symbol(lsymbol,i);
1353 
1354  /*
1355  * Skip functions; may need them in the chain, however, so that
1356  * our location resolution functions can obtain the frame
1357  * register info they need to resolve, if a subsequent
1358  * variable's location is dependent on the frame base register.
1359  *
1360  * Also skip namespaces; they have no bearing on location
1361  * resolution.
1362  */
1363  if (SYMBOL_IS_FUNC(symbol) || SYMBOL_IST_NAMESPACE(symbol)) {
1364  vdebug(12,LA_DEBUG,LF_DLOC,"pass %d: skipping ",i);
1365  LOGDUMPSYMBOL(12,LA_DEBUG,LF_DLOC,symbol);
1366  if (symbol->datatype) {
1367  vdebugc(12,LA_DEBUG,LF_DLOC," with datatype ");
1370  }
1371  vdebugc(12,LA_DEBUG,LF_DLOC,"\n");
1372 
1373  ++i;
1374 
1375  continue;
1376  }
1377  else {
1378  vdebug(12,LA_DEBUG,LF_DLOC,"pass %d: checking ",i);
1379  LOGDUMPSYMBOL(12,LA_DEBUG,LF_DLOC,symbol);
1380  if (symbol->datatype) {
1381  vdebugc(12,LA_DEBUG,LF_DLOC," with datatype ");
1384  }
1385  vdebugc(12,LA_DEBUG,LF_DLOC,"\n");
1386 
1387  ++i;
1388  }
1389 
1390  /*
1391  * If the symbol is a pointer or struct/union/class type, we
1392  * support those (pointers by autoloading; S/U/C by skipping).
1393  * Otherwise, it's an error -- i.e., users can't try to compute
1394  * an address for 'enum foo_enum.FOO_ENUM_ONE'.
1395  */
1396  if (SYMBOL_IS_TYPE(symbol)) {
1397  /* Grab the type's datatype. */
1398  tdatatype = symbol_type_skip_qualifiers(symbol);
1399 
1400  if (SYMBOL_IST_PTR(tdatatype)) {
1401  datatype = tdatatype;
1402  rc = LOCTYPE_ADDR;
1403  goto check_pointer;
1404  }
1405  else if (SYMBOL_IST_STUNC(tdatatype))
1406  continue;
1407  else {
1408  verror("cannot load intermediate type symbol %s!\n",
1409  symbol_get_name(symbol));
1410  errno = EINVAL;
1411  goto errout;
1412  }
1413  }
1414 
1415  /* We error on all other symbol types that are not variables. */
1416  if (!SYMBOL_IS_VAR(symbol)) {
1417  verror("symbol %s of type %s is not a full variable!\n",
1418  symbol_get_name(symbol),SYMBOL_TYPE(symbol->type));
1419  errno = EINVAL;
1420  goto errout;
1421  }
1422 
1423  /* Grab the symbol's datatype. */
1424  datatype = symbol_get_datatype(symbol);
1425 
1426  memset(&tloc,0,sizeof(tloc));
1427  rc = symbol_resolve_location(symbol,lctxt,&tloc);
1428  // &retval,&reg,&offset);
1429  if (rc == LOCTYPE_MEMBER_OFFSET) {
1430  retval += LOCATION_OFFSET(&tloc);
1431  vdebug(12,LA_DEBUG,LF_DLOC,
1432  "member %s at offset 0x%"PRIxOFFSET"; addr 0x%"PRIxADDR"\n",
1433  symbol_get_name(symbol),LOCATION_OFFSET(&tloc),retval);
1434  }
1435  else if (rc == LOCTYPE_REG) {
1436  reg = LOCATION_REG(&tloc);
1437  /*
1438  * NB: see below inside the pointer check where we will try
1439  * to load the pointer across this register.
1440  */
1441  vdebug(12,LA_DEBUG,LF_DLOC,"var %s in reg %"PRIiREG"\n",
1442  symbol_get_name(symbol),reg);
1443  }
1444  else if (rc == LOCTYPE_ADDR) {
1445  retval = LOCATION_ADDR(&tloc);
1446  vdebug(12,LA_DEBUG,LF_DLOC,"var %s at 0x%"PRIxADDR"\n",
1447  symbol_get_name(symbol),retval);
1448  }
1449  else if (rc == LOCTYPE_IMPLICIT_WORD) {
1450  retval = LOCATION_WORD(&tloc);
1451  vdebug(12,LA_DEBUG,LF_DLOC,
1452  "var %s has implicit value 0x%"PRIxADDR"\n",
1453  symbol_get_name(symbol),retval);
1454  }
1455  else {
1457  "could not resolve location for symbol %s: %s (%d)!\n",
1458  symbol_get_name(symbol),strerror(errno),errno);
1459  goto errout;
1460  }
1461 
1462  /*
1463  * If the symbol is a pointer, load it now. If this is the
1464  * final symbol in the chain (i == llen), don't load its
1465  * pointer; just stop where we are.
1466  */
1467  check_pointer:
1468  if (i < llen && SYMBOL_IST_PTR(datatype)) {
1469  if (rc == LOCTYPE_REG) {
1470  /*
1471  * Try to load the ptr value from a register; might or
1472  * might not be an address; only is if the current
1473  * symbol was a pointer; we handle that below. There's
1474  * a termination condition below this loop that if we
1475  * end after having resolved the location to a register,
1476  * we can't calculate the address for it.
1477  */
1478  if (location_ctxt_read_reg(lctxt,reg,&retval)) {
1479  verror("could not read ptr symbol %s from reg %d: %s!\n",
1480  symbol_get_name(symbol),reg,strerror(errno));
1481  goto errout;
1482  }
1483 
1484  vdebug(12,LA_DEBUG,LF_DLOC,
1485  "ptr var (in reg %"PRIiREG") %s = 0x%"PRIxADDR"\n",
1486  reg,symbol_get_name(symbol),retval);
1487 
1488  /* We have to skip one pointer type */
1489  datatype = symbol_type_skip_qualifiers(datatype->datatype);
1490 
1491  /*
1492  * Clear the in_reg bit, since we were able to
1493  * autoload the pointer!
1494  */
1495  rc = LOCTYPE_ADDR;
1496 
1497  /* Do we need to keep trying to load through the pointer? */
1498  if (SYMBOL_IST_PTR(datatype))
1499  goto check_pointer;
1500  }
1501  else {
1502  errno = 0;
1503  retval = __autoload_pointers(datatype,retval,lctxt,&datatype);
1504  if (errno) {
1505  verror("could not load pointer for symbol %s\n",
1506  symbol_get_name(symbol));
1507  goto errout;
1508  }
1509 
1510  vdebug(12,LA_DEBUG,LF_DLOC,
1511  "autoloaded pointer(s) for var %s = 0x%"PRIxADDR"\n",
1512  symbol_get_name(symbol),retval);
1513  }
1514  }
1515  }
1516 
1517  /* Return! */
1518  if (rc == LOCTYPE_REG) {
1519  if (o_loc)
1520  location_set_reg(o_loc,reg);
1521 
1522  vdebug(12,LA_DEBUG,LF_DLOC,"regno = 0x%"PRIiREG"; datatype = ",reg);
1523  if (datatype) {
1525  symbol_type_skip_qualifiers(datatype));
1526  }
1527  else
1528  vdebugc(12,LA_DEBUG,LF_DLOC,"NULL\n");
1529 
1530  return LOCTYPE_REG;
1531  }
1532  else if (rc == LOCTYPE_ADDR || rc == LOCTYPE_MEMBER_OFFSET) {
1533  if (o_loc)
1534  location_set_addr(o_loc,retval);
1535 
1536  vdebug(12,LA_DEBUG,LF_DLOC,"addr = 0x%"PRIxADDR"; datatype = ",retval);
1537  if (datatype) {
1539  symbol_type_skip_qualifiers(datatype));
1540  }
1541  else
1542  vdebugc(12,LA_DEBUG,LF_DLOC,"NULL\n");
1543 
1544  return LOCTYPE_ADDR;
1545  }
1546  else if (rc == LOCTYPE_IMPLICIT_WORD) {
1547  if (o_loc)
1548  location_set_implicit_word(o_loc,retval);
1549 
1550  vdebug(12,LA_DEBUG,LF_DLOC,
1551  "implicit word = 0x%"PRIxADDR"; datatype = ",retval);
1552  if (datatype) {
1554  symbol_type_skip_qualifiers(datatype));
1555  }
1556  else
1557  vdebugc(12,LA_DEBUG,LF_DLOC,"NULL\n");
1558 
1559  return LOCTYPE_IMPLICIT_WORD;
1560  }
1561 
1562  errout:
1563  return rc;
1564 }
1565 
1567  struct location_ctxt *lctxt,
1568  ADDR *start,ADDR *end,int *is_noncontiguous,
1569  ADDR *alt_start,ADDR *alt_end) {
1570  struct symbol *symbol;
1571  uint32_t size = 0;
1572  loctype_t rc;
1573  struct location tloc;
1574 
1575  if (!lctxt) {
1576  verror("no location_ctxt for current frame!\n");
1577  errno = EINVAL;
1578  return -1;
1579  }
1580 
1581  symbol = lsymbol_last_symbol(lsymbol);
1582 
1583  if (SYMBOL_IS_TYPE(symbol)) {
1584  errno = EINVAL;
1585  return -1;
1586  }
1587 
1588  /*
1589  * If it's not a var, its location is independent of the lsymbol
1590  * chain. Otherwise, we have to resolve its base, then update its
1591  * end according to its size.
1592  */
1593  if (!SYMBOL_IS_VAR(symbol))
1594  return symbol_resolve_bounds(symbol,lctxt,start,end,
1595  is_noncontiguous,alt_start,alt_end);
1596 
1597  /*
1598  * Otherwise, work the chain to resolve the base addr, then fill in
1599  * the size. No alt_* info for variables, obviously.
1600  */
1601  memset(&tloc,0,sizeof(tloc));
1602  rc = lsymbol_resolve_location(lsymbol,base_addr,lctxt,&tloc);
1603  if (rc != LOCTYPE_ADDR) {
1604  verror("could not resolve location for %s to addr: %s (%d) (%s)!\n",
1605  symbol_get_name(symbol),strerror(errno),rc,
1606  (rc > LOCTYPE_UNKNOWN) ? LOCTYPE(rc) : "");
1607  return -1;
1608  }
1609 
1611  "found base of '%s' at 0x%"PRIxADDR"\n",
1612  symbol_get_name(symbol),*start);
1613 
1614  /* Collect its size. */
1615  if (end) {
1616  size = symbol_get_bytesize(symbol);
1617  *end = *start + size;
1618  }
1619 
1620  return 0;
1621 }
#define SYMBOL_IST_NAMESPACE(sym)
#define LOCATION_ADDR(loc)
Definition: dwdebug_priv.h:622
void loclistloc_dump(struct loclistloc *list, struct dump_info *ud)
Definition: location.c:364
void location_dump(struct location *location, struct dump_info *ud)
Definition: location.c:392
int location_set_fbreg_offset(struct location *l, OFFSET offset)
Definition: location.c:98
char * data
Definition: dwdebug_priv.h:605
#define vwarnopt(level, area, flags, format,...)
Definition: log.h:37
struct symbol * symbol_find_parent(struct symbol *symbol)
Definition: debug.c:3106
#define LOCATION_IS_ADDR(loc)
Definition: dwdebug_priv.h:611
#define PRIiOFFSET
Definition: common.h:70
int location_ctxt_writereg(struct location_ctxt *lctxt, REG reg, REGVAL regval)
Definition: location.c:774
#define LOCATION_IS_FB_OFFSET(loc)
Definition: dwdebug_priv.h:616
union location::@6 l
struct location * location_create(void)
Definition: location.c:39
unsigned int has_addr
Definition: dwdebug_priv.h:839
#define SYMBOL_RX_ROOT(sym, rvar)
union symbol::@7 size
#define SYMBOL_RX_FUNC(sym, rvar)
Definition: probe.h:392
struct scope * symbol_read_owned_scope(struct symbol *symbol)
Definition: debug.c:2674
struct location_ops * ops
Definition: dwdebug_priv.h:744
int location_update_loclist(struct location *loc, ADDR start, ADDR end, struct location *rloc, int *action)
Definition: location.c:199
#define PRIiREG
Definition: common.h:94
static uint64_t unsigned int i
struct symbol * symbol_find_root(struct symbol *symbol)
Definition: debug.c:3119
int(* relocate)(struct location_ctxt *lctxt, ADDR obj_addr, ADDR *real_addr)
Definition: dwdebug_priv.h:704
ADDR addr
Definition: dwdebug_priv.h:916
void location_internal_free(struct location *location)
Definition: location.c:347
#define LOCATION_LOCLIST(loc)
Definition: dwdebug_priv.h:625
uint32_t symbol_get_bytesize(struct symbol *symbol)
Definition: debug.c:3065
ADDR __autoload_pointers(struct symbol *datatype, ADDR addr, struct location_ctxt *lctxt, struct symbol **datatype_saveptr)
Definition: location.c:1196
int32_t OFFSET
Definition: common.h:65
int location_ctxt_read_reg(struct location_ctxt *lctxt, REG reg, REGVAL *o_regval)
Definition: location.c:632
#define verror(format,...)
Definition: log.h:30
struct symbol * symbol_get_datatype(struct symbol *symbol)
Definition: debug.c:2989
int(* frame_read_saved_reg)(struct debugfile *debugfile, struct location_ctxt *lctxt, REG reg, REGVAL *o_regval)
Definition: dwdebug_priv.h:154
#define SYMBOLX_VAR_LOC(sym)
#define LOGDUMPSYMBOL_NL(dl, lt, lf, s)
Definition: dwdebug_priv.h:30
int location_set_reg(struct location *l, REG reg)
Definition: location.c:55
symbol_type_t type
Definition: dwdebug_priv.h:833
int symbol_is_member(struct symbol *symbol)
Definition: debug.c:3038
OFFSET offset
Definition: dwdebug_priv.h:603
#define vwarn(format,...)
Definition: log.h:33
#define LOCATION_WORD(loc)
Definition: dwdebug_priv.h:626
void free(void *ptr)
Definition: debugserver.c:207
#define LOCATION_GET_DATA(loc, buf, buflen)
Definition: dwdebug_priv.h:633
#define LOCATION_IS_M_OFFSET(loc)
Definition: dwdebug_priv.h:615
#define SYMBOL_IS_LABEL(sym)
#define LOCATION_OFFSET(loc)
Definition: dwdebug_priv.h:624
Definition: log.h:69
struct loclistloc * next
Definition: dwdebug_priv.h:562
int location_set_implicit_data(struct location *loc, char *data, int len, int nocopy)
Definition: location.c:128
struct location * loc
Definition: dwdebug_priv.h:561
char * prefix
Definition: output.h:25
loctype_t location_resolve(struct location *loc, struct location_ctxt *lctxt, struct symbol *symbol, struct location *o_loc)
Definition: location.c:825
struct loclistloc * loclist
Definition: dwdebug_priv.h:606
int location_set_reg_addr(struct location *l, REG reg)
Definition: location.c:64
struct symbol *(* getsymbol)(struct location_ctxt *lctxt)
Definition: dwdebug_priv.h:681
struct debugfile *(* getdebugfile)(struct location_ctxt *lctxt)
Definition: dwdebug_priv.h:677
struct debugfile_ops * ops
Definition: dwdebug.h:799
uint32_t offset
Definition: dwdebug_priv.h:906
int(* cachereg)(struct location_ctxt *lctxt, REG regno, REGVAL regval)
Definition: dwdebug_priv.h:693
int lsymbol_resolve_bounds(struct lsymbol *lsymbol, ADDR base_addr, struct location_ctxt *lctxt, ADDR *start, ADDR *end, int *is_noncontiguous, ADDR *alt_start, ADDR *alt_end)
Definition: location.c:1566
#define PRIxOFFSET
Definition: common.h:71
#define SYMBOL_IST_PTR(sym)
#define WARNDUMPSYMBOL_NL(s)
Definition: dwdebug_priv.h:38
#define SYMBOL_IS_BLOCK(sym)
int(* readipreg)(struct location_ctxt *lctxt, REGVAL *regval)
Definition: dwdebug_priv.h:697
int(* frame_read_retaddr)(struct debugfile *debugfile, struct location_ctxt *lctxt, ADDR *o_retaddr)
Definition: dwdebug_priv.h:171
#define LOCATION_GET_REGOFFSET(loc, reg, offset)
Definition: dwdebug_priv.h:628
int len
Definition: dumptarget.c:52
#define SYMBOL_IST_STUNC(sym)
#define SYMBOL_IST_STUN(sym)
#define LOCATION_IS_REG_ADDR(loc)
Definition: dwdebug_priv.h:613
int location_set_member_offset(struct location *l, OFFSET offset)
Definition: location.c:89
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
FILE * stream
Definition: output.h:26
int location_ctxt_read_retaddr(struct location_ctxt *lctxt, ADDR *o_retaddr)
Definition: location.c:576
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
struct symbol * symbol_type_skip_qualifiers(struct symbol *type)
Definition: debug.c:4191
loctype_t symbol_resolve_location(struct symbol *symbol, struct location_ctxt *lctxt, struct location *o_loc)
Definition: location.c:546
int location_set_loclist(struct location *l, struct loclistloc *list)
Definition: location.c:107
int(* setcurrentframe)(struct location_ctxt *lctxt, int frame)
Definition: dwdebug_priv.h:673
#define vdebugc(devel, areas, flags, format,...)
Definition: log.h:303
#define SYMBOL_IS_TYPE(sym)
#define SYMBOL_IS_FULL_VAR(sym)
void * calloc(size_t nmemb, size_t size)
Definition: debugserver.c:200
Definition: log.h:129
int symbol_resolve_bounds(struct symbol *symbol, struct location_ctxt *lctxt, ADDR *o_start, ADDR *o_end, int *is_noncontiguous, ADDR *o_alt_start, ADDR *o_alt_end)
Definition: location.c:1047
#define LOCATION_IS_REG_OFFSET(loc)
Definition: dwdebug_priv.h:614
int(* unrelocate)(struct location_ctxt *lctxt, ADDR real_addr, ADDR *obj_addr)
Definition: dwdebug_priv.h:705
uint32_t REGVAL
Definition: common.h:66
int location_set_reg_offset(struct location *l, REG reg, OFFSET offset)
Definition: location.c:73
#define LOCATION_REMAINING_BITS
Definition: dwdebug_priv.h:570
#define LOCATION_IS_LOCLIST(loc)
Definition: dwdebug_priv.h:617
int8_t REG
Definition: common.h:93
#define LOCATION_IS_RUNTIME(loc)
Definition: dwdebug_priv.h:620
#define vwarnc(format,...)
Definition: log.h:35
uint32_t ADDR
Definition: common.h:64
loctype_t loctype
Definition: dwdebug_priv.h:585
struct location_ctxt * location_ctxt_create(struct location_ops *ops, void *priv)
Definition: location.c:802
#define PRIxADDR
Definition: common.h:67
#define SYMBOL_IS_ROOT(sym)
int detail
Definition: output.h:28
char * SYMBOL_TYPE(int n)
Definition: debug.c:5662
#define LOCATION_REG(loc)
Definition: dwdebug_priv.h:623
char * symbol_get_name(struct symbol *symbol)
Definition: debug.c:2587
#define LOCATION_IS_IMPLICIT_WORD(loc)
Definition: dwdebug_priv.h:618
struct symbol_root * root
Definition: dwdebug_priv.h:973
void * malloc(size_t size)
Definition: debugserver.c:214
int(* writereg)(struct location_ctxt *lctxt, REG regno, REGVAL regval)
Definition: dwdebug_priv.h:688
unsigned int isinlineinstance
Definition: dwdebug_priv.h:839
int meta
Definition: output.h:27
void location_free(struct location *location)
Definition: location.c:359
int location_set_implicit_word(struct location *loc, ADDR word)
Definition: location.c:119
int location_set_runtime(struct location *l, char *data, int len, int nocopy)
Definition: location.c:164
int scope_get_overall_range(struct scope *scope, ADDR *low_addr_saveptr, ADDR *high_addr_saveptr, int *is_noncontiguous)
Definition: scope.c:290
struct location * location_copy(struct location *location)
Definition: location.c:313
#define SYMBOL_IS_FUNC(sym)
void location_ctxt_free(struct location_ctxt *lctxt)
Definition: location.c:812
int(* readword)(struct location_ctxt *lctxt, ADDR real_addr, ADDR *pval)
Definition: dwdebug_priv.h:702
#define LOCATION_IS_REG(loc)
Definition: dwdebug_priv.h:612
#define WARNOPTDUMPSYMBOL_NL(wl, lt, lf, s)
Definition: dwdebug_priv.h:46
loctype_t
Definition: dwdebug.h:234
struct symbol * datatype
Definition: dwdebug_priv.h:925
unsigned int ismember
Definition: dwdebug_priv.h:839
Definition: log.h:127
#define LOGDUMPSYMBOL(dl, lt, lf, s)
Definition: dwdebug_priv.h:25
#define SYMBOL_IS_VAR(sym)
loctype_t lsymbol_resolve_location(struct lsymbol *lsymbol, ADDR base_addr, struct location_ctxt *lctxt, struct location *o_loc)
Definition: location.c:1266
#define PRIxREGVAL
Definition: common.h:72
int location_set_addr(struct location *l, ADDR addr)
Definition: location.c:46
#define LOCATION_IS_UNKNOWN(loc)
Definition: dwdebug_priv.h:610