• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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