1
2 /*--------------------------------------------------------------------*/
3 /*--- Format-neutral storage of and querying of info acquired from ---*/
4 /*--- ELF/XCOFF stabs/dwarf1/dwarf2/dwarf3 debug info. ---*/
5 /*--- storage.c ---*/
6 /*--------------------------------------------------------------------*/
7
8 /*
9 This file is part of Valgrind, a dynamic binary instrumentation
10 framework.
11
12 Copyright (C) 2000-2011 Julian Seward
13 jseward@acm.org
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file COPYING.
31 */
32
33 /* This file manages the data structures built by the debuginfo
34 system. These are: the top level SegInfo list. For each SegInfo,
35 there are tables for for address-to-symbol mappings,
36 address-to-src-file/line mappings, and address-to-CFI-info
37 mappings.
38 */
39
40 #include "pub_core_basics.h"
41 #include "pub_core_options.h" /* VG_(clo_verbosity) */
42 #include "pub_core_debuginfo.h"
43 #include "pub_core_libcassert.h"
44 #include "pub_core_libcbase.h"
45 #include "pub_core_libcprint.h"
46 #include "pub_core_xarray.h"
47 #include "pub_core_oset.h"
48
49 #include "priv_misc.h" /* dinfo_zalloc/free/strdup */
50 #include "priv_d3basics.h" /* ML_(pp_GX) */
51 #include "priv_tytypes.h"
52 #include "priv_storage.h" /* self */
53
54
55 /*------------------------------------------------------------*/
56 /*--- Misc (printing, errors) ---*/
57 /*------------------------------------------------------------*/
58
59 /* Show a non-fatal debug info reading error. Use vg_panic if
60 terminal. 'serious' errors are shown regardless of the
61 verbosity setting. */
ML_(symerr)62 void ML_(symerr) ( struct _DebugInfo* di, Bool serious, HChar* msg )
63 {
64 /* XML mode hides everything :-( */
65 if (VG_(clo_xml))
66 return;
67
68 if (serious) {
69
70 VG_(message)(Vg_DebugMsg, "WARNING: Serious error when "
71 "reading debug info\n");
72 if (True || VG_(clo_verbosity) < 2) {
73 /* Need to show what the file name is, at verbosity levels 2
74 or below, since that won't already have been shown */
75 VG_(message)(Vg_DebugMsg,
76 "When reading debug info from %s:\n",
77 (di && di->fsm.filename) ? di->fsm.filename
78 : (UChar*)"???");
79 }
80 VG_(message)(Vg_DebugMsg, "%s\n", msg);
81
82 } else { /* !serious */
83
84 if (VG_(clo_verbosity) >= 2)
85 VG_(message)(Vg_DebugMsg, "%s\n", msg);
86
87 }
88 }
89
90
91 /* Print a symbol. */
ML_(ppSym)92 void ML_(ppSym) ( Int idx, DiSym* sym )
93 {
94 UChar** sec_names = sym->sec_names;
95 vg_assert(sym->pri_name);
96 if (sec_names)
97 vg_assert(sec_names);
98 VG_(printf)( "%5d: %c%c %#8lx .. %#8lx (%d) %s%s",
99 idx,
100 sym->isText ? 'T' : '-',
101 sym->isIFunc ? 'I' : '-',
102 sym->addr,
103 sym->addr + sym->size - 1, sym->size,
104 sym->pri_name, sec_names ? " " : "" );
105 if (sec_names) {
106 while (*sec_names) {
107 VG_(printf)("%s%s", *sec_names, *(sec_names+1) ? " " : "");
108 sec_names++;
109 }
110 }
111 VG_(printf)("\n");
112 }
113
114 /* Print a call-frame-info summary. */
ML_(ppDiCfSI)115 void ML_(ppDiCfSI) ( XArray* /* of CfiExpr */ exprs, DiCfSI* si )
116 {
117 # define SHOW_HOW(_how, _off) \
118 do { \
119 if (_how == CFIR_UNKNOWN) { \
120 VG_(printf)("Unknown"); \
121 } else \
122 if (_how == CFIR_SAME) { \
123 VG_(printf)("Same"); \
124 } else \
125 if (_how == CFIR_CFAREL) { \
126 VG_(printf)("cfa+%d", _off); \
127 } else \
128 if (_how == CFIR_MEMCFAREL) { \
129 VG_(printf)("*(cfa+%d)", _off); \
130 } else \
131 if (_how == CFIR_EXPR) { \
132 VG_(printf)("{"); \
133 ML_(ppCfiExpr)(exprs, _off); \
134 VG_(printf)("}"); \
135 } else { \
136 vg_assert(0+0); \
137 } \
138 } while (0)
139
140 VG_(printf)("[%#lx .. %#lx]: ", si->base,
141 si->base + (UWord)si->len - 1);
142 switch (si->cfa_how) {
143 case CFIC_IA_SPREL:
144 VG_(printf)("let cfa=oldSP+%d", si->cfa_off);
145 break;
146 case CFIC_IA_BPREL:
147 VG_(printf)("let cfa=oldBP+%d", si->cfa_off);
148 break;
149 case CFIC_ARM_R13REL:
150 VG_(printf)("let cfa=oldR13+%d", si->cfa_off);
151 break;
152 case CFIC_ARM_R12REL:
153 VG_(printf)("let cfa=oldR12+%d", si->cfa_off);
154 break;
155 case CFIC_ARM_R11REL:
156 VG_(printf)("let cfa=oldR11+%d", si->cfa_off);
157 break;
158 case CFIR_SAME:
159 VG_(printf)("let cfa=Same");
160 break;
161 case CFIC_ARM_R7REL:
162 VG_(printf)("let cfa=oldR7+%d", si->cfa_off);
163 break;
164 case CFIC_EXPR:
165 VG_(printf)("let cfa={");
166 ML_(ppCfiExpr)(exprs, si->cfa_off);
167 VG_(printf)("}");
168 break;
169 default:
170 vg_assert(0);
171 }
172
173 VG_(printf)(" in RA=");
174 SHOW_HOW(si->ra_how, si->ra_off);
175 # if defined(VGA_x86) || defined(VGA_amd64)
176 VG_(printf)(" SP=");
177 SHOW_HOW(si->sp_how, si->sp_off);
178 VG_(printf)(" BP=");
179 SHOW_HOW(si->bp_how, si->bp_off);
180 # elif defined(VGA_arm)
181 VG_(printf)(" R14=");
182 SHOW_HOW(si->r14_how, si->r14_off);
183 VG_(printf)(" R13=");
184 SHOW_HOW(si->r13_how, si->r13_off);
185 VG_(printf)(" R12=");
186 SHOW_HOW(si->r12_how, si->r12_off);
187 VG_(printf)(" R11=");
188 SHOW_HOW(si->r11_how, si->r11_off);
189 VG_(printf)(" R7=");
190 SHOW_HOW(si->r7_how, si->r7_off);
191 # elif defined(VGA_ppc32) || defined(VGA_ppc64)
192 # elif defined(VGA_s390x)
193 VG_(printf)(" SP=");
194 SHOW_HOW(si->sp_how, si->sp_off);
195 VG_(printf)(" FP=");
196 SHOW_HOW(si->fp_how, si->fp_off);
197 # else
198 # error "Unknown arch"
199 # endif
200 VG_(printf)("\n");
201 # undef SHOW_HOW
202 }
203
204
205 /*------------------------------------------------------------*/
206 /*--- Adding stuff ---*/
207 /*------------------------------------------------------------*/
208
209 /* Add a str to the string table, including terminating zero, and
210 return pointer to the string in vg_strtab. Unless it's been seen
211 recently, in which case we find the old pointer and return that.
212 This avoids the most egregious duplications.
213
214 JSGF: changed from returning an index to a pointer, and changed to
215 a chunking memory allocator rather than reallocating, so the
216 pointers are stable.
217 */
ML_(addStr)218 UChar* ML_(addStr) ( struct _DebugInfo* di, UChar* str, Int len )
219 {
220 struct strchunk *chunk;
221 Int space_needed;
222 UChar* p;
223
224 if (len == -1) {
225 len = VG_(strlen)(str);
226 } else {
227 vg_assert(len >= 0);
228 }
229
230 space_needed = 1 + len;
231
232 // Allocate a new strtab chunk if necessary
233 if (di->strchunks == NULL ||
234 (di->strchunks->strtab_used
235 + space_needed) > SEGINFO_STRCHUNKSIZE) {
236 chunk = ML_(dinfo_zalloc)("di.storage.addStr.1", sizeof(*chunk));
237 chunk->strtab_used = 0;
238 chunk->next = di->strchunks;
239 di->strchunks = chunk;
240 }
241 chunk = di->strchunks;
242
243 p = &chunk->strtab[chunk->strtab_used];
244 VG_(memcpy)(p, str, len);
245 chunk->strtab[chunk->strtab_used+len] = '\0';
246 chunk->strtab_used += space_needed;
247
248 return p;
249 }
250
251
252 /* Add a symbol to the symbol table, by copying *sym. 'sym' may only
253 have one name, so there's no complexities to do with deep vs
254 shallow copying of the sec_name array. This is checked.
255 */
ML_(addSym)256 void ML_(addSym) ( struct _DebugInfo* di, DiSym* sym )
257 {
258 UInt new_sz, i;
259 DiSym* new_tab;
260
261 vg_assert(sym->pri_name != NULL);
262 vg_assert(sym->sec_names == NULL);
263
264 /* Ignore zero-sized syms. */
265 if (sym->size == 0) return;
266
267 if (di->symtab_used == di->symtab_size) {
268 new_sz = 2 * di->symtab_size;
269 if (new_sz == 0) new_sz = 500;
270 new_tab = ML_(dinfo_zalloc)( "di.storage.addSym.1",
271 new_sz * sizeof(DiSym) );
272 if (di->symtab != NULL) {
273 for (i = 0; i < di->symtab_used; i++)
274 new_tab[i] = di->symtab[i];
275 ML_(dinfo_free)(di->symtab);
276 }
277 di->symtab = new_tab;
278 di->symtab_size = new_sz;
279 }
280
281 di->symtab[di->symtab_used++] = *sym;
282 vg_assert(di->symtab_used <= di->symtab_size);
283 }
284
285
286 /* Add a location to the location table.
287 */
addLoc(struct _DebugInfo * di,DiLoc * loc)288 static void addLoc ( struct _DebugInfo* di, DiLoc* loc )
289 {
290 UInt new_sz, i;
291 DiLoc* new_tab;
292
293 /* Zero-sized locs should have been ignored earlier */
294 vg_assert(loc->size > 0);
295
296 if (di->loctab_used == di->loctab_size) {
297 new_sz = 2 * di->loctab_size;
298 if (new_sz == 0) new_sz = 500;
299 new_tab = ML_(dinfo_zalloc)( "di.storage.addLoc.1",
300 new_sz * sizeof(DiLoc) );
301 if (di->loctab != NULL) {
302 for (i = 0; i < di->loctab_used; i++)
303 new_tab[i] = di->loctab[i];
304 ML_(dinfo_free)(di->loctab);
305 }
306 di->loctab = new_tab;
307 di->loctab_size = new_sz;
308 }
309
310 di->loctab[di->loctab_used] = *loc;
311 di->loctab_used++;
312 vg_assert(di->loctab_used <= di->loctab_size);
313 }
314
315
316 /* Resize the LocTab (line number table) to save memory, by removing
317 (and, potentially, allowing m_mallocfree to unmap) any unused space
318 at the end of the table.
319 */
shrinkLocTab(struct _DebugInfo * di)320 static void shrinkLocTab ( struct _DebugInfo* di )
321 {
322 DiLoc* new_tab;
323 UWord new_sz = di->loctab_used;
324 if (new_sz == di->loctab_size) return;
325 vg_assert(new_sz < di->loctab_size);
326
327 new_tab = ML_(dinfo_zalloc)( "di.storage.shrinkLocTab",
328 new_sz * sizeof(DiLoc) );
329 VG_(memcpy)(new_tab, di->loctab, new_sz * sizeof(DiLoc));
330
331 ML_(dinfo_free)(di->loctab);
332 di->loctab = new_tab;
333 di->loctab_size = new_sz;
334 }
335
336
337 /* Top-level place to call to add a source-location mapping entry.
338 */
ML_(addLineInfo)339 void ML_(addLineInfo) ( struct _DebugInfo* di,
340 UChar* filename,
341 UChar* dirname, /* NULL == directory is unknown */
342 Addr this,
343 Addr next,
344 Int lineno,
345 Int entry /* only needed for debug printing */
346 )
347 {
348 static const Bool debug = False;
349 DiLoc loc;
350 Int size = next - this;
351
352 /* Ignore zero-sized locs */
353 if (this == next) return;
354
355 if (debug)
356 VG_(printf)( " src %s %s line %d %#lx-%#lx\n",
357 dirname ? dirname : (UChar*)"(unknown)",
358 filename, lineno, this, next );
359
360 /* Maximum sanity checking. Some versions of GNU as do a shabby
361 * job with stabs entries; if anything looks suspicious, revert to
362 * a size of 1. This should catch the instruction of interest
363 * (since if using asm-level debug info, one instruction will
364 * correspond to one line, unlike with C-level debug info where
365 * multiple instructions can map to the one line), but avoid
366 * catching any other instructions bogusly. */
367 if (this > next) {
368 if (VG_(clo_verbosity) > 2) {
369 VG_(message)(Vg_DebugMsg,
370 "warning: line info addresses out of order "
371 "at entry %d: 0x%lx 0x%lx\n", entry, this, next);
372 }
373 size = 1;
374 }
375
376 if (size > MAX_LOC_SIZE) {
377 if (0)
378 VG_(message)(Vg_DebugMsg,
379 "warning: line info address range too large "
380 "at entry %d: %d\n", entry, size);
381 size = 1;
382 }
383
384 /* Rule out ones which are completely outside the r-x mapped area.
385 See "Comment_Regarding_Text_Range_Checks" elsewhere in this file
386 for background and rationale. */
387 vg_assert(di->fsm.have_rx_map && di->fsm.have_rw_map);
388 if (next-1 < di->fsm.rx_map_avma
389 || this >= di->fsm.rx_map_avma + di->fsm.rx_map_size ) {
390 if (0)
391 VG_(message)(Vg_DebugMsg,
392 "warning: ignoring line info entry falling "
393 "outside current DebugInfo: %#lx %#lx %#lx %#lx\n",
394 di->text_avma,
395 di->text_avma + di->text_size,
396 this, next-1);
397 return;
398 }
399
400 vg_assert(lineno >= 0);
401 if (lineno > MAX_LINENO) {
402 static Bool complained = False;
403 if (!complained) {
404 complained = True;
405 VG_(message)(Vg_UserMsg,
406 "warning: ignoring line info entry with "
407 "huge line number (%d)\n", lineno);
408 VG_(message)(Vg_UserMsg,
409 " Can't handle line numbers "
410 "greater than %d, sorry\n", MAX_LINENO);
411 VG_(message)(Vg_UserMsg,
412 "(Nb: this message is only shown once)\n");
413 }
414 return;
415 }
416
417 loc.addr = this;
418 loc.size = (UShort)size;
419 loc.lineno = lineno;
420 loc.filename = filename;
421 loc.dirname = dirname;
422
423 if (0) VG_(message)(Vg_DebugMsg,
424 "addLoc: addr %#lx, size %d, line %d, file %s\n",
425 this,size,lineno,filename);
426
427 addLoc ( di, &loc );
428 }
429
430
431 /* Top-level place to call to add a CFI summary record. The supplied
432 DiCfSI is copied. */
ML_(addDiCfSI)433 void ML_(addDiCfSI) ( struct _DebugInfo* di, DiCfSI* cfsi_orig )
434 {
435 static const Bool debug = False;
436 UInt new_sz, i;
437 DiCfSI* new_tab;
438 SSizeT delta;
439
440 /* copy the original, so we can mess with it */
441 DiCfSI cfsi = *cfsi_orig;
442
443 if (debug) {
444 VG_(printf)("adding DiCfSI: ");
445 ML_(ppDiCfSI)(di->cfsi_exprs, &cfsi);
446 }
447
448 /* sanity */
449 vg_assert(cfsi.len > 0);
450 /* If this fails, the implication is you have a single procedure
451 with more than 5 million bytes of code. Which is pretty
452 unlikely. Either that, or the debuginfo reader is somehow
453 broken. 5 million is of course arbitrary; but it's big enough
454 to be bigger than the size of any plausible piece of code that
455 would fall within a single procedure. */
456 vg_assert(cfsi.len < 5000000);
457
458 vg_assert(di->fsm.have_rx_map && di->fsm.have_rw_map);
459 /* If we have an empty r-x mapping (is that possible?) then the
460 DiCfSI can't possibly fall inside it. In which case skip. */
461 if (di->fsm.rx_map_size == 0)
462 return;
463
464 /* Rule out ones which are completely outside the r-x mapped area.
465 See "Comment_Regarding_Text_Range_Checks" elsewhere in this file
466 for background and rationale. */
467 if (cfsi.base + cfsi.len - 1 < di->fsm.rx_map_avma
468 || cfsi.base >= di->fsm.rx_map_avma + di->fsm.rx_map_size) {
469 static Int complaints = 10;
470 if (VG_(clo_trace_cfi) || complaints > 0) {
471 complaints--;
472 if (VG_(clo_verbosity) > 1) {
473 VG_(message)(
474 Vg_DebugMsg,
475 "warning: DiCfSI %#lx .. %#lx outside segment %#lx .. %#lx\n",
476 cfsi.base,
477 cfsi.base + cfsi.len - 1,
478 di->text_avma,
479 di->text_avma + di->text_size - 1
480 );
481 }
482 if (VG_(clo_trace_cfi))
483 ML_(ppDiCfSI)(di->cfsi_exprs, &cfsi);
484 }
485 return;
486 }
487
488 /* Now we know the range is at least partially inside the r-x
489 mapped area. That implies that at least one of the ends of the
490 range falls inside the area. If necessary, clip it so it is
491 completely within the area. If we don't do this,
492 check_CFSI_related_invariants() in debuginfo.c (invariant #2)
493 will fail. See
494 "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
495 priv_storage.h for background. */
496 if (cfsi.base < di->fsm.rx_map_avma) {
497 /* Lower end is outside the mapped area. Hence upper end must
498 be inside it. */
499 if (0) VG_(printf)("XXX truncate lower\n");
500 vg_assert(cfsi.base + cfsi.len - 1 >= di->fsm.rx_map_avma);
501 delta = (SSizeT)(di->fsm.rx_map_avma - cfsi.base);
502 vg_assert(delta > 0);
503 vg_assert(delta < (SSizeT)cfsi.len);
504 cfsi.base += delta;
505 cfsi.len -= delta;
506 }
507 else
508 if (cfsi.base + cfsi.len - 1 > di->fsm.rx_map_avma
509 + di->fsm.rx_map_size - 1) {
510 /* Upper end is outside the mapped area. Hence lower end must be
511 inside it. */
512 if (0) VG_(printf)("XXX truncate upper\n");
513 vg_assert(cfsi.base <= di->fsm.rx_map_avma + di->fsm.rx_map_size - 1);
514 delta = (SSizeT)( (cfsi.base + cfsi.len - 1)
515 - (di->fsm.rx_map_avma + di->fsm.rx_map_size - 1) );
516 vg_assert(delta > 0); vg_assert(delta < (SSizeT)cfsi.len);
517 cfsi.len -= delta;
518 }
519
520 /* Final checks */
521
522 /* Because: either cfsi was entirely inside the range, in which
523 case we asserted that len > 0 at the start, OR it fell partially
524 inside the range, in which case we reduced it by some size
525 (delta) which is < its original size. */
526 vg_assert(cfsi.len > 0);
527
528 /* Similar logic applies for the next two assertions. */
529 vg_assert(cfsi.base >= di->fsm.rx_map_avma);
530 vg_assert(cfsi.base + cfsi.len - 1
531 <= di->fsm.rx_map_avma + di->fsm.rx_map_size - 1);
532
533 if (di->cfsi_used == di->cfsi_size) {
534 new_sz = 2 * di->cfsi_size;
535 if (new_sz == 0) new_sz = 20;
536 new_tab = ML_(dinfo_zalloc)( "di.storage.addDiCfSI.1",
537 new_sz * sizeof(DiCfSI) );
538 if (di->cfsi != NULL) {
539 for (i = 0; i < di->cfsi_used; i++)
540 new_tab[i] = di->cfsi[i];
541 ML_(dinfo_free)(di->cfsi);
542 }
543 di->cfsi = new_tab;
544 di->cfsi_size = new_sz;
545 }
546
547 di->cfsi[di->cfsi_used] = cfsi;
548 di->cfsi_used++;
549 vg_assert(di->cfsi_used <= di->cfsi_size);
550 }
551
552
ML_(CfiExpr_Undef)553 Int ML_(CfiExpr_Undef)( XArray* dst )
554 {
555 CfiExpr e;
556 VG_(memset)( &e, 0, sizeof(e) );
557 e.tag = Cex_Undef;
558 return (Int)VG_(addToXA)( dst, &e );
559 }
ML_(CfiExpr_Deref)560 Int ML_(CfiExpr_Deref)( XArray* dst, Int ixAddr )
561 {
562 CfiExpr e;
563 VG_(memset)( &e, 0, sizeof(e) );
564 e.tag = Cex_Deref;
565 e.Cex.Deref.ixAddr = ixAddr;
566 return (Int)VG_(addToXA)( dst, &e );
567 }
ML_(CfiExpr_Const)568 Int ML_(CfiExpr_Const)( XArray* dst, UWord con )
569 {
570 CfiExpr e;
571 VG_(memset)( &e, 0, sizeof(e) );
572 e.tag = Cex_Const;
573 e.Cex.Const.con = con;
574 return (Int)VG_(addToXA)( dst, &e );
575 }
ML_(CfiExpr_Binop)576 Int ML_(CfiExpr_Binop)( XArray* dst, CfiOp op, Int ixL, Int ixR )
577 {
578 CfiExpr e;
579 VG_(memset)( &e, 0, sizeof(e) );
580 e.tag = Cex_Binop;
581 e.Cex.Binop.op = op;
582 e.Cex.Binop.ixL = ixL;
583 e.Cex.Binop.ixR = ixR;
584 return (Int)VG_(addToXA)( dst, &e );
585 }
ML_(CfiExpr_CfiReg)586 Int ML_(CfiExpr_CfiReg)( XArray* dst, CfiReg reg )
587 {
588 CfiExpr e;
589 VG_(memset)( &e, 0, sizeof(e) );
590 e.tag = Cex_CfiReg;
591 e.Cex.CfiReg.reg = reg;
592 return (Int)VG_(addToXA)( dst, &e );
593 }
ML_(CfiExpr_DwReg)594 Int ML_(CfiExpr_DwReg)( XArray* dst, Int reg )
595 {
596 CfiExpr e;
597 VG_(memset)( &e, 0, sizeof(e) );
598 e.tag = Cex_DwReg;
599 e.Cex.DwReg.reg = reg;
600 return (Int)VG_(addToXA)( dst, &e );
601 }
602
ppCfiOp(CfiOp op)603 static void ppCfiOp ( CfiOp op )
604 {
605 switch (op) {
606 case Cop_Add: VG_(printf)("+"); break;
607 case Cop_Sub: VG_(printf)("-"); break;
608 case Cop_And: VG_(printf)("&"); break;
609 case Cop_Mul: VG_(printf)("*"); break;
610 case Cop_Shl: VG_(printf)("<<"); break;
611 case Cop_Shr: VG_(printf)(">>"); break;
612 case Cop_Eq: VG_(printf)("=="); break;
613 case Cop_Ge: VG_(printf)(">="); break;
614 case Cop_Gt: VG_(printf)(">"); break;
615 case Cop_Le: VG_(printf)("<="); break;
616 case Cop_Lt: VG_(printf)("<"); break;
617 case Cop_Ne: VG_(printf)("!="); break;
618 default: vg_assert(0);
619 }
620 }
621
ppCfiReg(CfiReg reg)622 static void ppCfiReg ( CfiReg reg )
623 {
624 switch (reg) {
625 case Creg_IA_SP: VG_(printf)("xSP"); break;
626 case Creg_IA_BP: VG_(printf)("xBP"); break;
627 case Creg_IA_IP: VG_(printf)("xIP"); break;
628 case Creg_ARM_R13: VG_(printf)("R13"); break;
629 case Creg_ARM_R12: VG_(printf)("R12"); break;
630 case Creg_ARM_R15: VG_(printf)("R15"); break;
631 case Creg_ARM_R14: VG_(printf)("R14"); break;
632 default: vg_assert(0);
633 }
634 }
635
ML_(ppCfiExpr)636 void ML_(ppCfiExpr)( XArray* src, Int ix )
637 {
638 /* VG_(indexXA) checks for invalid src/ix values, so we can
639 use it indiscriminately. */
640 CfiExpr* e = (CfiExpr*) VG_(indexXA)( src, ix );
641 switch (e->tag) {
642 case Cex_Undef:
643 VG_(printf)("Undef");
644 break;
645 case Cex_Deref:
646 VG_(printf)("*(");
647 ML_(ppCfiExpr)(src, e->Cex.Deref.ixAddr);
648 VG_(printf)(")");
649 break;
650 case Cex_Const:
651 VG_(printf)("0x%lx", e->Cex.Const.con);
652 break;
653 case Cex_Binop:
654 VG_(printf)("(");
655 ML_(ppCfiExpr)(src, e->Cex.Binop.ixL);
656 VG_(printf)(")");
657 ppCfiOp(e->Cex.Binop.op);
658 VG_(printf)("(");
659 ML_(ppCfiExpr)(src, e->Cex.Binop.ixR);
660 VG_(printf)(")");
661 break;
662 case Cex_CfiReg:
663 ppCfiReg(e->Cex.CfiReg.reg);
664 break;
665 case Cex_DwReg:
666 VG_(printf)("dwr%d", e->Cex.DwReg.reg);
667 break;
668 default:
669 VG_(core_panic)("ML_(ppCfiExpr)");
670 /*NOTREACHED*/
671 break;
672 }
673 }
674
675
ML_(cmp_for_DiAddrRange_range)676 Word ML_(cmp_for_DiAddrRange_range) ( const void* keyV,
677 const void* elemV ) {
678 const Addr* key = (const Addr*)keyV;
679 const DiAddrRange* elem = (const DiAddrRange*)elemV;
680 if (0)
681 VG_(printf)("cmp_for_DiAddrRange_range: %#lx vs %#lx\n",
682 *key, elem->aMin);
683 if ((*key) < elem->aMin) return -1;
684 if ((*key) > elem->aMax) return 1;
685 return 0;
686 }
687
688 static
show_scope(OSet * scope,HChar * who)689 void show_scope ( OSet* /* of DiAddrRange */ scope, HChar* who )
690 {
691 DiAddrRange* range;
692 VG_(printf)("Scope \"%s\" = {\n", who);
693 VG_(OSetGen_ResetIter)( scope );
694 while (True) {
695 range = VG_(OSetGen_Next)( scope );
696 if (!range) break;
697 VG_(printf)(" %#lx .. %#lx: %lu vars\n", range->aMin, range->aMax,
698 range->vars ? VG_(sizeXA)(range->vars) : 0);
699 }
700 VG_(printf)("}\n");
701 }
702
703 /* Add the variable 'var' to 'scope' for the address range [aMin,aMax]
704 (inclusive of aMin and aMax). Split existing ranges as required if
705 aMin or aMax or both don't match existing range boundaries, and add
706 'var' to all required ranges. Take great care to preserve the
707 invariant that the ranges in 'scope' cover the entire address range
708 exactly once, with no overlaps and no holes. */
add_var_to_arange(OSet * scope,Addr aMin,Addr aMax,DiVariable * var)709 static void add_var_to_arange (
710 /*MOD*/OSet* /* of DiAddrRange */ scope,
711 Addr aMin,
712 Addr aMax,
713 DiVariable* var
714 )
715 {
716 DiAddrRange *first, *last, *range;
717 /* These xx variables are for assertion checking only; they don't
718 contribute anything to the actual work of this function. */
719 DiAddrRange *xxRangep, *xxFirst, *xxLast;
720 UWord xxIters;
721
722 vg_assert(aMin <= aMax);
723
724 if (0) VG_(printf)("add_var_to_arange: %#lx .. %#lx\n", aMin, aMax);
725 if (0) show_scope( scope, "add_var_to_arange(1)" );
726
727 /* See if the lower end of the range (aMin) falls exactly on an
728 existing range boundary. If not, find the range it does fall
729 into, and split it (copying the variables in the process), so
730 that aMin does exactly fall on a range boundary. */
731 first = VG_(OSetGen_Lookup)( scope, &aMin );
732 /* It must be present, since the presented OSet must cover
733 the entire address range. */
734 vg_assert(first);
735 vg_assert(first->aMin <= first->aMax);
736 vg_assert(first->aMin <= aMin && aMin <= first->aMax);
737
738 /* Fast track common case, which is that the range specified for
739 the variable exactly coincides with one already-existing
740 range. */
741 if (first->aMin == aMin && first->aMax == aMax) {
742 vg_assert(first->vars);
743 VG_(addToXA)( first->vars, var );
744 return;
745 }
746
747 /* We have to get into splitting ranges, which is complex
748 and slow. */
749 if (first->aMin < aMin) {
750 DiAddrRange* nyu;
751 /* Ok. We'll have to split 'first'. */
752 /* truncate the upper end of 'first' */
753 Addr tmp = first->aMax;
754 first->aMax = aMin-1;
755 vg_assert(first->aMin <= first->aMax);
756 /* create a new range */
757 nyu = VG_(OSetGen_AllocNode)( scope, sizeof(DiAddrRange) );
758 vg_assert(nyu);
759 nyu->aMin = aMin;
760 nyu->aMax = tmp;
761 vg_assert(nyu->aMin <= nyu->aMax);
762 /* copy vars into it */
763 vg_assert(first->vars);
764 nyu->vars = VG_(cloneXA)( "di.storage.avta.1", first->vars );
765 vg_assert(nyu->vars);
766 VG_(OSetGen_Insert)( scope, nyu );
767 first = nyu;
768 }
769
770 vg_assert(first->aMin == aMin);
771
772 /* Now do exactly the same for the upper end (aMax): if it doesn't
773 fall on a boundary, cause it to do so by splitting the range it
774 does currently fall into. */
775 last = VG_(OSetGen_Lookup)( scope, &aMax );
776 vg_assert(last->aMin <= last->aMax);
777 vg_assert(last->aMin <= aMax && aMax <= last->aMax);
778
779 if (aMax < last->aMax) {
780 DiAddrRange* nyu;
781 /* We have to split 'last'. */
782 /* truncate the lower end of 'last' */
783 Addr tmp = last->aMin;
784 last->aMin = aMax+1;
785 vg_assert(last->aMin <= last->aMax);
786 /* create a new range */
787 nyu = VG_(OSetGen_AllocNode)( scope, sizeof(DiAddrRange) );
788 vg_assert(nyu);
789 nyu->aMin = tmp;
790 nyu->aMax = aMax;
791 vg_assert(nyu->aMin <= nyu->aMax);
792 /* copy vars into it */
793 vg_assert(last->vars);
794 nyu->vars = VG_(cloneXA)( "di.storage.avta.2", last->vars );
795 vg_assert(nyu->vars);
796 VG_(OSetGen_Insert)( scope, nyu );
797 last = nyu;
798 }
799
800 vg_assert(aMax == last->aMax);
801
802 xxFirst = (DiAddrRange*)VG_(OSetGen_Lookup)(scope, &aMin);
803 xxLast = (DiAddrRange*)VG_(OSetGen_Lookup)(scope, &aMax);
804 vg_assert(xxFirst);
805 vg_assert(xxLast);
806 vg_assert(xxFirst->aMin == aMin);
807 vg_assert(xxLast->aMax == aMax);
808 if (xxFirst != xxLast)
809 vg_assert(xxFirst->aMax < xxLast->aMin);
810
811 /* Great. Now we merely need to iterate over the segments from
812 'first' to 'last' inclusive, and add 'var' to the variable set
813 of each of them. */
814 if (0) {
815 static UWord ctr = 0;
816 ctr++;
817 VG_(printf)("ctr = %lu\n", ctr);
818 if (ctr >= 33263) show_scope( scope, "add_var_to_arange(2)" );
819 }
820
821 xxIters = 0;
822 range = xxRangep = NULL;
823 VG_(OSetGen_ResetIterAt)( scope, &aMin );
824 while (True) {
825 xxRangep = range;
826 range = VG_(OSetGen_Next)( scope );
827 if (!range) break;
828 if (range->aMin > aMax) break;
829 xxIters++;
830 if (0) VG_(printf)("have range %#lx %#lx\n",
831 range->aMin, range->aMax);
832
833 /* Sanity checks */
834 if (!xxRangep) {
835 /* This is the first in the range */
836 vg_assert(range->aMin == aMin);
837 } else {
838 vg_assert(xxRangep->aMax + 1 == range->aMin);
839 }
840
841 vg_assert(range->vars);
842 VG_(addToXA)( range->vars, var );
843 }
844 /* Done. We should have seen at least one range. */
845 vg_assert(xxIters >= 1);
846 if (xxIters == 1) vg_assert(xxFirst == xxLast);
847 if (xxFirst == xxLast) vg_assert(xxIters == 1);
848 vg_assert(xxRangep);
849 vg_assert(xxRangep->aMax == aMax);
850 vg_assert(xxRangep == xxLast);
851 }
852
853
854 /* Top-level place to call to add a variable description (as extracted
855 from a DWARF3 .debug_info section. */
ML_(addVar)856 void ML_(addVar)( struct _DebugInfo* di,
857 Int level,
858 Addr aMin,
859 Addr aMax,
860 UChar* name, /* in di's .strchunks */
861 UWord typeR, /* a cuOff */
862 GExpr* gexpr,
863 GExpr* fbGX,
864 UChar* fileName, /* where decl'd - may be NULL.
865 in di's .strchunks */
866 Int lineNo, /* where decl'd - may be zero */
867 Bool show )
868 {
869 OSet* /* of DiAddrRange */ scope;
870 DiVariable var;
871 Bool all;
872 TyEnt* ent;
873 MaybeULong mul;
874 HChar* badness;
875
876 tl_assert(di && di->admin_tyents);
877
878 if (0) {
879 VG_(printf)(" ML_(addVar): level %d %#lx-%#lx %s :: ",
880 level, aMin, aMax, name );
881 ML_(pp_TyEnt_C_ishly)( di->admin_tyents, typeR );
882 VG_(printf)("\n Var=");
883 ML_(pp_GX)(gexpr);
884 VG_(printf)("\n");
885 if (fbGX) {
886 VG_(printf)(" FrB=");
887 ML_(pp_GX)( fbGX );
888 VG_(printf)("\n");
889 } else {
890 VG_(printf)(" FrB=none\n");
891 }
892 VG_(printf)("\n");
893 }
894
895 vg_assert(level >= 0);
896 vg_assert(aMin <= aMax);
897 vg_assert(name);
898 vg_assert(gexpr);
899
900 ent = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL, typeR);
901 tl_assert(ent);
902 vg_assert(ML_(TyEnt__is_type)(ent));
903
904 /* "Comment_Regarding_Text_Range_Checks" (is referred to elsewhere)
905 ----------------------------------------------------------------
906 Ignore any variables whose aMin .. aMax (that is, range of text
907 addresses for which they actually exist) falls outside the text
908 segment. Is this indicative of a bug in the reader? Maybe.
909 (LATER): instead of restricting strictly to the .text segment,
910 be a bit more relaxed, and accept any variable whose text range
911 falls inside the r-x mapped area. This is useful because .text
912 is not always the only instruction-carrying segment: others are:
913 .init .plt __libc_freeres_fn and .fini. This implicitly assumes
914 that those extra sections have the same bias as .text, but that
915 seems a reasonable assumption to me. */
916 /* This is assured us by top level steering logic in debuginfo.c,
917 and it is re-checked at the start of
918 ML_(read_elf_debug_info). */
919 vg_assert(di->fsm.have_rx_map && di->fsm.have_rw_map);
920 if (level > 0
921 && (aMax < di->fsm.rx_map_avma
922 || aMin >= di->fsm.rx_map_avma + di->fsm.rx_map_size)) {
923 if (VG_(clo_verbosity) >= 0) {
924 VG_(message)(Vg_DebugMsg,
925 "warning: addVar: in range %#lx .. %#lx outside "
926 "segment %#lx .. %#lx (%s)\n",
927 aMin, aMax,
928 di->text_avma, di->text_avma + di->text_size -1,
929 name
930 );
931 }
932 return;
933 }
934
935 /* If the type's size is zero (which can mean unknown size), ignore
936 it. We will never be able to actually relate a data address to
937 a data object with zero size, so there's no point in storing
938 info on it. On 32-bit platforms, also reject types whose size
939 is 2^32 bytes or large. (It's amazing what junk shows up ..) */
940 mul = ML_(sizeOfType)(di->admin_tyents, typeR);
941
942 badness = NULL;
943 if (mul.b != True)
944 badness = "unknown size";
945 else if (mul.ul == 0)
946 badness = "zero size ";
947 else if (sizeof(void*) == 4 && mul.ul >= (1ULL<<32))
948 badness = "implausibly large";
949
950 if (badness) {
951 static Int complaints = 10;
952 if (VG_(clo_verbosity) >= 2 && complaints > 0) {
953 VG_(message)(Vg_DebugMsg, "warning: addVar: %s (%s)\n",
954 badness, name );
955 complaints--;
956 }
957 return;
958 }
959
960 if (!di->varinfo) {
961 di->varinfo = VG_(newXA)( ML_(dinfo_zalloc),
962 "di.storage.addVar.1",
963 ML_(dinfo_free),
964 sizeof(OSet*) );
965 }
966
967 vg_assert(level < 256); /* arbitrary; stay sane */
968 /* Expand the top level array enough to map this level */
969 while ( VG_(sizeXA)(di->varinfo) <= level ) {
970 DiAddrRange* nyu;
971 scope = VG_(OSetGen_Create)( offsetof(DiAddrRange,aMin),
972 ML_(cmp_for_DiAddrRange_range),
973 ML_(dinfo_zalloc), "di.storage.addVar.2",
974 ML_(dinfo_free) );
975 vg_assert(scope);
976 if (0) VG_(printf)("create: scope = %p, adding at %ld\n",
977 scope, VG_(sizeXA)(di->varinfo));
978 VG_(addToXA)( di->varinfo, &scope );
979 /* Add a single range covering the entire address space. At
980 level 0 we require this doesn't get split. At levels above 0
981 we require that any additions to it cause it to get split.
982 All of these invariants get checked both add_var_to_arange
983 and after reading is complete, in canonicaliseVarInfo. */
984 nyu = VG_(OSetGen_AllocNode)( scope, sizeof(DiAddrRange) );
985 vg_assert(nyu);
986 nyu->aMin = (Addr)0;
987 nyu->aMax = ~(Addr)0;
988 nyu->vars = VG_(newXA)( ML_(dinfo_zalloc), "di.storage.addVar.3",
989 ML_(dinfo_free),
990 sizeof(DiVariable) );
991 vg_assert(nyu->vars);
992 VG_(OSetGen_Insert)( scope, nyu );
993 }
994
995 vg_assert( VG_(sizeXA)(di->varinfo) > level );
996 scope = *(OSet**)VG_(indexXA)( di->varinfo, level );
997 vg_assert(scope);
998
999 var.name = name;
1000 var.typeR = typeR;
1001 var.gexpr = gexpr;
1002 var.fbGX = fbGX;
1003 var.fileName = fileName;
1004 var.lineNo = lineNo;
1005
1006 all = aMin == (Addr)0 && aMax == ~(Addr)0;
1007 vg_assert(level == 0 ? all : !all);
1008
1009 add_var_to_arange( /*MOD*/scope, aMin, aMax, &var );
1010 }
1011
1012
1013 /* This really just checks the constructed data structure, as there is
1014 no canonicalisation to do. */
canonicaliseVarInfo(struct _DebugInfo * di)1015 static void canonicaliseVarInfo ( struct _DebugInfo* di )
1016 {
1017 Word i, nInThisScope;
1018
1019 if (!di->varinfo)
1020 return;
1021
1022 for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
1023
1024 DiAddrRange *range, *rangep;
1025 OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
1026 if (!scope) continue;
1027
1028 /* Deal with the global-scope case. */
1029 if (i == 0) {
1030 Addr zero = 0;
1031 vg_assert(VG_(OSetGen_Size)( scope ) == 1);
1032 range = VG_(OSetGen_Lookup)( scope, &zero );
1033 vg_assert(range);
1034 vg_assert(range->aMin == (Addr)0);
1035 vg_assert(range->aMax == ~(Addr)0);
1036 continue;
1037 }
1038
1039 /* All the rest of this is for the local-scope case. */
1040 /* iterate over all entries in 'scope' */
1041 nInThisScope = 0;
1042 rangep = NULL;
1043 VG_(OSetGen_ResetIter)(scope);
1044 while (True) {
1045 range = VG_(OSetGen_Next)(scope);
1046 if (!range) {
1047 /* We just saw the last one. There must have been at
1048 least one entry in the range. */
1049 vg_assert(rangep);
1050 vg_assert(rangep->aMax == ~(Addr)0);
1051 break;
1052 }
1053
1054 vg_assert(range->aMin <= range->aMax);
1055 vg_assert(range->vars);
1056
1057 if (!rangep) {
1058 /* This is the first entry in the range. */
1059 vg_assert(range->aMin == 0);
1060 } else {
1061 vg_assert(rangep->aMax + 1 == range->aMin);
1062 }
1063
1064 rangep = range;
1065 nInThisScope++;
1066 } /* iterating over ranges in a given scope */
1067
1068 /* If there's only one entry in this (local) scope, it must
1069 cover the entire address space (obviously), but it must not
1070 contain any vars. */
1071
1072 vg_assert(nInThisScope > 0);
1073 if (nInThisScope == 1) {
1074 Addr zero = 0;
1075 vg_assert(VG_(OSetGen_Size)( scope ) == 1);
1076 range = VG_(OSetGen_Lookup)( scope, &zero );
1077 vg_assert(range);
1078 vg_assert(range->aMin == (Addr)0);
1079 vg_assert(range->aMax == ~(Addr)0);
1080 vg_assert(range->vars);
1081 vg_assert(VG_(sizeXA)(range->vars) == 0);
1082 }
1083
1084 } /* iterate over scopes */
1085 }
1086
1087
1088 /*------------------------------------------------------------*/
1089 /*--- Canonicalisers ---*/
1090 /*------------------------------------------------------------*/
1091
1092 /* Sort the symtab by starting address, and emit warnings if any
1093 symbols have overlapping address ranges. We use that old chestnut,
1094 shellsort. Mash the table around so as to establish the property
1095 that addresses are in order and the ranges to not overlap. This
1096 facilitates using binary search to map addresses to symbols when we
1097 come to query the table.
1098 */
compare_DiSym(void * va,void * vb)1099 static Int compare_DiSym ( void* va, void* vb )
1100 {
1101 DiSym* a = (DiSym*)va;
1102 DiSym* b = (DiSym*)vb;
1103 if (a->addr < b->addr) return -1;
1104 if (a->addr > b->addr) return 1;
1105 return 0;
1106 }
1107
1108
1109 /* An address is associated with more than one name. Which do we
1110 prefer as the "display" name (that we show the user in stack
1111 traces)? In order:
1112
1113 - Prefer "PMPI_<foo>" over "MPI_<foo>".
1114
1115 - Else, prefer a non-empty name over an empty one.
1116
1117 - Else, prefer a non-whitespace name over an all-whitespace name.
1118
1119 - Else, prefer the shorter symbol name. If the symbol contains a
1120 version symbol ('@' on Linux, other platforms may differ), which means it
1121 is versioned, then the length up to the version symbol is used for length
1122 comparison purposes (so "foo@GLIBC_2.4.2" is considered shorter than
1123 "foobar").
1124
1125 - Else, if two symbols have the same length, prefer a versioned symbol over
1126 a non-versioned symbol.
1127
1128 - Else, use alphabetical ordering.
1129
1130 - Otherwise, they must be the same; use the name with the lower address.
1131
1132 Very occasionally this goes wrong (eg. 'memcmp' and 'bcmp' are
1133 aliases in glibc, we choose the 'bcmp' symbol because it's shorter,
1134 so we can misdescribe memcmp() as bcmp()). This is hard to avoid.
1135 It's mentioned in the FAQ file.
1136
1137 Returned value is True if a_name is preferred, False if b_name is
1138 preferred.
1139 */
1140 static
preferName(struct _DebugInfo * di,UChar * a_name,UChar * b_name,Addr sym_avma)1141 Bool preferName ( struct _DebugInfo* di,
1142 UChar* a_name, UChar* b_name,
1143 Addr sym_avma/*exposition only*/ )
1144 {
1145 Word cmp;
1146 Word vlena, vlenb; /* length without version */
1147 const UChar *vpa, *vpb;
1148
1149 Bool preferA = False;
1150 Bool preferB = False;
1151
1152 vg_assert(a_name);
1153 vg_assert(b_name);
1154 vg_assert(a_name != b_name);
1155
1156 vlena = VG_(strlen)(a_name);
1157 vlenb = VG_(strlen)(b_name);
1158
1159 # if defined(VGO_linux)
1160 # define VERSION_CHAR '@'
1161 # elif defined(VGO_darwin)
1162 # define VERSION_CHAR '$'
1163 # else
1164 # error Unknown OS
1165 # endif
1166
1167 vpa = VG_(strchr)(a_name, VERSION_CHAR);
1168 vpb = VG_(strchr)(b_name, VERSION_CHAR);
1169
1170 # undef VERSION_CHAR
1171
1172 if (vpa)
1173 vlena = vpa - a_name;
1174 if (vpb)
1175 vlenb = vpb - b_name;
1176
1177 /* MPI hack: prefer PMPI_Foo over MPI_Foo */
1178 if (0==VG_(strncmp)(a_name, "MPI_", 4)
1179 && 0==VG_(strncmp)(b_name, "PMPI_", 5)
1180 && 0==VG_(strcmp)(a_name, 1+b_name)) {
1181 preferB = True; goto out;
1182 }
1183 if (0==VG_(strncmp)(b_name, "MPI_", 4)
1184 && 0==VG_(strncmp)(a_name, "PMPI_", 5)
1185 && 0==VG_(strcmp)(b_name, 1+a_name)) {
1186 preferA = True; goto out;
1187 }
1188
1189 /* Prefer non-empty name. */
1190 if (vlena && !vlenb) {
1191 preferA = True; goto out;
1192 }
1193 if (vlenb && !vlena) {
1194 preferB = True; goto out;
1195 }
1196
1197 /* Prefer non-whitespace name. */
1198 {
1199 Bool blankA = True;
1200 Bool blankB = True;
1201 Char *s;
1202 s = a_name;
1203 while (*s) {
1204 if (!VG_(isspace)(*s++)) {
1205 blankA = False;
1206 break;
1207 }
1208 }
1209 s = b_name;
1210 while (*s) {
1211 if (!VG_(isspace)(*s++)) {
1212 blankB = False;
1213 break;
1214 }
1215 }
1216
1217 if (!blankA && blankB) {
1218 preferA = True; goto out;
1219 }
1220 if (!blankB && blankA) {
1221 preferB = True; goto out;
1222 }
1223 }
1224
1225 /* Select the shortest unversioned name */
1226 if (vlena < vlenb) {
1227 preferA = True; goto out;
1228 }
1229 if (vlenb < vlena) {
1230 preferB = True; goto out;
1231 }
1232
1233 /* Equal lengths; select the versioned name */
1234 if (vpa && !vpb) {
1235 preferA = True; goto out;
1236 }
1237 if (vpb && !vpa) {
1238 preferB = True; goto out;
1239 }
1240
1241 /* Either both versioned or neither is versioned; select them
1242 alphabetically */
1243 cmp = VG_(strcmp)(a_name, b_name);
1244 if (cmp < 0) {
1245 preferA = True; goto out;
1246 }
1247 if (cmp > 0) {
1248 preferB = True; goto out;
1249 }
1250
1251 /* If we get here, they are the same name. */
1252
1253 /* In this case we could choose either (arbitrarily), but might as
1254 well choose the one with the lowest DiSym* address, so as to try
1255 and make the comparison mechanism more stable (a la sorting
1256 parlance). Also, skip the diagnostic printing in this case. */
1257 return a_name <= b_name ? True : False;
1258
1259 /*NOTREACHED*/
1260 vg_assert(0);
1261 out:
1262 if (preferA && !preferB) {
1263 TRACE_SYMTAB("sym at %#lx: prefer '%s' to '%s'\n",
1264 sym_avma, a_name, b_name );
1265 return True;
1266 }
1267 if (preferB && !preferA) {
1268 TRACE_SYMTAB("sym at %#lx: prefer '%s' to '%s'\n",
1269 sym_avma, b_name, a_name );
1270 return False;
1271 }
1272 /*NOTREACHED*/
1273 vg_assert(0);
1274 }
1275
1276
1277 /* Add the names in FROM to the names in TO. */
1278 static
add_DiSym_names_to_from(DebugInfo * di,DiSym * to,DiSym * from)1279 void add_DiSym_names_to_from ( DebugInfo* di, DiSym* to, DiSym* from )
1280 {
1281 vg_assert(to->pri_name);
1282 vg_assert(from->pri_name);
1283 /* Figure out how many names there will be in the new combined
1284 secondary vector. */
1285 UChar** to_sec = to->sec_names;
1286 UChar** from_sec = from->sec_names;
1287 Word n_new_sec = 1;
1288 if (from_sec) {
1289 while (*from_sec) {
1290 n_new_sec++;
1291 from_sec++;
1292 }
1293 }
1294 if (to_sec) {
1295 while (*to_sec) {
1296 n_new_sec++;
1297 to_sec++;
1298 }
1299 }
1300 if (0)
1301 TRACE_SYMTAB("merge: -> %ld\n", n_new_sec);
1302 /* Create the new sec and copy stuff into it, putting the new
1303 entries at the end. */
1304 UChar** new_sec = ML_(dinfo_zalloc)( "di.storage.aDntf.1",
1305 (n_new_sec+1) * sizeof(UChar*) );
1306 from_sec = from->sec_names;
1307 to_sec = to->sec_names;
1308 Word i = 0;
1309 if (to_sec) {
1310 while (*to_sec) {
1311 new_sec[i++] = *to_sec;
1312 to_sec++;
1313 }
1314 }
1315 new_sec[i++] = from->pri_name;
1316 if (from_sec) {
1317 while (*from_sec) {
1318 new_sec[i++] = *from_sec;
1319 from_sec++;
1320 }
1321 }
1322 vg_assert(i == n_new_sec);
1323 vg_assert(new_sec[i] == NULL);
1324 /* If we're replacing an existing secondary vector, free it. */
1325 if (to->sec_names) {
1326 ML_(dinfo_free)(to->sec_names);
1327 }
1328 to->sec_names = new_sec;
1329 }
1330
1331
canonicaliseSymtab(struct _DebugInfo * di)1332 static void canonicaliseSymtab ( struct _DebugInfo* di )
1333 {
1334 Word i, j, n_truncated;
1335 Addr sta1, sta2, end1, end2, toc1, toc2;
1336 UChar *pri1, *pri2, **sec1, **sec2;
1337 Bool ist1, ist2, isf1, isf2;
1338
1339 # define SWAP(ty,aa,bb) \
1340 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0)
1341
1342 if (di->symtab_used == 0)
1343 return;
1344
1345 /* Check initial invariants */
1346 for (i = 0; i < di->symtab_used; i++) {
1347 DiSym* sym = &di->symtab[i];
1348 vg_assert(sym->pri_name);
1349 vg_assert(!sym->sec_names);
1350 }
1351
1352 /* Sort by address. */
1353 VG_(ssort)(di->symtab, di->symtab_used,
1354 sizeof(*di->symtab), compare_DiSym);
1355
1356 cleanup_more:
1357
1358 /* If two symbols have identical address ranges, and agree on
1359 .isText and .isIFunc, merge them into a single entry, but
1360 preserve both names, so we end up knowing all the names for that
1361 particular address range. */
1362 while (1) {
1363 Word r, w, n_merged;
1364 n_merged = 0;
1365 w = 0;
1366 /* A pass merging entries together */
1367 for (r = 1; r < di->symtab_used; r++) {
1368 vg_assert(w < r);
1369 if ( di->symtab[w].addr == di->symtab[r].addr
1370 && di->symtab[w].size == di->symtab[r].size
1371 && !!di->symtab[w].isText == !!di->symtab[r].isText
1372 && !!di->symtab[w].isIFunc == !!di->symtab[r].isIFunc) {
1373 /* merge the two into one */
1374 n_merged++;
1375 add_DiSym_names_to_from(di, &di->symtab[w], &di->symtab[r]);
1376 /* and use ::pri_names to indicate this slot is no longer in use */
1377 di->symtab[r].pri_name = NULL;
1378 if (di->symtab[r].sec_names) {
1379 ML_(dinfo_free)(di->symtab[r].sec_names);
1380 di->symtab[r].sec_names = NULL;
1381 }
1382 /* Completely zap the entry -- paranoia to make it more
1383 likely we'll notice if we inadvertantly use it
1384 again. */
1385 VG_(memset)(&di->symtab[r], 0, sizeof(DiSym));
1386 } else {
1387 w = r;
1388 }
1389 }
1390 TRACE_SYMTAB( "canonicaliseSymtab: %ld symbols merged\n", n_merged);
1391 if (n_merged == 0)
1392 break;
1393 /* Now a pass to squeeze out any unused ones */
1394 w = 0;
1395 for (r = 0; r < di->symtab_used; r++) {
1396 vg_assert(w <= r);
1397 if (di->symtab[r].pri_name == NULL)
1398 continue;
1399 if (w < r) {
1400 di->symtab[w] = di->symtab[r];
1401 }
1402 w++;
1403 }
1404 vg_assert(w + n_merged == di->symtab_used);
1405 di->symtab_used = w;
1406 }
1407
1408 /* Detect and "fix" overlapping address ranges. */
1409 n_truncated = 0;
1410
1411 for (i = 0; i < ((Word)di->symtab_used) -1; i++) {
1412
1413 vg_assert(di->symtab[i].addr <= di->symtab[i+1].addr);
1414
1415 /* Check for common (no overlap) case. */
1416 if (di->symtab[i].addr + di->symtab[i].size
1417 <= di->symtab[i+1].addr)
1418 continue;
1419
1420 /* There's an overlap. Truncate one or the other. */
1421 if (di->trace_symtab) {
1422 VG_(printf)("overlapping address ranges in symbol table\n\t");
1423 ML_(ppSym)( i, &di->symtab[i] );
1424 VG_(printf)("\t");
1425 ML_(ppSym)( i+1, &di->symtab[i+1] );
1426 VG_(printf)("\n");
1427 }
1428
1429 /* Truncate one or the other. */
1430 sta1 = di->symtab[i].addr;
1431 end1 = sta1 + di->symtab[i].size - 1;
1432 toc1 = di->symtab[i].tocptr;
1433 pri1 = di->symtab[i].pri_name;
1434 sec1 = di->symtab[i].sec_names;
1435 ist1 = di->symtab[i].isText;
1436 isf1 = di->symtab[i].isIFunc;
1437
1438 sta2 = di->symtab[i+1].addr;
1439 end2 = sta2 + di->symtab[i+1].size - 1;
1440 toc2 = di->symtab[i+1].tocptr;
1441 pri2 = di->symtab[i+1].pri_name;
1442 sec2 = di->symtab[i+1].sec_names;
1443 ist2 = di->symtab[i+1].isText;
1444 isf2 = di->symtab[i+1].isIFunc;
1445
1446 if (sta1 < sta2) {
1447 end1 = sta2 - 1;
1448 } else {
1449 vg_assert(sta1 == sta2);
1450 if (end1 > end2) {
1451 sta1 = end2 + 1;
1452 SWAP(Addr,sta1,sta2); SWAP(Addr,end1,end2); SWAP(Addr,toc1,toc2);
1453 SWAP(UChar*,pri1,pri2); SWAP(UChar**,sec1,sec2);
1454 SWAP(Bool,ist1,ist2); SWAP(Bool,isf1,isf2);
1455 } else
1456 if (end1 < end2) {
1457 sta2 = end1 + 1;
1458 } else {
1459 /* end1 == end2. Identical addr ranges. We'll eventually wind
1460 up back at cleanup_more, which will take care of it. */
1461 }
1462 }
1463 di->symtab[i].addr = sta1;
1464 di->symtab[i].size = end1 - sta1 + 1;
1465 di->symtab[i].tocptr = toc1;
1466 di->symtab[i].pri_name = pri1;
1467 di->symtab[i].sec_names = sec1;
1468 di->symtab[i].isText = ist1;
1469 di->symtab[i].isIFunc = isf1;
1470
1471 di->symtab[i+1].addr = sta2;
1472 di->symtab[i+1].size = end2 - sta2 + 1;
1473 di->symtab[i+1].tocptr = toc2;
1474 di->symtab[i+1].pri_name = pri2;
1475 di->symtab[i+1].sec_names = sec2;
1476 di->symtab[i+1].isText = ist2;
1477 di->symtab[i+1].isIFunc = isf2;
1478
1479 vg_assert(sta1 <= sta2);
1480 vg_assert(di->symtab[i].size > 0);
1481 vg_assert(di->symtab[i+1].size > 0);
1482 /* It may be that the i+1 entry now needs to be moved further
1483 along to maintain the address order requirement. */
1484 j = i+1;
1485 while (j < ((Word)di->symtab_used)-1
1486 && di->symtab[j].addr > di->symtab[j+1].addr) {
1487 SWAP(DiSym,di->symtab[j],di->symtab[j+1]);
1488 j++;
1489 }
1490 n_truncated++;
1491 }
1492
1493 if (n_truncated > 0) goto cleanup_more;
1494
1495 /* Ensure relevant postconditions hold. */
1496 for (i = 0; i < ((Word)di->symtab_used)-1; i++) {
1497 /* No zero-sized symbols. */
1498 vg_assert(di->symtab[i].size > 0);
1499 /* In order. */
1500 vg_assert(di->symtab[i].addr < di->symtab[i+1].addr);
1501 /* No overlaps. */
1502 vg_assert(di->symtab[i].addr + di->symtab[i].size - 1
1503 < di->symtab[i+1].addr);
1504 /* Names are sane(ish) */
1505 vg_assert(di->symtab[i].pri_name);
1506 if (di->symtab[i].sec_names) {
1507 vg_assert(di->symtab[i].sec_names[0]);
1508 }
1509 }
1510
1511 /* For each symbol that has more than one name, use preferName to
1512 select the primary name. This is a complete kludge in that
1513 doing it properly requires making a total ordering on the
1514 candidate names, whilst what we have to work with is an ad-hoc
1515 binary relation (preferName) that certainly doesn't have the
1516 relevant transitivity etc properties that are needed to induce a
1517 legitimate total order. Doesn't matter though if it doesn't
1518 always work right since this is only used to generate names to
1519 show the user. */
1520 for (i = 0; i < ((Word)di->symtab_used)-1; i++) {
1521 DiSym* sym = &di->symtab[i];
1522 UChar** sec = sym->sec_names;
1523 if (!sec)
1524 continue;
1525 /* Slow but simple. Copy all the cands into a temp array,
1526 choose the primary name, and copy them all back again. */
1527 Word n_tmp = 1;
1528 while (*sec) { n_tmp++; sec++; }
1529 j = 0;
1530 UChar** tmp = ML_(dinfo_zalloc)( "di.storage.cS.1",
1531 (n_tmp+1) * sizeof(UChar*) );
1532 tmp[j++] = sym->pri_name;
1533 sec = sym->sec_names;
1534 while (*sec) { tmp[j++] = *sec; sec++; }
1535 vg_assert(j == n_tmp);
1536 vg_assert(tmp[n_tmp] == NULL); /* because of zalloc */
1537 /* Choose the most favoured. */
1538 Word best = 0;
1539 for (j = 1; j < n_tmp; j++) {
1540 if (preferName(di, tmp[best], tmp[j], di->symtab[i].addr)) {
1541 /* best is unchanged */
1542 } else {
1543 best = j;
1544 }
1545 }
1546 vg_assert(best >= 0 && best < n_tmp);
1547 /* Copy back */
1548 sym->pri_name = tmp[best];
1549 UChar** cursor = sym->sec_names;
1550 for (j = 0; j < n_tmp; j++) {
1551 if (j == best)
1552 continue;
1553 *cursor = tmp[j];
1554 cursor++;
1555 }
1556 vg_assert(*cursor == NULL);
1557 ML_(dinfo_free)( tmp );
1558 }
1559
1560 # undef SWAP
1561 }
1562
1563
1564 /* Sort the location table by starting address. Mash the table around
1565 so as to establish the property that addresses are in order and the
1566 ranges do not overlap. This facilitates using binary search to map
1567 addresses to locations when we come to query the table.
1568 */
compare_DiLoc(void * va,void * vb)1569 static Int compare_DiLoc ( void* va, void* vb )
1570 {
1571 DiLoc* a = (DiLoc*)va;
1572 DiLoc* b = (DiLoc*)vb;
1573 if (a->addr < b->addr) return -1;
1574 if (a->addr > b->addr) return 1;
1575 return 0;
1576 }
1577
canonicaliseLoctab(struct _DebugInfo * di)1578 static void canonicaliseLoctab ( struct _DebugInfo* di )
1579 {
1580 Word i, j;
1581
1582 # define SWAP(ty,aa,bb) \
1583 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0);
1584
1585 if (di->loctab_used == 0)
1586 return;
1587
1588 /* Sort by start address. */
1589 VG_(ssort)(di->loctab, di->loctab_used,
1590 sizeof(*di->loctab), compare_DiLoc);
1591
1592 /* If two adjacent entries overlap, truncate the first. */
1593 for (i = 0; i < ((Word)di->loctab_used)-1; i++) {
1594 vg_assert(di->loctab[i].size < 10000);
1595 if (di->loctab[i].addr + di->loctab[i].size > di->loctab[i+1].addr) {
1596 /* Do this in signed int32 because the actual .size fields
1597 are only 12 bits. */
1598 Int new_size = di->loctab[i+1].addr - di->loctab[i].addr;
1599 if (new_size < 0) {
1600 di->loctab[i].size = 0;
1601 } else
1602 if (new_size > MAX_LOC_SIZE) {
1603 di->loctab[i].size = MAX_LOC_SIZE;
1604 } else {
1605 di->loctab[i].size = (UShort)new_size;
1606 }
1607 }
1608 }
1609
1610 /* Zap any zero-sized entries resulting from the truncation
1611 process. */
1612 j = 0;
1613 for (i = 0; i < (Word)di->loctab_used; i++) {
1614 if (di->loctab[i].size > 0) {
1615 if (j != i)
1616 di->loctab[j] = di->loctab[i];
1617 j++;
1618 }
1619 }
1620 di->loctab_used = j;
1621
1622 /* Ensure relevant postconditions hold. */
1623 for (i = 0; i < ((Word)di->loctab_used)-1; i++) {
1624 /*
1625 VG_(printf)("%d (%d) %d 0x%x\n",
1626 i, di->loctab[i+1].confident,
1627 di->loctab[i+1].size, di->loctab[i+1].addr );
1628 */
1629 /* No zero-sized symbols. */
1630 vg_assert(di->loctab[i].size > 0);
1631 /* In order. */
1632 vg_assert(di->loctab[i].addr < di->loctab[i+1].addr);
1633 /* No overlaps. */
1634 vg_assert(di->loctab[i].addr + di->loctab[i].size - 1
1635 < di->loctab[i+1].addr);
1636 }
1637 # undef SWAP
1638
1639 /* Free up unused space at the end of the table. */
1640 shrinkLocTab(di);
1641 }
1642
1643
1644 /* Sort the call-frame-info table by starting address. Mash the table
1645 around so as to establish the property that addresses are in order
1646 and the ranges do not overlap. This facilitates using binary
1647 search to map addresses to locations when we come to query the
1648 table.
1649
1650 Also, set cfisi_minaddr and cfisi_maxaddr to be the min and max of
1651 any of the address ranges contained in cfisi[0 .. cfisi_used-1], so
1652 as to facilitate rapidly skipping this SegInfo when looking for an
1653 address which falls outside that range.
1654 */
compare_DiCfSI(void * va,void * vb)1655 static Int compare_DiCfSI ( void* va, void* vb )
1656 {
1657 DiCfSI* a = (DiCfSI*)va;
1658 DiCfSI* b = (DiCfSI*)vb;
1659 if (a->base < b->base) return -1;
1660 if (a->base > b->base) return 1;
1661 return 0;
1662 }
1663
ML_(canonicaliseCFI)1664 void ML_(canonicaliseCFI) ( struct _DebugInfo* di )
1665 {
1666 Word i, j;
1667 const Addr minAvma = 0;
1668 const Addr maxAvma = ~minAvma;
1669
1670 /* Note: take care in here. di->cfsi can be NULL, in which
1671 case _used and _size fields will be zero. */
1672 if (di->cfsi == NULL) {
1673 vg_assert(di->cfsi_used == 0);
1674 vg_assert(di->cfsi_size == 0);
1675 }
1676
1677 /* Set cfsi_minavma and cfsi_maxavma to summarise the entire
1678 address range contained in cfsi[0 .. cfsi_used-1]. */
1679 di->cfsi_minavma = maxAvma;
1680 di->cfsi_maxavma = minAvma;
1681 for (i = 0; i < (Word)di->cfsi_used; i++) {
1682 Addr here_min = di->cfsi[i].base;
1683 Addr here_max = di->cfsi[i].base + di->cfsi[i].len - 1;
1684 if (here_min < di->cfsi_minavma)
1685 di->cfsi_minavma = here_min;
1686 if (here_max > di->cfsi_maxavma)
1687 di->cfsi_maxavma = here_max;
1688 }
1689
1690 if (di->trace_cfi)
1691 VG_(printf)("canonicaliseCfiSI: %ld entries, %#lx .. %#lx\n",
1692 di->cfsi_used,
1693 di->cfsi_minavma, di->cfsi_maxavma);
1694
1695 /* Sort the cfsi array by base address. */
1696 VG_(ssort)(di->cfsi, di->cfsi_used, sizeof(*di->cfsi), compare_DiCfSI);
1697
1698 /* If two adjacent entries overlap, truncate the first. */
1699 for (i = 0; i < (Word)di->cfsi_used-1; i++) {
1700 if (di->cfsi[i].base + di->cfsi[i].len > di->cfsi[i+1].base) {
1701 Word new_len = di->cfsi[i+1].base - di->cfsi[i].base;
1702 /* how could it be otherwise? The entries are sorted by the
1703 .base field. */
1704 vg_assert(new_len >= 0);
1705 vg_assert(new_len <= di->cfsi[i].len);
1706 di->cfsi[i].len = new_len;
1707 }
1708 }
1709
1710 /* Zap any zero-sized entries resulting from the truncation
1711 process. */
1712 j = 0;
1713 for (i = 0; i < (Word)di->cfsi_used; i++) {
1714 if (di->cfsi[i].len > 0) {
1715 if (j != i)
1716 di->cfsi[j] = di->cfsi[i];
1717 j++;
1718 }
1719 }
1720 /* VG_(printf)("XXXXXXXXXXXXX %d %d\n", di->cfsi_used, j); */
1721 di->cfsi_used = j;
1722
1723 /* Ensure relevant postconditions hold. */
1724 for (i = 0; i < (Word)di->cfsi_used; i++) {
1725 /* No zero-length ranges. */
1726 vg_assert(di->cfsi[i].len > 0);
1727 /* Makes sense w.r.t. summary address range */
1728 vg_assert(di->cfsi[i].base >= di->cfsi_minavma);
1729 vg_assert(di->cfsi[i].base + di->cfsi[i].len - 1
1730 <= di->cfsi_maxavma);
1731
1732 if (i < di->cfsi_used - 1) {
1733 /*
1734 if (!(di->cfsi[i].base < di->cfsi[i+1].base)) {
1735 VG_(printf)("\nOOO cfsis:\n");
1736 ML_(ppCfiSI)(&di->cfsi[i]);
1737 ML_(ppCfiSI)(&di->cfsi[i+1]);
1738 }
1739 */
1740 /* In order. */
1741 vg_assert(di->cfsi[i].base < di->cfsi[i+1].base);
1742 /* No overlaps. */
1743 vg_assert(di->cfsi[i].base + di->cfsi[i].len - 1
1744 < di->cfsi[i+1].base);
1745 }
1746 }
1747
1748 }
1749
1750
1751 /* Canonicalise the tables held by 'di', in preparation for use. Call
1752 this after finishing adding entries to these tables. */
ML_(canonicaliseTables)1753 void ML_(canonicaliseTables) ( struct _DebugInfo* di )
1754 {
1755 canonicaliseSymtab ( di );
1756 canonicaliseLoctab ( di );
1757 ML_(canonicaliseCFI) ( di );
1758 canonicaliseVarInfo ( di );
1759 }
1760
1761
1762 /*------------------------------------------------------------*/
1763 /*--- Searching the tables ---*/
1764 /*------------------------------------------------------------*/
1765
1766 /* Find a symbol-table index containing the specified pointer, or -1
1767 if not found. Binary search. */
1768
ML_(search_one_symtab)1769 Word ML_(search_one_symtab) ( struct _DebugInfo* di, Addr ptr,
1770 Bool match_anywhere_in_sym,
1771 Bool findText )
1772 {
1773 Addr a_mid_lo, a_mid_hi;
1774 Word mid, size,
1775 lo = 0,
1776 hi = di->symtab_used-1;
1777 while (True) {
1778 /* current unsearched space is from lo to hi, inclusive. */
1779 if (lo > hi) return -1; /* not found */
1780 mid = (lo + hi) / 2;
1781 a_mid_lo = di->symtab[mid].addr;
1782 size = ( match_anywhere_in_sym
1783 ? di->symtab[mid].size
1784 : 1);
1785 a_mid_hi = ((Addr)di->symtab[mid].addr) + size - 1;
1786
1787 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1788 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1789 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1790 /* Found a symbol with the correct address range. But is it
1791 of the right kind (text vs data) ? */
1792 if ( findText && di->symtab[mid].isText ) return mid;
1793 if ( (!findText) && (!di->symtab[mid].isText) ) return mid;
1794 return -1;
1795 }
1796 }
1797
1798
1799 /* Find a location-table index containing the specified pointer, or -1
1800 if not found. Binary search. */
1801
ML_(search_one_loctab)1802 Word ML_(search_one_loctab) ( struct _DebugInfo* di, Addr ptr )
1803 {
1804 Addr a_mid_lo, a_mid_hi;
1805 Word mid,
1806 lo = 0,
1807 hi = di->loctab_used-1;
1808 while (True) {
1809 /* current unsearched space is from lo to hi, inclusive. */
1810 if (lo > hi) return -1; /* not found */
1811 mid = (lo + hi) / 2;
1812 a_mid_lo = di->loctab[mid].addr;
1813 a_mid_hi = ((Addr)di->loctab[mid].addr) + di->loctab[mid].size - 1;
1814
1815 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1816 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1817 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1818 return mid;
1819 }
1820 }
1821
1822
1823 /* Find a CFI-table index containing the specified pointer, or -1
1824 if not found. Binary search. */
1825
ML_(search_one_cfitab)1826 Word ML_(search_one_cfitab) ( struct _DebugInfo* di, Addr ptr )
1827 {
1828 Addr a_mid_lo, a_mid_hi;
1829 Word mid, size,
1830 lo = 0,
1831 hi = di->cfsi_used-1;
1832 while (True) {
1833 /* current unsearched space is from lo to hi, inclusive. */
1834 if (lo > hi) return -1; /* not found */
1835 mid = (lo + hi) / 2;
1836 a_mid_lo = di->cfsi[mid].base;
1837 size = di->cfsi[mid].len;
1838 a_mid_hi = a_mid_lo + size - 1;
1839 vg_assert(a_mid_hi >= a_mid_lo);
1840 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1841 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1842 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1843 return mid;
1844 }
1845 }
1846
1847
1848 /* Find a FPO-table index containing the specified pointer, or -1
1849 if not found. Binary search. */
1850
ML_(search_one_fpotab)1851 Word ML_(search_one_fpotab) ( struct _DebugInfo* di, Addr ptr )
1852 {
1853 Addr const addr = ptr - di->fsm.rx_map_avma;
1854 Addr a_mid_lo, a_mid_hi;
1855 Word mid, size,
1856 lo = 0,
1857 hi = di->fpo_size-1;
1858 while (True) {
1859 /* current unsearched space is from lo to hi, inclusive. */
1860 if (lo > hi) return -1; /* not found */
1861 mid = (lo + hi) / 2;
1862 a_mid_lo = di->fpo[mid].ulOffStart;
1863 size = di->fpo[mid].cbProcSize;
1864 a_mid_hi = a_mid_lo + size - 1;
1865 vg_assert(a_mid_hi >= a_mid_lo);
1866 if (addr < a_mid_lo) { hi = mid-1; continue; }
1867 if (addr > a_mid_hi) { lo = mid+1; continue; }
1868 vg_assert(addr >= a_mid_lo && addr <= a_mid_hi);
1869 return mid;
1870 }
1871 }
1872
1873 /*--------------------------------------------------------------------*/
1874 /*--- end ---*/
1875 /*--------------------------------------------------------------------*/
1876