1eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Format-neutral storage of and querying of info acquired from ---*/
472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/*--- ELF/XCOFF stabs/dwarf1/dwarf2/dwarf3 debug info.             ---*/
5eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                    storage.c ---*/
6eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
7eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*
9eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This file is part of Valgrind, a dynamic binary instrumentation
10eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   framework.
11eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
120f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj   Copyright (C) 2000-2013 Julian Seward
13eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      jseward@acm.org
14eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
15eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is free software; you can redistribute it and/or
16eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   modify it under the terms of the GNU General Public License as
17eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   published by the Free Software Foundation; either version 2 of the
18eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   License, or (at your option) any later version.
19eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
20eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is distributed in the hope that it will be useful, but
21eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
22eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   General Public License for more details.
24eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   You should have received a copy of the GNU General Public License
26eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   along with this program; if not, write to the Free Software
27eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   02111-1307, USA.
29eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
30eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   The GNU General Public License is contained in the file COPYING.
31eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
32eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
33eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This file manages the data structures built by the debuginfo
34eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   system.  These are: the top level SegInfo list.  For each SegInfo,
35eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   there are tables for for address-to-symbol mappings,
36eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   address-to-src-file/line mappings, and address-to-CFI-info
37eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   mappings.
38eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
39eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
40eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_basics.h"
41eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_options.h"      /* VG_(clo_verbosity) */
42588658b13b5ad77672f323d48fe9da0ca60b0bcbtom#include "pub_core_debuginfo.h"
435c3dba227192de63d86f65ec7d9597c132818c37philippe#include "pub_core_debuglog.h"
44eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcassert.h"
45eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcbase.h"
46eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcprint.h"
4772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj#include "pub_core_xarray.h"
48b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_oset.h"
497293d2530f8c60c1060f9f003e214cc341d35266philippe#include "pub_core_deduppoolalloc.h"
50b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
51b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_misc.h"         /* dinfo_zalloc/free/strdup */
525d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj#include "priv_image.h"
53b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_d3basics.h"     /* ML_(pp_GX) */
54b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_tytypes.h"
55b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_storage.h"      /* self */
56eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
57eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
58eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
59eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Misc (printing, errors)                              ---*/
60eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
61eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
62205a42f1b48012de8b9633982d3a2d21cb26e006florian/* Show a non-fatal debug info reading error.  Use VG_(core_panic) for
63205a42f1b48012de8b9633982d3a2d21cb26e006florian   fatal errors.  'serious' errors are shown regardless of the
64b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   verbosity setting. */
65518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid ML_(symerr) ( const DebugInfo* di, Bool serious, const HChar* msg )
66eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
67b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* XML mode hides everything :-( */
68b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (VG_(clo_xml))
69b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
70b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
71b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (serious) {
72b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
73b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(message)(Vg_DebugMsg, "WARNING: Serious error when "
74738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                                "reading debug info\n");
75b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (True || VG_(clo_verbosity) < 2) {
76b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Need to show what the file name is, at verbosity levels 2
77b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            or below, since that won't already have been shown */
78b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(message)(Vg_DebugMsg,
79738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                      "When reading debug info from %s:\n",
80a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                      (di && di->fsm.filename) ? di->fsm.filename
811636d33c13958b9c0e7d3059cdd5005746418eb2florian                                               : "???");
82b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
83738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_DebugMsg, "%s\n", msg);
84b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
85b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else { /* !serious */
86b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
87b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(clo_verbosity) >= 2)
88738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_DebugMsg, "%s\n", msg);
89b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
90b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
91eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
92eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
93b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
94eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Print a symbol. */
95518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid ML_(ppSym) ( Int idx, const DiSym* sym )
96eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
971ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian   const HChar** sec_names = sym->sec_names;
98a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(sym->pri_name);
99a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (sec_names)
100a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vg_assert(sec_names);
1017cf235b7622757d6a29b9a61d9698f7eda9d1ed1sewardj   VG_(printf)( "%5d:  %c%c %#8lx .. %#8lx (%d)      %s%s",
102738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                idx,
1037cf235b7622757d6a29b9a61d9698f7eda9d1ed1sewardj                sym->isText ? 'T' : '-',
1047cf235b7622757d6a29b9a61d9698f7eda9d1ed1sewardj                sym->isIFunc ? 'I' : '-',
1054cace66777ca9ee73ea156210c04e9d4cc178395philippe                sym->avmas.main,
1064cace66777ca9ee73ea156210c04e9d4cc178395philippe                sym->avmas.main + sym->size - 1, sym->size,
107a5cace0c2a3e212931badbf6398a0cd98393121asewardj                sym->pri_name, sec_names ? " " : "" );
108a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (sec_names) {
109a5cace0c2a3e212931badbf6398a0cd98393121asewardj      while (*sec_names) {
110a5cace0c2a3e212931badbf6398a0cd98393121asewardj         VG_(printf)("%s%s", *sec_names, *(sec_names+1) ? " " : "");
111a5cace0c2a3e212931badbf6398a0cd98393121asewardj         sec_names++;
112a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
113a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
114a5cace0c2a3e212931badbf6398a0cd98393121asewardj   VG_(printf)("\n");
115eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
116eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
117eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Print a call-frame-info summary. */
118518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid ML_(ppDiCfSI) ( const XArray* /* of CfiExpr */ exprs,
1195c3dba227192de63d86f65ec7d9597c132818c37philippe                     Addr base, UInt len,
120518850bf0da07ed3e2244e307268ae0fd80e93a8florian                     const DiCfSI_m* si_m )
121eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
122eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define SHOW_HOW(_how, _off)                   \
123eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                       \
124eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (_how == CFIR_UNKNOWN) {             \
125eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(printf)("Unknown");              \
126eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         } else                                  \
127eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (_how == CFIR_SAME) {                \
128eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(printf)("Same");                 \
129eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         } else                                  \
130eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (_how == CFIR_CFAREL) {              \
131eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(printf)("cfa+%d", _off);         \
132eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         } else                                  \
133eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (_how == CFIR_MEMCFAREL) {           \
134eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(printf)("*(cfa+%d)", _off);      \
13572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         } else                                  \
13672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (_how == CFIR_EXPR) {                \
13772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            VG_(printf)("{");                    \
13872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            ML_(ppCfiExpr)(exprs, _off);         \
13972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            VG_(printf)("}");                    \
140eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         } else {                                \
14172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            vg_assert(0+0);                      \
142eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                       \
143eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
144eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1455c3dba227192de63d86f65ec7d9597c132818c37philippe   VG_(printf)("[%#lx .. %#lx]: ", base,
1465c3dba227192de63d86f65ec7d9597c132818c37philippe                                   base + (UWord)len - 1);
1475c3dba227192de63d86f65ec7d9597c132818c37philippe   switch (si_m->cfa_how) {
1483026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_SPREL:
1495c3dba227192de63d86f65ec7d9597c132818c37philippe         VG_(printf)("let cfa=oldSP+%d", si_m->cfa_off);
15072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
1513026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_BPREL:
1525c3dba227192de63d86f65ec7d9597c132818c37philippe         VG_(printf)("let cfa=oldBP+%d", si_m->cfa_off);
1533026f71684a930286186aa10fef266c304672e8fsewardj         break;
1543026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R13REL:
1555c3dba227192de63d86f65ec7d9597c132818c37philippe         VG_(printf)("let cfa=oldR13+%d", si_m->cfa_off);
1563026f71684a930286186aa10fef266c304672e8fsewardj         break;
1573026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R12REL:
1585c3dba227192de63d86f65ec7d9597c132818c37philippe         VG_(printf)("let cfa=oldR12+%d", si_m->cfa_off);
1593026f71684a930286186aa10fef266c304672e8fsewardj         break;
1603026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R11REL:
1615c3dba227192de63d86f65ec7d9597c132818c37philippe         VG_(printf)("let cfa=oldR11+%d", si_m->cfa_off);
16272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
163b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_SAME:
164b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         VG_(printf)("let cfa=Same");
165b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
166fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj      case CFIC_ARM_R7REL:
1675c3dba227192de63d86f65ec7d9597c132818c37philippe         VG_(printf)("let cfa=oldR7+%d", si_m->cfa_off);
168fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         break;
169821283b2110420321fd3f60afcc799b287788c68sewardj      case CFIC_ARM64_SPREL:
1705c3dba227192de63d86f65ec7d9597c132818c37philippe         VG_(printf)("let cfa=oldSP+%d", si_m->cfa_off);
171821283b2110420321fd3f60afcc799b287788c68sewardj         break;
172821283b2110420321fd3f60afcc799b287788c68sewardj      case CFIC_ARM64_X29REL:
1735c3dba227192de63d86f65ec7d9597c132818c37philippe         VG_(printf)("let cfa=oldX29+%d", si_m->cfa_off);
174821283b2110420321fd3f60afcc799b287788c68sewardj         break;
17572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case CFIC_EXPR:
17672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(printf)("let cfa={");
1775c3dba227192de63d86f65ec7d9597c132818c37philippe         ML_(ppCfiExpr)(exprs, si_m->cfa_off);
17872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(printf)("}");
17972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
18072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
18172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
18272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
18372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
184eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(printf)(" in RA=");
1855c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->ra_how, si_m->ra_off);
1863026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
187eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(printf)(" SP=");
1885c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->sp_how, si_m->sp_off);
1893026f71684a930286186aa10fef266c304672e8fsewardj   VG_(printf)(" BP=");
1905c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->bp_how, si_m->bp_off);
1913026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
1923026f71684a930286186aa10fef266c304672e8fsewardj   VG_(printf)(" R14=");
1935c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->r14_how, si_m->r14_off);
1943026f71684a930286186aa10fef266c304672e8fsewardj   VG_(printf)(" R13=");
1955c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->r13_how, si_m->r13_off);
1963026f71684a930286186aa10fef266c304672e8fsewardj   VG_(printf)(" R12=");
1975c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->r12_how, si_m->r12_off);
1983026f71684a930286186aa10fef266c304672e8fsewardj   VG_(printf)(" R11=");
1995c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->r11_how, si_m->r11_off);
200fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   VG_(printf)(" R7=");
2015c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->r7_how, si_m->r7_off);
202582d58245637ab05272d89fb94b12fd0f18fa0f8carll#  elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
2034df0bfc0614379192c780c944415dc420d9cfe8epetarj#  elif defined(VGA_s390x) || defined(VGA_mips32) || defined(VGA_mips64)
204b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   VG_(printf)(" SP=");
2055c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->sp_how, si_m->sp_off);
206b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   VG_(printf)(" FP=");
2075c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->fp_how, si_m->fp_off);
208f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGA_arm64)
209821283b2110420321fd3f60afcc799b287788c68sewardj   VG_(printf)(" SP=");
2105c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->sp_how, si_m->sp_off);
211821283b2110420321fd3f60afcc799b287788c68sewardj   VG_(printf)(" X30=");
2125c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->x30_how, si_m->x30_off);
213821283b2110420321fd3f60afcc799b287788c68sewardj   VG_(printf)(" X29=");
2145c3dba227192de63d86f65ec7d9597c132818c37philippe   SHOW_HOW(si_m->x29_how, si_m->x29_off);
215112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#  elif defined(VGA_tilegx)
216112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   VG_(printf)(" SP=");
217112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   SHOW_HOW(si_m->sp_how, si_m->sp_off);
218112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   VG_(printf)(" FP=");
219112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   SHOW_HOW(si_m->fp_how, si_m->fp_off);
2203026f71684a930286186aa10fef266c304672e8fsewardj#  else
2213026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
2223026f71684a930286186aa10fef266c304672e8fsewardj#  endif
223eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(printf)("\n");
224eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef SHOW_HOW
225eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
226eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
227eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
228eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
229eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Adding stuff                                         ---*/
230eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
231eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
232eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Add a str to the string table, including terminating zero, and
233eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return pointer to the string in vg_strtab.  Unless it's been seen
234eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   recently, in which case we find the old pointer and return that.
235eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This avoids the most egregious duplications.
236eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
237eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   JSGF: changed from returning an index to a pointer, and changed to
238eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   a chunking memory allocator rather than reallocating, so the
239eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   pointers are stable.
240eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
2411ef70c6f00ab1b50d1936f77037e9923d8ed8c59florianconst HChar* ML_(addStr) ( DebugInfo* di, const HChar* str, Int len )
242eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
243b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len == -1) {
244eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      len = VG_(strlen)(str);
245b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
246b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(len >= 0);
247b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2487293d2530f8c60c1060f9f003e214cc341d35266philippe   if (UNLIKELY(di->strpool == NULL))
2497293d2530f8c60c1060f9f003e214cc341d35266philippe      di->strpool = VG_(newDedupPA)(SEGINFO_STRPOOLSIZE,
2507293d2530f8c60c1060f9f003e214cc341d35266philippe                                    1,
2517293d2530f8c60c1060f9f003e214cc341d35266philippe                                    ML_(dinfo_zalloc),
2527293d2530f8c60c1060f9f003e214cc341d35266philippe                                    "di.storage.addStr.1",
2537293d2530f8c60c1060f9f003e214cc341d35266philippe                                    ML_(dinfo_free));
2541ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian   return VG_(allocEltDedupPA) (di->strpool, len+1, str);
255eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
256eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25759e1f3c79e870a978d24add86db6d8c5450c8b63philippeUInt ML_(addFnDn) (struct _DebugInfo* di,
25859e1f3c79e870a978d24add86db6d8c5450c8b63philippe                   const HChar* filename,
25959e1f3c79e870a978d24add86db6d8c5450c8b63philippe                   const HChar* dirname)
26059e1f3c79e870a978d24add86db6d8c5450c8b63philippe{
26159e1f3c79e870a978d24add86db6d8c5450c8b63philippe   FnDn fndn;
26259e1f3c79e870a978d24add86db6d8c5450c8b63philippe   UInt fndn_ix;
26359e1f3c79e870a978d24add86db6d8c5450c8b63philippe
26459e1f3c79e870a978d24add86db6d8c5450c8b63philippe   if (UNLIKELY(di->fndnpool == NULL))
26559e1f3c79e870a978d24add86db6d8c5450c8b63philippe      di->fndnpool = VG_(newDedupPA)(500,
26659e1f3c79e870a978d24add86db6d8c5450c8b63philippe                                     vg_alignof(FnDn),
26759e1f3c79e870a978d24add86db6d8c5450c8b63philippe                                     ML_(dinfo_zalloc),
26859e1f3c79e870a978d24add86db6d8c5450c8b63philippe                                     "di.storage.addFnDn.1",
26959e1f3c79e870a978d24add86db6d8c5450c8b63philippe                                     ML_(dinfo_free));
27059e1f3c79e870a978d24add86db6d8c5450c8b63philippe   fndn.filename = ML_(addStr)(di, filename, -1);
27159e1f3c79e870a978d24add86db6d8c5450c8b63philippe   fndn.dirname = dirname ? ML_(addStr)(di, dirname, -1) : NULL;
27259e1f3c79e870a978d24add86db6d8c5450c8b63philippe   fndn_ix = VG_(allocFixedEltDedupPA) (di->fndnpool, sizeof(FnDn), &fndn);
27359e1f3c79e870a978d24add86db6d8c5450c8b63philippe   return fndn_ix;
27459e1f3c79e870a978d24add86db6d8c5450c8b63philippe}
275eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
276518850bf0da07ed3e2244e307268ae0fd80e93a8florianconst HChar* ML_(fndn_ix2filename) (const DebugInfo* di,
277666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                                    UInt fndn_ix)
278666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe{
279666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   FnDn *fndn;
280666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   if (fndn_ix == 0)
281666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      return "???";
282666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   else {
283666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      fndn = VG_(indexEltNumber) (di->fndnpool, fndn_ix);
284666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      return fndn->filename;
285666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   }
286666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe}
287666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe
288518850bf0da07ed3e2244e307268ae0fd80e93a8florianconst HChar* ML_(fndn_ix2dirname) (const DebugInfo* di,
289666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                                   UInt fndn_ix)
290666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe{
291666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   FnDn *fndn;
292666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   if (fndn_ix == 0)
293666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      return "";
294666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   else {
295666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      fndn = VG_(indexEltNumber) (di->fndnpool, fndn_ix);
296666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      if (fndn->dirname)
297666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe         return fndn->dirname;
298666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      else
299666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe         return "";
300666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   }
301666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe}
302666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe
3035d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj/* Add a string to the string table of a DebugInfo, by copying the
3045d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj   string from the given DiCursor.  Measures the length of the string
3055d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj   itself. */
3061ef70c6f00ab1b50d1936f77037e9923d8ed8c59florianconst HChar* ML_(addStrFromCursor)( DebugInfo* di, DiCursor c )
3075d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj{
3085d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj   /* This is a less-than-stellar implementation, but it should
3095d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj      work. */
3105d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj   vg_assert(ML_(cur_is_valid)(c));
3115d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj   HChar* str = ML_(cur_read_strdup)(c, "di.addStrFromCursor.1");
3121ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian   const HChar* res = ML_(addStr)(di, str, -1);
3135d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj   ML_(dinfo_free)(str);
3145d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj   return res;
3155d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj}
3165d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj
3175d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj
318a5cace0c2a3e212931badbf6398a0cd98393121asewardj/* Add a symbol to the symbol table, by copying *sym.  'sym' may only
319a5cace0c2a3e212931badbf6398a0cd98393121asewardj   have one name, so there's no complexities to do with deep vs
320a5cace0c2a3e212931badbf6398a0cd98393121asewardj   shallow copying of the sec_name array.  This is checked.
321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjvoid ML_(addSym) ( struct _DebugInfo* di, DiSym* sym )
323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt   new_sz, i;
325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   DiSym* new_tab;
326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
327a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(sym->pri_name != NULL);
328a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(sym->sec_names == NULL);
329a5cace0c2a3e212931badbf6398a0cd98393121asewardj
330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Ignore zero-sized syms. */
331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (sym->size == 0) return;
332eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->symtab_used == di->symtab_size) {
334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      new_sz = 2 * di->symtab_size;
335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (new_sz == 0) new_sz = 500;
3369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      new_tab = ML_(dinfo_zalloc)( "di.storage.addSym.1",
3379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                   new_sz * sizeof(DiSym) );
338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->symtab != NULL) {
339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         for (i = 0; i < di->symtab_used; i++)
340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            new_tab[i] = di->symtab[i];
341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(dinfo_free)(di->symtab);
342eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->symtab = new_tab;
344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->symtab_size = new_sz;
345eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
346eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
347a5cace0c2a3e212931badbf6398a0cd98393121asewardj   di->symtab[di->symtab_used++] = *sym;
348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di->symtab_used <= di->symtab_size);
349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
351518850bf0da07ed3e2244e307268ae0fd80e93a8florianUInt ML_(fndn_ix) (const DebugInfo* di, Word locno)
35259e1f3c79e870a978d24add86db6d8c5450c8b63philippe{
35359e1f3c79e870a978d24add86db6d8c5450c8b63philippe   UInt fndn_ix;
35459e1f3c79e870a978d24add86db6d8c5450c8b63philippe
35559e1f3c79e870a978d24add86db6d8c5450c8b63philippe   switch(di->sizeof_fndn_ix) {
35659e1f3c79e870a978d24add86db6d8c5450c8b63philippe      case 1: fndn_ix = ((UChar*)  di->loctab_fndn_ix)[locno]; break;
35759e1f3c79e870a978d24add86db6d8c5450c8b63philippe      case 2: fndn_ix = ((UShort*) di->loctab_fndn_ix)[locno]; break;
35859e1f3c79e870a978d24add86db6d8c5450c8b63philippe      case 4: fndn_ix = ((UInt*)   di->loctab_fndn_ix)[locno]; break;
35959e1f3c79e870a978d24add86db6d8c5450c8b63philippe      default: vg_assert(0);
36059e1f3c79e870a978d24add86db6d8c5450c8b63philippe   }
36159e1f3c79e870a978d24add86db6d8c5450c8b63philippe   return fndn_ix;
36259e1f3c79e870a978d24add86db6d8c5450c8b63philippe}
36359e1f3c79e870a978d24add86db6d8c5450c8b63philippe
36459e1f3c79e870a978d24add86db6d8c5450c8b63philippestatic inline void set_fndn_ix (struct _DebugInfo* di, Word locno, UInt fndn_ix)
36559e1f3c79e870a978d24add86db6d8c5450c8b63philippe{
36659e1f3c79e870a978d24add86db6d8c5450c8b63philippe   Word i;
36759e1f3c79e870a978d24add86db6d8c5450c8b63philippe
36859e1f3c79e870a978d24add86db6d8c5450c8b63philippe   switch(di->sizeof_fndn_ix) {
36959e1f3c79e870a978d24add86db6d8c5450c8b63philippe      case 1:
37059e1f3c79e870a978d24add86db6d8c5450c8b63philippe         if (LIKELY (fndn_ix <= 255)) {
37159e1f3c79e870a978d24add86db6d8c5450c8b63philippe            ((UChar*) di->loctab_fndn_ix)[locno] = fndn_ix;
37259e1f3c79e870a978d24add86db6d8c5450c8b63philippe            return;
37359e1f3c79e870a978d24add86db6d8c5450c8b63philippe         }
37459e1f3c79e870a978d24add86db6d8c5450c8b63philippe         {
37559e1f3c79e870a978d24add86db6d8c5450c8b63philippe            UChar* old = (UChar*) di->loctab_fndn_ix;
37659e1f3c79e870a978d24add86db6d8c5450c8b63philippe            UShort* new = ML_(dinfo_zalloc)( "di.storage.sfix.1",
37759e1f3c79e870a978d24add86db6d8c5450c8b63philippe                                             di->loctab_size * 2 );
37859e1f3c79e870a978d24add86db6d8c5450c8b63philippe            for (i = 0; i < di->loctab_used; i++)
37959e1f3c79e870a978d24add86db6d8c5450c8b63philippe               new[i] = old[i];
38059e1f3c79e870a978d24add86db6d8c5450c8b63philippe            ML_(dinfo_free)(old);
38159e1f3c79e870a978d24add86db6d8c5450c8b63philippe            di->sizeof_fndn_ix = 2;
38259e1f3c79e870a978d24add86db6d8c5450c8b63philippe            di->loctab_fndn_ix = new;
38359e1f3c79e870a978d24add86db6d8c5450c8b63philippe         }
38459e1f3c79e870a978d24add86db6d8c5450c8b63philippe         // Fallthrough
38559e1f3c79e870a978d24add86db6d8c5450c8b63philippe
38659e1f3c79e870a978d24add86db6d8c5450c8b63philippe      case 2:
38759e1f3c79e870a978d24add86db6d8c5450c8b63philippe         if (LIKELY (fndn_ix <= 65535)) {
38859e1f3c79e870a978d24add86db6d8c5450c8b63philippe            ((UShort*) di->loctab_fndn_ix)[locno] = fndn_ix;
38959e1f3c79e870a978d24add86db6d8c5450c8b63philippe            return;
39059e1f3c79e870a978d24add86db6d8c5450c8b63philippe         }
39159e1f3c79e870a978d24add86db6d8c5450c8b63philippe         {
39259e1f3c79e870a978d24add86db6d8c5450c8b63philippe            UShort* old = (UShort*) di->loctab_fndn_ix;
39359e1f3c79e870a978d24add86db6d8c5450c8b63philippe            UInt* new = ML_(dinfo_zalloc)( "di.storage.sfix.2",
39459e1f3c79e870a978d24add86db6d8c5450c8b63philippe                                           di->loctab_size * 4 );
39559e1f3c79e870a978d24add86db6d8c5450c8b63philippe            for (i = 0; i < di->loctab_used; i++)
39659e1f3c79e870a978d24add86db6d8c5450c8b63philippe               new[i] = old[i];
39759e1f3c79e870a978d24add86db6d8c5450c8b63philippe            ML_(dinfo_free)(old);
39859e1f3c79e870a978d24add86db6d8c5450c8b63philippe            di->sizeof_fndn_ix = 4;
39959e1f3c79e870a978d24add86db6d8c5450c8b63philippe            di->loctab_fndn_ix = new;
40059e1f3c79e870a978d24add86db6d8c5450c8b63philippe         }
40159e1f3c79e870a978d24add86db6d8c5450c8b63philippe         // Fallthrough
40259e1f3c79e870a978d24add86db6d8c5450c8b63philippe
40359e1f3c79e870a978d24add86db6d8c5450c8b63philippe      case 4:
40459e1f3c79e870a978d24add86db6d8c5450c8b63philippe         ((UInt*) di->loctab_fndn_ix)[locno] = fndn_ix;
40559e1f3c79e870a978d24add86db6d8c5450c8b63philippe         return;
40659e1f3c79e870a978d24add86db6d8c5450c8b63philippe
40759e1f3c79e870a978d24add86db6d8c5450c8b63philippe      default: vg_assert(0);
40859e1f3c79e870a978d24add86db6d8c5450c8b63philippe   }
40959e1f3c79e870a978d24add86db6d8c5450c8b63philippe}
410eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
411eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Add a location to the location table.
412eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
41359e1f3c79e870a978d24add86db6d8c5450c8b63philippestatic void addLoc ( struct _DebugInfo* di, DiLoc* loc, UInt fndn_ix )
414eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
415eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Zero-sized locs should have been ignored earlier */
416eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(loc->size > 0);
417eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->loctab_used == di->loctab_size) {
41959e1f3c79e870a978d24add86db6d8c5450c8b63philippe      UInt   new_sz;
42059e1f3c79e870a978d24add86db6d8c5450c8b63philippe      DiLoc* new_loctab;
42159e1f3c79e870a978d24add86db6d8c5450c8b63philippe      void*  new_loctab_fndn_ix;
42259e1f3c79e870a978d24add86db6d8c5450c8b63philippe
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      new_sz = 2 * di->loctab_size;
424eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (new_sz == 0) new_sz = 500;
42559e1f3c79e870a978d24add86db6d8c5450c8b63philippe      new_loctab = ML_(dinfo_zalloc)( "di.storage.addLoc.1",
42659e1f3c79e870a978d24add86db6d8c5450c8b63philippe                                      new_sz * sizeof(DiLoc) );
42759e1f3c79e870a978d24add86db6d8c5450c8b63philippe      if (di->sizeof_fndn_ix == 0)
42859e1f3c79e870a978d24add86db6d8c5450c8b63philippe         di->sizeof_fndn_ix = 1; // To start with.
42959e1f3c79e870a978d24add86db6d8c5450c8b63philippe      new_loctab_fndn_ix = ML_(dinfo_zalloc)( "di.storage.addLoc.2",
43059e1f3c79e870a978d24add86db6d8c5450c8b63philippe                                              new_sz * di->sizeof_fndn_ix );
431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->loctab != NULL) {
43259e1f3c79e870a978d24add86db6d8c5450c8b63philippe         VG_(memcpy)(new_loctab, di->loctab,
43359e1f3c79e870a978d24add86db6d8c5450c8b63philippe                     di->loctab_used * sizeof(DiLoc));
43459e1f3c79e870a978d24add86db6d8c5450c8b63philippe         VG_(memcpy)(new_loctab_fndn_ix, di->loctab_fndn_ix,
43559e1f3c79e870a978d24add86db6d8c5450c8b63philippe                     di->loctab_used * di->sizeof_fndn_ix);
436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(dinfo_free)(di->loctab);
43759e1f3c79e870a978d24add86db6d8c5450c8b63philippe         ML_(dinfo_free)(di->loctab_fndn_ix);
438eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
43959e1f3c79e870a978d24add86db6d8c5450c8b63philippe      di->loctab = new_loctab;
44059e1f3c79e870a978d24add86db6d8c5450c8b63philippe      di->loctab_fndn_ix = new_loctab_fndn_ix;
441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->loctab_size = new_sz;
442eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
443eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di->loctab[di->loctab_used] = *loc;
44559e1f3c79e870a978d24add86db6d8c5450c8b63philippe   set_fndn_ix (di, di->loctab_used, fndn_ix);
446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di->loctab_used++;
447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di->loctab_used <= di->loctab_size);
448eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
449eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
450eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
451796e4b25100561a9e953cfe4dad83130b0153ce5sewardj/* Resize the LocTab (line number table) to save memory, by removing
452796e4b25100561a9e953cfe4dad83130b0153ce5sewardj   (and, potentially, allowing m_mallocfree to unmap) any unused space
4530b9d0646949bd382758763664d3bf2d6115993aephilippe   at the end of the table. */
454796e4b25100561a9e953cfe4dad83130b0153ce5sewardjstatic void shrinkLocTab ( struct _DebugInfo* di )
455f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
456796e4b25100561a9e953cfe4dad83130b0153ce5sewardj   UWord new_sz = di->loctab_used;
457f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (new_sz == di->loctab_size) return;
458796e4b25100561a9e953cfe4dad83130b0153ce5sewardj   vg_assert(new_sz < di->loctab_size);
4590b9d0646949bd382758763664d3bf2d6115993aephilippe   ML_(dinfo_shrink_block)( di->loctab, new_sz * sizeof(DiLoc));
46059e1f3c79e870a978d24add86db6d8c5450c8b63philippe   ML_(dinfo_shrink_block)( di->loctab_fndn_ix, new_sz * di->sizeof_fndn_ix);
461f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   di->loctab_size = new_sz;
462f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
463f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
464f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
465eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Top-level place to call to add a source-location mapping entry.
466eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjvoid ML_(addLineInfo) ( struct _DebugInfo* di,
46859e1f3c79e870a978d24add86db6d8c5450c8b63philippe                        UInt     fndn_ix,
469eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        Addr     this,
470eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        Addr     next,
471eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        Int      lineno,
472eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        Int      entry /* only needed for debug printing */
473eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj     )
474eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
475eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static const Bool debug = False;
476eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   DiLoc loc;
477c1d946eb075492d55397d0070349e3b8461bd793sewardj   UWord size = next - this;
478eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
479eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Ignore zero-sized locs */
480eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (this == next) return;
481eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
48259e1f3c79e870a978d24add86db6d8c5450c8b63philippe   if (debug) {
48359e1f3c79e870a978d24add86db6d8c5450c8b63philippe      FnDn *fndn = VG_(indexEltNumber) (di->fndnpool, fndn_ix);
48459e1f3c79e870a978d24add86db6d8c5450c8b63philippe      VG_(printf)( "  src ix %u %s %s line %d %#lx-%#lx\n",
48559e1f3c79e870a978d24add86db6d8c5450c8b63philippe                   fndn_ix,
48659e1f3c79e870a978d24add86db6d8c5450c8b63philippe                   fndn->dirname ? fndn->dirname : "(unknown)",
48759e1f3c79e870a978d24add86db6d8c5450c8b63philippe                   fndn->filename, lineno, this, next );
48859e1f3c79e870a978d24add86db6d8c5450c8b63philippe   }
489eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
490eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Maximum sanity checking.  Some versions of GNU as do a shabby
491eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj    * job with stabs entries; if anything looks suspicious, revert to
492eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj    * a size of 1.  This should catch the instruction of interest
493eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj    * (since if using asm-level debug info, one instruction will
494eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj    * correspond to one line, unlike with C-level debug info where
495eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj    * multiple instructions can map to the one line), but avoid
496eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj    * catching any other instructions bogusly. */
497eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (this > next) {
498eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj       if (VG_(clo_verbosity) > 2) {
499eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj           VG_(message)(Vg_DebugMsg,
500eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        "warning: line info addresses out of order "
501738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                        "at entry %d: 0x%lx 0x%lx\n", entry, this, next);
502eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj       }
503eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj       size = 1;
504eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
505eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
506eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (size > MAX_LOC_SIZE) {
507eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj       if (0)
508eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj       VG_(message)(Vg_DebugMsg,
509eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                    "warning: line info address range too large "
510c1d946eb075492d55397d0070349e3b8461bd793sewardj                    "at entry %d: %lu\n", entry, size);
511eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj       size = 1;
512eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
513eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
514c1d946eb075492d55397d0070349e3b8461bd793sewardj   /* At this point, we know that the original value for |size|, viz
515c1d946eb075492d55397d0070349e3b8461bd793sewardj      |next - this|, will only still be used in the case where
516c1d946eb075492d55397d0070349e3b8461bd793sewardj      |this| <u |next|, so it can't have underflowed.  Considering
517c1d946eb075492d55397d0070349e3b8461bd793sewardj      that and the three checks that follow it, the following must
518c1d946eb075492d55397d0070349e3b8461bd793sewardj      hold. */
519c1d946eb075492d55397d0070349e3b8461bd793sewardj   vg_assert(size >= 1);
520c1d946eb075492d55397d0070349e3b8461bd793sewardj   vg_assert(size <= MAX_LOC_SIZE);
521c1d946eb075492d55397d0070349e3b8461bd793sewardj
522b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Rule out ones which are completely outside the r-x mapped area.
523b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      See "Comment_Regarding_Text_Range_Checks" elsewhere in this file
524b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for background and rationale. */
525a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rx_map && di->fsm.have_rw_map);
526c1d946eb075492d55397d0070349e3b8461bd793sewardj   if (ML_(find_rx_mapping)(di, this, this + size - 1) == NULL) {
527eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj       if (0)
528eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj          VG_(message)(Vg_DebugMsg,
529eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                       "warning: ignoring line info entry falling "
530738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                       "outside current DebugInfo: %#lx %#lx %#lx %#lx\n",
531b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       di->text_avma,
532b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       di->text_avma + di->text_size,
533c1d946eb075492d55397d0070349e3b8461bd793sewardj                       this, this + size - 1);
534eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj       return;
535eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
536eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
537eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(lineno >= 0);
538eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (lineno > MAX_LINENO) {
539eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      static Bool complained = False;
540eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!complained) {
541eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         complained = True;
542eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(message)(Vg_UserMsg,
543eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                      "warning: ignoring line info entry with "
544738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                      "huge line number (%d)\n", lineno);
545eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(message)(Vg_UserMsg,
546eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                      "         Can't handle line numbers "
547738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                      "greater than %d, sorry\n", MAX_LINENO);
548eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(message)(Vg_UserMsg,
549738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                      "(Nb: this message is only shown once)\n");
550eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
551eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return;
552eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
553eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
554eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   loc.addr      = this;
555eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   loc.size      = (UShort)size;
556eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   loc.lineno    = lineno;
557eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
558eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (0) VG_(message)(Vg_DebugMsg,
55959e1f3c79e870a978d24add86db6d8c5450c8b63philippe		       "addLoc: addr %#lx, size %lu, line %d, fndn_ix %u\n",
56059e1f3c79e870a978d24add86db6d8c5450c8b63philippe		       this,size,lineno,fndn_ix);
561eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
56259e1f3c79e870a978d24add86db6d8c5450c8b63philippe   addLoc ( di, &loc, fndn_ix );
563eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
564eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
565a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/* Add an inlined call info to the inlined call table.
566a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe*/
567a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic void addInl ( struct _DebugInfo* di, DiInlLoc* inl )
568a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
569a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   UInt   new_sz, i;
570a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DiInlLoc* new_tab;
571a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
572a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* empty inl should have been ignored earlier */
573a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert(inl->addr_lo < inl->addr_hi);
574a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
575a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (di->inltab_used == di->inltab_size) {
576a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      new_sz = 2 * di->inltab_size;
577a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (new_sz == 0) new_sz = 500;
578a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      new_tab = ML_(dinfo_zalloc)( "di.storage.addInl.1",
579a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                                   new_sz * sizeof(DiInlLoc) );
580a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab != NULL) {
581a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         for (i = 0; i < di->inltab_used; i++)
582a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe            new_tab[i] = di->inltab[i];
583a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         ML_(dinfo_free)(di->inltab);
584a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      }
585a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      di->inltab = new_tab;
586a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      di->inltab_size = new_sz;
587a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
588a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
589a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   di->inltab[di->inltab_used] = *inl;
590a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (inl->addr_hi - inl->addr_lo > di->maxinl_codesz)
591a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      di->maxinl_codesz = inl->addr_hi - inl->addr_lo;
592a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   di->inltab_used++;
593a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert(di->inltab_used <= di->inltab_size);
594a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
595a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
596a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
597a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/* Resize the InlTab (inlined call table) to save memory, by removing
598a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   (and, potentially, allowing m_mallocfree to unmap) any unused space
5990b9d0646949bd382758763664d3bf2d6115993aephilippe   at the end of the table. */
600a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic void shrinkInlTab ( struct _DebugInfo* di )
601a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
602a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   UWord new_sz = di->inltab_used;
603a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (new_sz == di->inltab_size) return;
604a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert(new_sz < di->inltab_size);
6050b9d0646949bd382758763664d3bf2d6115993aephilippe   ML_(dinfo_shrink_block)( di->inltab, new_sz * sizeof(DiInlLoc));
606a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   di->inltab_size = new_sz;
607a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
608a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
609a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/* Top-level place to call to add a addr-to-inlined fn info. */
610a0a73939b0398b6608fd6dbde49820ce6530d12cphilippevoid ML_(addInlInfo) ( struct _DebugInfo* di,
611a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                       Addr addr_lo, Addr addr_hi,
612a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                       const HChar* inlinedfn,
613666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                       UInt fndn_ix,
614a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                       Int lineno, UShort level)
615a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
616a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DiInlLoc inl;
617a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
618a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* Similar paranoia as in ML_(addLineInfo). Unclear if needed. */
619a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (addr_lo >= addr_hi) {
620a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe       if (VG_(clo_verbosity) > 2) {
621a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe           VG_(message)(Vg_DebugMsg,
622a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        "warning: inlined info addresses out of order "
623a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        "at: 0x%lx 0x%lx\n", addr_lo, addr_hi);
624a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe       }
625a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe       addr_hi = addr_lo + 1;
626a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
627a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
628a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert(lineno >= 0);
629a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (lineno > MAX_LINENO) {
630a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      static Bool complained = False;
631a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (!complained) {
632a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         complained = True;
633a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         VG_(message)(Vg_UserMsg,
634a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                      "warning: ignoring inlined call info entry with "
635a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                      "huge line number (%d)\n", lineno);
636a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         VG_(message)(Vg_UserMsg,
637a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                      "         Can't handle line numbers "
638a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                      "greater than %d, sorry\n", MAX_LINENO);
639a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         VG_(message)(Vg_UserMsg,
640a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                      "(Nb: this message is only shown once)\n");
641a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      }
642a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return;
643a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
644a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
645a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   // code resulting from inlining of inlinedfn:
646a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   inl.addr_lo   = addr_lo;
647a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   inl.addr_hi   = addr_hi;
648a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   inl.inlinedfn = inlinedfn;
649a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   // caller:
650666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   inl.fndn_ix   = fndn_ix;
651a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   inl.lineno    = lineno;
652a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   inl.level     = level;
653a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
654a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (0) VG_(message)
655a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe             (Vg_DebugMsg,
656a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe              "addInlInfo: fn %s inlined as addr_lo %#lx,addr_hi %#lx,"
657666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe              "caller fndn_ix %d %s:%d\n",
658666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe              inlinedfn, addr_lo, addr_hi, fndn_ix,
659666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe              ML_(fndn_ix2filename) (di, fndn_ix), lineno);
660a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
661a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   addInl ( di, &inl );
662a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
663a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
664518850bf0da07ed3e2244e307268ae0fd80e93a8florianDiCfSI_m* ML_(get_cfsi_m) (const DebugInfo* di, UInt pos)
6655c3dba227192de63d86f65ec7d9597c132818c37philippe{
6665c3dba227192de63d86f65ec7d9597c132818c37philippe   UInt cfsi_m_ix;
6675c3dba227192de63d86f65ec7d9597c132818c37philippe
6685c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert(pos >= 0 && pos < di->cfsi_used);
66959e1f3c79e870a978d24add86db6d8c5450c8b63philippe   switch (di->sizeof_cfsi_m_ix) {
6705c3dba227192de63d86f65ec7d9597c132818c37philippe      case 1: cfsi_m_ix = ((UChar*)  di->cfsi_m_ix)[pos]; break;
6715c3dba227192de63d86f65ec7d9597c132818c37philippe      case 2: cfsi_m_ix = ((UShort*) di->cfsi_m_ix)[pos]; break;
6725c3dba227192de63d86f65ec7d9597c132818c37philippe      case 4: cfsi_m_ix = ((UInt*)   di->cfsi_m_ix)[pos]; break;
6735c3dba227192de63d86f65ec7d9597c132818c37philippe      default: vg_assert(0);
6745c3dba227192de63d86f65ec7d9597c132818c37philippe   }
6755c3dba227192de63d86f65ec7d9597c132818c37philippe   if (cfsi_m_ix == 0)
6765c3dba227192de63d86f65ec7d9597c132818c37philippe      return NULL; // cfi hole
6775c3dba227192de63d86f65ec7d9597c132818c37philippe   else
6785c3dba227192de63d86f65ec7d9597c132818c37philippe      return VG_(indexEltNumber) (di->cfsi_m_pool, cfsi_m_ix);
6795c3dba227192de63d86f65ec7d9597c132818c37philippe}
680eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Top-level place to call to add a CFI summary record.  The supplied
6825c3dba227192de63d86f65ec7d9597c132818c37philippe   DiCfSI_m is copied. */
6835c3dba227192de63d86f65ec7d9597c132818c37philippevoid ML_(addDiCfSI) ( struct _DebugInfo* di,
6845c3dba227192de63d86f65ec7d9597c132818c37philippe                      Addr base, UInt len, DiCfSI_m* cfsi_m )
685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static const Bool debug = False;
6875c3dba227192de63d86f65ec7d9597c132818c37philippe   UInt    new_sz;
688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   DiCfSI* new_tab;
68910deba428bd24d2105dbbe5bf58469385cc740besewardj   SSizeT  delta;
690518850bf0da07ed3e2244e307268ae0fd80e93a8florian   DebugInfoMapping* map;
691518850bf0da07ed3e2244e307268ae0fd80e93a8florian   DebugInfoMapping* map2;
69210deba428bd24d2105dbbe5bf58469385cc740besewardj
693eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (debug) {
694eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      VG_(printf)("adding DiCfSI: ");
6955c3dba227192de63d86f65ec7d9597c132818c37philippe      ML_(ppDiCfSI)(di->cfsi_exprs, base, len, cfsi_m);
696eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
697eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
6982e54028ae63b2e4be7f737300a87d70f17b85edbsewardj   /* sanity */
6995c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert(len > 0);
7009b54074df0311ae2509cda596b388b065d101b67florian   /* Issue a warning if LEN is unexpectedly large (exceeds 5 million).
7019b54074df0311ae2509cda596b388b065d101b67florian      The implication is you have a single procedure
7022e54028ae63b2e4be7f737300a87d70f17b85edbsewardj      with more than 5 million bytes of code.  Which is pretty
7032e54028ae63b2e4be7f737300a87d70f17b85edbsewardj      unlikely.  Either that, or the debuginfo reader is somehow
70410deba428bd24d2105dbbe5bf58469385cc740besewardj      broken.  5 million is of course arbitrary; but it's big enough
70510deba428bd24d2105dbbe5bf58469385cc740besewardj      to be bigger than the size of any plausible piece of code that
7069b54074df0311ae2509cda596b388b065d101b67florian      would fall within a single procedure. But occasionally it does
7079b54074df0311ae2509cda596b388b065d101b67florian      happen (c.f. BZ #339542). */
7089b54074df0311ae2509cda596b388b065d101b67florian   if (len >= 5000000)
7099b54074df0311ae2509cda596b388b065d101b67florian      VG_(message)(Vg_DebugMsg,
7109b54074df0311ae2509cda596b388b065d101b67florian                   "warning: DiCfSI %#lx .. %#lx is huge; length = %u (%s)\n",
7119b54074df0311ae2509cda596b388b065d101b67florian                   base, base + len - 1, len, di->soname);
71210deba428bd24d2105dbbe5bf58469385cc740besewardj
713a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rx_map && di->fsm.have_rw_map);
7146b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Find mapping where at least one end of the CFSI falls into. */
7155c3dba227192de63d86f65ec7d9597c132818c37philippe   map  = ML_(find_rx_mapping)(di, base, base);
7165c3dba227192de63d86f65ec7d9597c132818c37philippe   map2 = ML_(find_rx_mapping)(di, base + len - 1,
7175c3dba227192de63d86f65ec7d9597c132818c37philippe                                   base + len - 1);
7186b5625bb609b154766d2e138b61e15655f60b710sewardj   if (map == NULL)
7196b5625bb609b154766d2e138b61e15655f60b710sewardj      map = map2;
7206b5625bb609b154766d2e138b61e15655f60b710sewardj   else if (map2 == NULL)
7216b5625bb609b154766d2e138b61e15655f60b710sewardj      map2 = map;
7226b5625bb609b154766d2e138b61e15655f60b710sewardj
7236b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Rule out ones which are completely outside the r-x mapped area
7246b5625bb609b154766d2e138b61e15655f60b710sewardj      (or which span across different areas).
725b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      See "Comment_Regarding_Text_Range_Checks" elsewhere in this file
726b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for background and rationale. */
7276b5625bb609b154766d2e138b61e15655f60b710sewardj   if (map == NULL || map != map2) {
728b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      static Int complaints = 10;
729eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (VG_(clo_trace_cfi) || complaints > 0) {
730eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         complaints--;
731eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (VG_(clo_verbosity) > 1) {
732eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(
733eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Vg_DebugMsg,
734ade2eddf567a868bafad9110ed92acf7373a972bsewardj               "warning: DiCfSI %#lx .. %#lx outside mapped rx segments (%s)\n",
7355c3dba227192de63d86f65ec7d9597c132818c37philippe               base,
7365c3dba227192de63d86f65ec7d9597c132818c37philippe               base + len - 1,
7376b5625bb609b154766d2e138b61e15655f60b710sewardj               di->soname
738eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            );
739eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
740eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (VG_(clo_trace_cfi))
7415c3dba227192de63d86f65ec7d9597c132818c37philippe            ML_(ppDiCfSI)(di->cfsi_exprs, base, len, cfsi_m);
742eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
743eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return;
744eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
745eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
74610deba428bd24d2105dbbe5bf58469385cc740besewardj   /* Now we know the range is at least partially inside the r-x
74710deba428bd24d2105dbbe5bf58469385cc740besewardj      mapped area.  That implies that at least one of the ends of the
74810deba428bd24d2105dbbe5bf58469385cc740besewardj      range falls inside the area.  If necessary, clip it so it is
74910deba428bd24d2105dbbe5bf58469385cc740besewardj      completely within the area.  If we don't do this,
75010deba428bd24d2105dbbe5bf58469385cc740besewardj      check_CFSI_related_invariants() in debuginfo.c (invariant #2)
75110deba428bd24d2105dbbe5bf58469385cc740besewardj      will fail.  See
75210deba428bd24d2105dbbe5bf58469385cc740besewardj      "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
75310deba428bd24d2105dbbe5bf58469385cc740besewardj      priv_storage.h for background. */
7545c3dba227192de63d86f65ec7d9597c132818c37philippe   if (base < map->avma) {
75510deba428bd24d2105dbbe5bf58469385cc740besewardj      /* Lower end is outside the mapped area.  Hence upper end must
75610deba428bd24d2105dbbe5bf58469385cc740besewardj         be inside it. */
75710deba428bd24d2105dbbe5bf58469385cc740besewardj      if (0) VG_(printf)("XXX truncate lower\n");
7585c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(base + len - 1 >= map->avma);
7595c3dba227192de63d86f65ec7d9597c132818c37philippe      delta = (SSizeT)(map->avma - base);
76010deba428bd24d2105dbbe5bf58469385cc740besewardj      vg_assert(delta > 0);
7615c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(delta < (SSizeT)len);
7625c3dba227192de63d86f65ec7d9597c132818c37philippe      base += delta;
7635c3dba227192de63d86f65ec7d9597c132818c37philippe      len -= delta;
76410deba428bd24d2105dbbe5bf58469385cc740besewardj   }
76510deba428bd24d2105dbbe5bf58469385cc740besewardj   else
7665c3dba227192de63d86f65ec7d9597c132818c37philippe   if (base + len - 1 > map->avma + map->size - 1) {
76710deba428bd24d2105dbbe5bf58469385cc740besewardj      /* Upper end is outside the mapped area.  Hence lower end must be
76810deba428bd24d2105dbbe5bf58469385cc740besewardj         inside it. */
76910deba428bd24d2105dbbe5bf58469385cc740besewardj      if (0) VG_(printf)("XXX truncate upper\n");
7705c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(base <= map->avma + map->size - 1);
7715c3dba227192de63d86f65ec7d9597c132818c37philippe      delta = (SSizeT)( (base + len - 1)
7726b5625bb609b154766d2e138b61e15655f60b710sewardj                        - (map->avma + map->size - 1) );
7736b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(delta > 0);
7745c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(delta < (SSizeT)len);
7755c3dba227192de63d86f65ec7d9597c132818c37philippe      len -= delta;
77610deba428bd24d2105dbbe5bf58469385cc740besewardj   }
77710deba428bd24d2105dbbe5bf58469385cc740besewardj
77810deba428bd24d2105dbbe5bf58469385cc740besewardj   /* Final checks */
77910deba428bd24d2105dbbe5bf58469385cc740besewardj
78010deba428bd24d2105dbbe5bf58469385cc740besewardj   /* Because: either cfsi was entirely inside the range, in which
78110deba428bd24d2105dbbe5bf58469385cc740besewardj      case we asserted that len > 0 at the start, OR it fell partially
78210deba428bd24d2105dbbe5bf58469385cc740besewardj      inside the range, in which case we reduced it by some size
78310deba428bd24d2105dbbe5bf58469385cc740besewardj      (delta) which is < its original size. */
7845c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert(len > 0);
78510deba428bd24d2105dbbe5bf58469385cc740besewardj
78610deba428bd24d2105dbbe5bf58469385cc740besewardj   /* Similar logic applies for the next two assertions. */
7875c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert(base >= map->avma);
7885c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert(base + len - 1
7896b5625bb609b154766d2e138b61e15655f60b710sewardj             <= map->avma + map->size - 1);
79010deba428bd24d2105dbbe5bf58469385cc740besewardj
791b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->cfsi_used == di->cfsi_size) {
792b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      new_sz = 2 * di->cfsi_size;
793eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (new_sz == 0) new_sz = 20;
7949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      new_tab = ML_(dinfo_zalloc)( "di.storage.addDiCfSI.1",
7959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                   new_sz * sizeof(DiCfSI) );
7965c3dba227192de63d86f65ec7d9597c132818c37philippe      if (di->cfsi_rd != NULL) {
7975c3dba227192de63d86f65ec7d9597c132818c37philippe         VG_(memcpy)(new_tab, di->cfsi_rd,
7985c3dba227192de63d86f65ec7d9597c132818c37philippe                     di->cfsi_used * sizeof(DiCfSI));
7995c3dba227192de63d86f65ec7d9597c132818c37philippe         ML_(dinfo_free)(di->cfsi_rd);
800eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
8015c3dba227192de63d86f65ec7d9597c132818c37philippe      di->cfsi_rd = new_tab;
802b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->cfsi_size = new_sz;
8035c3dba227192de63d86f65ec7d9597c132818c37philippe      if (di->cfsi_m_pool == NULL)
8045c3dba227192de63d86f65ec7d9597c132818c37philippe         di->cfsi_m_pool = VG_(newDedupPA)(1000 * sizeof(DiCfSI_m),
8055c3dba227192de63d86f65ec7d9597c132818c37philippe                                           vg_alignof(DiCfSI_m),
8065c3dba227192de63d86f65ec7d9597c132818c37philippe                                           ML_(dinfo_zalloc),
8075c3dba227192de63d86f65ec7d9597c132818c37philippe                                           "di.storage.DiCfSI_m_pool",
8085c3dba227192de63d86f65ec7d9597c132818c37philippe                                           ML_(dinfo_free));
8095c3dba227192de63d86f65ec7d9597c132818c37philippe   }
8105c3dba227192de63d86f65ec7d9597c132818c37philippe
8115c3dba227192de63d86f65ec7d9597c132818c37philippe   di->cfsi_rd[di->cfsi_used].base = base;
8125c3dba227192de63d86f65ec7d9597c132818c37philippe   di->cfsi_rd[di->cfsi_used].len  = len;
8135c3dba227192de63d86f65ec7d9597c132818c37philippe   di->cfsi_rd[di->cfsi_used].cfsi_m_ix
8145c3dba227192de63d86f65ec7d9597c132818c37philippe      = VG_(allocFixedEltDedupPA)(di->cfsi_m_pool,
8155c3dba227192de63d86f65ec7d9597c132818c37philippe                                  sizeof(DiCfSI_m),
8165c3dba227192de63d86f65ec7d9597c132818c37philippe                                  cfsi_m);
817b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di->cfsi_used++;
818b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di->cfsi_used <= di->cfsi_size);
819eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
820eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
821eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
82272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjInt ML_(CfiExpr_Undef)( XArray* dst )
82372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
82472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExpr e;
82572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(memset)( &e, 0, sizeof(e) );
82672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.tag = Cex_Undef;
827bee43c15c5aed57d25df177308347224aa461d9csewardj   return (Int)VG_(addToXA)( dst, &e );
82872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
82972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjInt ML_(CfiExpr_Deref)( XArray* dst, Int ixAddr )
83072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
83172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExpr e;
83272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(memset)( &e, 0, sizeof(e) );
83372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.tag = Cex_Deref;
83472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.Cex.Deref.ixAddr = ixAddr;
835bee43c15c5aed57d25df177308347224aa461d9csewardj   return (Int)VG_(addToXA)( dst, &e );
83672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
83772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjInt ML_(CfiExpr_Const)( XArray* dst, UWord con )
83872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
83972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExpr e;
84072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(memset)( &e, 0, sizeof(e) );
84172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.tag = Cex_Const;
84272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.Cex.Const.con = con;
843bee43c15c5aed57d25df177308347224aa461d9csewardj   return (Int)VG_(addToXA)( dst, &e );
84472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
84540628facff2285b0fce592381c6e26fdcd2a1252tomInt ML_(CfiExpr_Unop)( XArray* dst, CfiUnop op, Int ix )
84640628facff2285b0fce592381c6e26fdcd2a1252tom{
84740628facff2285b0fce592381c6e26fdcd2a1252tom   CfiExpr e;
84840628facff2285b0fce592381c6e26fdcd2a1252tom   VG_(memset)( &e, 0, sizeof(e) );
84940628facff2285b0fce592381c6e26fdcd2a1252tom   e.tag = Cex_Unop;
85040628facff2285b0fce592381c6e26fdcd2a1252tom   e.Cex.Unop.op  = op;
85140628facff2285b0fce592381c6e26fdcd2a1252tom   e.Cex.Unop.ix = ix;
85240628facff2285b0fce592381c6e26fdcd2a1252tom   return (Int)VG_(addToXA)( dst, &e );
85340628facff2285b0fce592381c6e26fdcd2a1252tom}
854f6716dd8f025c9ace67541f3360d7f4523496d8atomInt ML_(CfiExpr_Binop)( XArray* dst, CfiBinop op, Int ixL, Int ixR )
85572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
85672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExpr e;
85772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(memset)( &e, 0, sizeof(e) );
85872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.tag = Cex_Binop;
85972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.Cex.Binop.op  = op;
86072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.Cex.Binop.ixL = ixL;
86172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.Cex.Binop.ixR = ixR;
862bee43c15c5aed57d25df177308347224aa461d9csewardj   return (Int)VG_(addToXA)( dst, &e );
86372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
86472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjInt ML_(CfiExpr_CfiReg)( XArray* dst, CfiReg reg )
86572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
86672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExpr e;
86772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(memset)( &e, 0, sizeof(e) );
86872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.tag = Cex_CfiReg;
86972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.Cex.CfiReg.reg = reg;
870bee43c15c5aed57d25df177308347224aa461d9csewardj   return (Int)VG_(addToXA)( dst, &e );
87172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
87272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjInt ML_(CfiExpr_DwReg)( XArray* dst, Int reg )
87372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
87472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExpr e;
87572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(memset)( &e, 0, sizeof(e) );
87672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.tag = Cex_DwReg;
87772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   e.Cex.DwReg.reg = reg;
878bee43c15c5aed57d25df177308347224aa461d9csewardj   return (Int)VG_(addToXA)( dst, &e );
87972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
88072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
88140628facff2285b0fce592381c6e26fdcd2a1252tomstatic void ppCfiUnop ( CfiUnop op )
88240628facff2285b0fce592381c6e26fdcd2a1252tom{
88340628facff2285b0fce592381c6e26fdcd2a1252tom   switch (op) {
88440628facff2285b0fce592381c6e26fdcd2a1252tom      case Cunop_Abs: VG_(printf)("abs"); break;
88540628facff2285b0fce592381c6e26fdcd2a1252tom      case Cunop_Neg: VG_(printf)("-"); break;
88640628facff2285b0fce592381c6e26fdcd2a1252tom      case Cunop_Not: VG_(printf)("~"); break;
88740628facff2285b0fce592381c6e26fdcd2a1252tom      default:        vg_assert(0);
88840628facff2285b0fce592381c6e26fdcd2a1252tom   }
88940628facff2285b0fce592381c6e26fdcd2a1252tom}
89040628facff2285b0fce592381c6e26fdcd2a1252tom
891f6716dd8f025c9ace67541f3360d7f4523496d8atomstatic void ppCfiBinop ( CfiBinop op )
89272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
89372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (op) {
894f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_Add: VG_(printf)("+"); break;
895f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_Sub: VG_(printf)("-"); break;
896f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_And: VG_(printf)("&"); break;
897f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_Mul: VG_(printf)("*"); break;
898f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_Shl: VG_(printf)("<<"); break;
899f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_Shr: VG_(printf)(">>"); break;
900f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_Eq:  VG_(printf)("=="); break;
901f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_Ge:  VG_(printf)(">="); break;
902f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_Gt:  VG_(printf)(">"); break;
903f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_Le:  VG_(printf)("<="); break;
904f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_Lt:  VG_(printf)("<"); break;
905f6716dd8f025c9ace67541f3360d7f4523496d8atom      case Cbinop_Ne:  VG_(printf)("!="); break;
906f6716dd8f025c9ace67541f3360d7f4523496d8atom      default:         vg_assert(0);
90772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
90872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
90972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
91072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjstatic void ppCfiReg ( CfiReg reg )
91172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
91272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (reg) {
913ade2eddf567a868bafad9110ed92acf7373a972bsewardj      case Creg_INVALID:   VG_(printf)("Creg_INVALID"); break;
914821283b2110420321fd3f60afcc799b287788c68sewardj      case Creg_IA_SP:     VG_(printf)("xSP"); break;
915821283b2110420321fd3f60afcc799b287788c68sewardj      case Creg_IA_BP:     VG_(printf)("xBP"); break;
916821283b2110420321fd3f60afcc799b287788c68sewardj      case Creg_IA_IP:     VG_(printf)("xIP"); break;
917821283b2110420321fd3f60afcc799b287788c68sewardj      case Creg_ARM_R13:   VG_(printf)("R13"); break;
918821283b2110420321fd3f60afcc799b287788c68sewardj      case Creg_ARM_R12:   VG_(printf)("R12"); break;
919821283b2110420321fd3f60afcc799b287788c68sewardj      case Creg_ARM_R15:   VG_(printf)("R15"); break;
920821283b2110420321fd3f60afcc799b287788c68sewardj      case Creg_ARM_R14:   VG_(printf)("R14"); break;
921ade2eddf567a868bafad9110ed92acf7373a972bsewardj      case Creg_ARM_R7:    VG_(printf)("R7");  break;
922821283b2110420321fd3f60afcc799b287788c68sewardj      case Creg_ARM64_X30: VG_(printf)("X30"); break;
923821283b2110420321fd3f60afcc799b287788c68sewardj      case Creg_MIPS_RA:   VG_(printf)("RA"); break;
924b6ba6d288e6000a8f95fba1dea671e0b53e26043florian      case Creg_S390_IA:   VG_(printf)("IA"); break;
925b6ba6d288e6000a8f95fba1dea671e0b53e26043florian      case Creg_S390_SP:   VG_(printf)("SP"); break;
926b6ba6d288e6000a8f95fba1dea671e0b53e26043florian      case Creg_S390_FP:   VG_(printf)("FP"); break;
927b6ba6d288e6000a8f95fba1dea671e0b53e26043florian      case Creg_S390_LR:   VG_(printf)("LR"); break;
928112711afefcfcd43680c7c4aa8d38ef180e8811esewardj      case Creg_TILEGX_IP: VG_(printf)("PC");  break;
929112711afefcfcd43680c7c4aa8d38ef180e8811esewardj      case Creg_TILEGX_SP: VG_(printf)("SP");  break;
930112711afefcfcd43680c7c4aa8d38ef180e8811esewardj      case Creg_TILEGX_BP: VG_(printf)("BP");  break;
931112711afefcfcd43680c7c4aa8d38ef180e8811esewardj      case Creg_TILEGX_LR: VG_(printf)("R55"); break;
93272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default: vg_assert(0);
93372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
93472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
93572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
936518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid ML_(ppCfiExpr)( const XArray* src, Int ix )
93772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
93872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* VG_(indexXA) checks for invalid src/ix values, so we can
93972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      use it indiscriminately. */
9403297124fa2116737066ac3cd709f18fdd5405163florian   const CfiExpr* e = VG_(indexXA)( src, ix );
94172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
94272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Undef:
94372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(printf)("Undef");
94472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
94572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Deref:
94672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(printf)("*(");
94772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         ML_(ppCfiExpr)(src, e->Cex.Deref.ixAddr);
94872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(printf)(")");
94972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
95072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
95172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(printf)("0x%lx", e->Cex.Const.con);
95272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
95340628facff2285b0fce592381c6e26fdcd2a1252tom      case Cex_Unop:
95440628facff2285b0fce592381c6e26fdcd2a1252tom         ppCfiUnop(e->Cex.Unop.op);
95540628facff2285b0fce592381c6e26fdcd2a1252tom         VG_(printf)("(");
95640628facff2285b0fce592381c6e26fdcd2a1252tom         ML_(ppCfiExpr)(src, e->Cex.Unop.ix);
95740628facff2285b0fce592381c6e26fdcd2a1252tom         VG_(printf)(")");
95840628facff2285b0fce592381c6e26fdcd2a1252tom         break;
95972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
96072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(printf)("(");
96172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         ML_(ppCfiExpr)(src, e->Cex.Binop.ixL);
96272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(printf)(")");
963f6716dd8f025c9ace67541f3360d7f4523496d8atom         ppCfiBinop(e->Cex.Binop.op);
96472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(printf)("(");
96572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         ML_(ppCfiExpr)(src, e->Cex.Binop.ixR);
96672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(printf)(")");
96772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
96872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
96972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         ppCfiReg(e->Cex.CfiReg.reg);
97072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
97172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_DwReg:
97272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(printf)("dwr%d", e->Cex.DwReg.reg);
97372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
97472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
97572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         VG_(core_panic)("ML_(ppCfiExpr)");
97672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
97772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
97872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
97972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
98072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
98172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
982b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjWord ML_(cmp_for_DiAddrRange_range) ( const void* keyV,
983b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                      const void* elemV ) {
984b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   const Addr* key = (const Addr*)keyV;
985b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   const DiAddrRange* elem = (const DiAddrRange*)elemV;
986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0)
987a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("cmp_for_DiAddrRange_range: %#lx vs %#lx\n",
988b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  *key, elem->aMin);
989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((*key) < elem->aMin) return -1;
990b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((*key) > elem->aMax) return 1;
991b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return 0;
992b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
993b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
994b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
9956bd9dc18c043927c1196caba20a327238a179c42florianvoid show_scope ( OSet* /* of DiAddrRange */ scope, const HChar* who )
996b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
997b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DiAddrRange* range;
998b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(printf)("Scope \"%s\" = {\n", who);
999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(OSetGen_ResetIter)( scope );
1000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
1001b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      range = VG_(OSetGen_Next)( scope );
1002b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!range) break;
1003a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("   %#lx .. %#lx: %lu vars\n", range->aMin, range->aMax,
1004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  range->vars ? VG_(sizeXA)(range->vars) : 0);
1005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(printf)("}\n");
1007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1008b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Add the variable 'var' to 'scope' for the address range [aMin,aMax]
1010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   (inclusive of aMin and aMax).  Split existing ranges as required if
1011b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   aMin or aMax or both don't match existing range boundaries, and add
1012b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   'var' to all required ranges.  Take great care to preserve the
1013b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   invariant that the ranges in 'scope' cover the entire address range
1014b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   exactly once, with no overlaps and no holes. */
1015b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void add_var_to_arange (
1016b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /*MOD*/OSet* /* of DiAddrRange */ scope,
1017b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               Addr aMin,
1018b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               Addr aMax,
1019b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var
1020b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            )
1021b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1022b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DiAddrRange *first, *last, *range;
1023b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* These xx variables are for assertion checking only; they don't
1024b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      contribute anything to the actual work of this function. */
1025b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DiAddrRange *xxRangep, *xxFirst, *xxLast;
1026b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UWord       xxIters;
1027b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1028b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(aMin <= aMax);
1029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1030a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("add_var_to_arange: %#lx .. %#lx\n", aMin, aMax);
1031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0) show_scope( scope, "add_var_to_arange(1)" );
1032b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1033b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if the lower end of the range (aMin) falls exactly on an
1034b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      existing range boundary.  If not, find the range it does fall
1035b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      into, and split it (copying the variables in the process), so
1036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that aMin does exactly fall on a range boundary. */
1037b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   first = VG_(OSetGen_Lookup)( scope, &aMin );
1038b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* It must be present, since the presented OSet must cover
1039b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      the entire address range. */
1040b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(first);
1041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(first->aMin <= first->aMax);
1042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(first->aMin <= aMin && aMin <= first->aMax);
1043b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1044b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Fast track common case, which is that the range specified for
1045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      the variable exactly coincides with one already-existing
1046b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      range. */
1047b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (first->aMin == aMin && first->aMax == aMax) {
1048b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(first->vars);
1049b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(addToXA)( first->vars, var );
1050b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1051b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1052b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1053b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We have to get into splitting ranges, which is complex
1054b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      and slow. */
1055b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (first->aMin < aMin) {
1056b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* nyu;
1057b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  We'll have to split 'first'. */
1058b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* truncate the upper end of 'first' */
1059b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr tmp = first->aMax;
1060b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      first->aMax = aMin-1;
1061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(first->aMin <= first->aMax);
1062b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* create a new range */
1063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      nyu = VG_(OSetGen_AllocNode)( scope, sizeof(DiAddrRange) );
1064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      nyu->aMin = aMin;
1065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      nyu->aMax = tmp;
1066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(nyu->aMin <= nyu->aMax);
1067b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* copy vars into it */
1068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(first->vars);
10699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      nyu->vars = VG_(cloneXA)( "di.storage.avta.1", first->vars );
1070b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(OSetGen_Insert)( scope, nyu );
1071b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      first = nyu;
1072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1073b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1074b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(first->aMin == aMin);
1075b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1076b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now do exactly the same for the upper end (aMax): if it doesn't
1077b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      fall on a boundary, cause it to do so by splitting the range it
1078b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      does currently fall into. */
1079b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   last = VG_(OSetGen_Lookup)( scope, &aMax );
1080b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(last->aMin <= last->aMax);
1081b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(last->aMin <= aMax && aMax <= last->aMax);
1082b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1083b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (aMax < last->aMax) {
1084b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* nyu;
1085b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have to split 'last'. */
1086b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* truncate the lower end of 'last' */
1087b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr tmp = last->aMin;
1088b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      last->aMin = aMax+1;
1089b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(last->aMin <= last->aMax);
1090b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* create a new range */
1091b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      nyu = VG_(OSetGen_AllocNode)( scope, sizeof(DiAddrRange) );
1092b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      nyu->aMin = tmp;
1093b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      nyu->aMax = aMax;
1094b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(nyu->aMin <= nyu->aMax);
1095b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* copy vars into it */
1096b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(last->vars);
10979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      nyu->vars = VG_(cloneXA)( "di.storage.avta.2", last->vars );
1098b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(OSetGen_Insert)( scope, nyu );
1099b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      last = nyu;
1100b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1101b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1102b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(aMax == last->aMax);
1103b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1104b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   xxFirst = (DiAddrRange*)VG_(OSetGen_Lookup)(scope, &aMin);
1105b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   xxLast  = (DiAddrRange*)VG_(OSetGen_Lookup)(scope, &aMax);
1106b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(xxFirst);
1107b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(xxLast);
1108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(xxFirst->aMin == aMin);
1109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(xxLast->aMax == aMax);
1110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (xxFirst != xxLast)
1111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(xxFirst->aMax < xxLast->aMin);
1112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Great.  Now we merely need to iterate over the segments from
1114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      'first' to 'last' inclusive, and add 'var' to the variable set
1115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of each of them. */
1116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0) {
1117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      static UWord ctr = 0;
1118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ctr++;
1119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("ctr = %lu\n", ctr);
1120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (ctr >= 33263) show_scope( scope, "add_var_to_arange(2)" );
1121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   xxIters = 0;
1124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   range = xxRangep = NULL;
1125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(OSetGen_ResetIterAt)( scope, &aMin );
1126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
1127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      xxRangep = range;
1128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      range    = VG_(OSetGen_Next)( scope );
1129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!range) break;
1130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (range->aMin > aMax) break;
1131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      xxIters++;
1132a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      if (0) VG_(printf)("have range %#lx %#lx\n",
1133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         range->aMin, range->aMax);
1134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Sanity checks */
1136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!xxRangep) {
1137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* This is the first in the range */
1138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(range->aMin == aMin);
1139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(xxRangep->aMax + 1 == range->aMin);
1141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
1142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(range->vars);
1144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(addToXA)( range->vars, var );
1145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Done.  We should have seen at least one range. */
1147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(xxIters >= 1);
1148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (xxIters == 1) vg_assert(xxFirst == xxLast);
1149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (xxFirst == xxLast) vg_assert(xxIters == 1);
1150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(xxRangep);
1151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(xxRangep->aMax == aMax);
1152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(xxRangep == xxLast);
1153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Top-level place to call to add a variable description (as extracted
1157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   from a DWARF3 .debug_info section. */
1158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjvoid ML_(addVar)( struct _DebugInfo* di,
1159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  Int    level,
1160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  Addr   aMin,
1161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  Addr   aMax,
11621ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian                  const  HChar* name, /* in di's .strpool */
11639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  UWord  typeR, /* a cuOff */
11643297124fa2116737066ac3cd709f18fdd5405163florian                  const GExpr* gexpr,
11653297124fa2116737066ac3cd709f18fdd5405163florian                  const GExpr* fbGX,
1166666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                  UInt   fndn_ix, /* where decl'd - may be zero.
1167666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                                     index in in di's .fndnpool */
1168b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  Int    lineNo, /* where decl'd - may be zero */
1169b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  Bool   show )
1170b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   OSet* /* of DiAddrRange */ scope;
1172b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DiVariable var;
1173b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       all;
11749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt*     ent;
117550fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
11766bd9dc18c043927c1196caba20a327238a179c42florian   const HChar* badness;
11779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
1178e2800c958044937e72eefa371c10ae47ac40e089florian   vg_assert(di && di->admin_tyents);
1179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0) {
1181a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("  ML_(addVar): level %d  %#lx-%#lx  %s :: ",
1182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  level, aMin, aMax, name );
11839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(pp_TyEnt_C_ishly)( di->admin_tyents, typeR );
1184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n  Var=");
1185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GX)(gexpr);
1186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
1187b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (fbGX) {
1188b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("  FrB=");
1189b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(pp_GX)( fbGX );
1190b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("\n");
1191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1192b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("  FrB=none\n");
1193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
1194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
1195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(level >= 0);
1198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(aMin <= aMax);
1199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(name);
1200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(gexpr);
1201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
12029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ent = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL, typeR);
1203e2800c958044937e72eefa371c10ae47ac40e089florian   vg_assert(ent);
12049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ML_(TyEnt__is_type)(ent));
12059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
1206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "Comment_Regarding_Text_Range_Checks" (is referred to elsewhere)
1207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ----------------------------------------------------------------
1208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Ignore any variables whose aMin .. aMax (that is, range of text
1209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      addresses for which they actually exist) falls outside the text
1210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      segment.  Is this indicative of a bug in the reader?  Maybe.
1211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (LATER): instead of restricting strictly to the .text segment,
1212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      be a bit more relaxed, and accept any variable whose text range
1213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      falls inside the r-x mapped area.  This is useful because .text
1214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      is not always the only instruction-carrying segment: others are:
1215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      .init .plt __libc_freeres_fn and .fini.  This implicitly assumes
1216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that those extra sections have the same bias as .text, but that
1217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      seems a reasonable assumption to me. */
1218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* This is assured us by top level steering logic in debuginfo.c,
1219b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      and it is re-checked at the start of
1220b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(read_elf_debug_info). */
1221a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rx_map && di->fsm.have_rw_map);
12226b5625bb609b154766d2e138b61e15655f60b710sewardj   if (level > 0 && ML_(find_rx_mapping)(di, aMin, aMax) == NULL) {
1223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(clo_verbosity) >= 0) {
1224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(message)(Vg_DebugMsg,
1225a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            "warning: addVar: in range %#lx .. %#lx outside "
12266b5625bb609b154766d2e138b61e15655f60b710sewardj            "all rx mapped areas (%s)\n",
12276b5625bb609b154766d2e138b61e15655f60b710sewardj            aMin, aMax, name
1228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         );
1229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
1230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1233b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the type's size is zero (which can mean unknown size), ignore
1234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      it.  We will never be able to actually relate a data address to
1235b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      a data object with zero size, so there's no point in storing
123650fde23467d92281b32dd537d0d9a590263628c3sewardj      info on it.  On 32-bit platforms, also reject types whose size
123750fde23467d92281b32dd537d0d9a590263628c3sewardj      is 2^32 bytes or large.  (It's amazing what junk shows up ..) */
123850fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(di->admin_tyents, typeR);
123950fde23467d92281b32dd537d0d9a590263628c3sewardj
124050fde23467d92281b32dd537d0d9a590263628c3sewardj   badness = NULL;
124150fde23467d92281b32dd537d0d9a590263628c3sewardj   if (mul.b != True)
124250fde23467d92281b32dd537d0d9a590263628c3sewardj      badness = "unknown size";
124350fde23467d92281b32dd537d0d9a590263628c3sewardj   else if (mul.ul == 0)
124450fde23467d92281b32dd537d0d9a590263628c3sewardj      badness = "zero size   ";
124550fde23467d92281b32dd537d0d9a590263628c3sewardj   else if (sizeof(void*) == 4 && mul.ul >= (1ULL<<32))
124650fde23467d92281b32dd537d0d9a590263628c3sewardj      badness = "implausibly large";
124750fde23467d92281b32dd537d0d9a590263628c3sewardj
124850fde23467d92281b32dd537d0d9a590263628c3sewardj   if (badness) {
1249b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      static Int complaints = 10;
1250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(clo_verbosity) >= 2 && complaints > 0) {
1251738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_DebugMsg, "warning: addVar: %s (%s)\n",
125250fde23467d92281b32dd537d0d9a590263628c3sewardj                                   badness, name );
1253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         complaints--;
1254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
1255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo) {
12599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->varinfo = VG_(newXA)( ML_(dinfo_zalloc),
12609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                "di.storage.addVar.1",
12619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                ML_(dinfo_free),
1262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                sizeof(OSet*) );
1263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(level < 256); /* arbitrary; stay sane */
1266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Expand the top level array enough to map this level */
1267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(sizeXA)(di->varinfo) <= level ) {
1268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* nyu;
1269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope = VG_(OSetGen_Create)( offsetof(DiAddrRange,aMin),
1270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   ML_(cmp_for_DiAddrRange_range),
12719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                   ML_(dinfo_zalloc), "di.storage.addVar.2",
12729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                   ML_(dinfo_free) );
1273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0) VG_(printf)("create: scope = %p, adding at %ld\n",
1274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         scope, VG_(sizeXA)(di->varinfo));
1275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(addToXA)( di->varinfo, &scope );
1276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Add a single range covering the entire address space.  At
1277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         level 0 we require this doesn't get split.  At levels above 0
1278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we require that any additions to it cause it to get split.
1279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         All of these invariants get checked both add_var_to_arange
1280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         and after reading is complete, in canonicaliseVarInfo. */
1281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      nyu = VG_(OSetGen_AllocNode)( scope, sizeof(DiAddrRange) );
1282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      nyu->aMin = (Addr)0;
1283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      nyu->aMax = ~(Addr)0;
12849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      nyu->vars = VG_(newXA)( ML_(dinfo_zalloc), "di.storage.addVar.3",
12859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                              ML_(dinfo_free),
1286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              sizeof(DiVariable) );
1287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(OSetGen_Insert)( scope, nyu );
1288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( VG_(sizeXA)(di->varinfo) > level );
1291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   scope = *(OSet**)VG_(indexXA)( di->varinfo, level );
1292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(scope);
1293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   var.name     = name;
12959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   var.typeR    = typeR;
1296b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   var.gexpr    = gexpr;
1297b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   var.fbGX     = fbGX;
1298666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   var.fndn_ix  = fndn_ix;
1299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   var.lineNo   = lineNo;
1300b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   all = aMin == (Addr)0 && aMax == ~(Addr)0;
1302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(level == 0 ? all : !all);
1303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1304b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   add_var_to_arange( /*MOD*/scope, aMin, aMax, &var );
1305b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1307b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1308b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* This really just checks the constructed data structure, as there is
1309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   no canonicalisation to do. */
1310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void canonicaliseVarInfo ( struct _DebugInfo* di )
1311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word i, nInThisScope;
1313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
1315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
1318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange *range, *rangep;
1320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
1321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!scope) continue;
1322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Deal with the global-scope case. */
1324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (i == 0) {
1325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Addr zero = 0;
1326b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(VG_(OSetGen_Size)( scope ) == 1);
1327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         range = VG_(OSetGen_Lookup)( scope, &zero );
1328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(range);
1329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(range->aMin == (Addr)0);
1330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(range->aMax == ~(Addr)0);
1331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
1332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
1333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* All the rest of this is for the local-scope case. */
1335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* iterate over all entries in 'scope' */
1336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      nInThisScope = 0;
13374c245e595b9f6300d3120408ca873f7115d9cc7dnjn      rangep = NULL;
1338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(OSetGen_ResetIter)(scope);
1339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
1340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         range = VG_(OSetGen_Next)(scope);
1341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!range) {
1342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           /* We just saw the last one.  There must have been at
1343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              least one entry in the range. */
1344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           vg_assert(rangep);
1345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           vg_assert(rangep->aMax == ~(Addr)0);
1346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           break;
1347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
1348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(range->aMin <= range->aMax);
1350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(range->vars);
1351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!rangep) {
1353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           /* This is the first entry in the range. */
1354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           vg_assert(range->aMin == 0);
1355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         } else {
1356b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           vg_assert(rangep->aMax + 1 == range->aMin);
1357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
1358b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         rangep = range;
1360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         nInThisScope++;
1361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } /* iterating over ranges in a given scope */
1362b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1363b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* If there's only one entry in this (local) scope, it must
1364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         cover the entire address space (obviously), but it must not
1365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         contain any vars. */
1366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(nInThisScope > 0);
1368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (nInThisScope == 1) {
1369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Addr zero = 0;
1370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(VG_(OSetGen_Size)( scope ) == 1);
1371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         range = VG_(OSetGen_Lookup)( scope, &zero );
1372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(range);
1373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(range->aMin == (Addr)0);
1374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(range->aMax == ~(Addr)0);
1375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(range->vars);
1376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(VG_(sizeXA)(range->vars) == 0);
1377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
1378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } /* iterate over scopes */
1380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1383eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1384eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Canonicalisers                                       ---*/
1385eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1386eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1387eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Sort the symtab by starting address, and emit warnings if any
1388eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   symbols have overlapping address ranges.  We use that old chestnut,
1389eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   shellsort.  Mash the table around so as to establish the property
1390eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   that addresses are in order and the ranges to not overlap.  This
1391eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   facilitates using binary search to map addresses to symbols when we
1392eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   come to query the table.
1393eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
13946bd9dc18c043927c1196caba20a327238a179c42florianstatic Int compare_DiSym ( const void* va, const void* vb )
1395eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13966bd9dc18c043927c1196caba20a327238a179c42florian   const DiSym* a = va;
13976bd9dc18c043927c1196caba20a327238a179c42florian   const DiSym* b = vb;
13984cace66777ca9ee73ea156210c04e9d4cc178395philippe   if (a->avmas.main < b->avmas.main) return -1;
13994cace66777ca9ee73ea156210c04e9d4cc178395philippe   if (a->avmas.main > b->avmas.main) return  1;
1400eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return 0;
1401eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1402eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1403eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1404a5cace0c2a3e212931badbf6398a0cd98393121asewardj/* An address is associated with more than one name.  Which do we
1405a5cace0c2a3e212931badbf6398a0cd98393121asewardj   prefer as the "display" name (that we show the user in stack
1406a5cace0c2a3e212931badbf6398a0cd98393121asewardj   traces)?  In order:
1407eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
140827a0024216fb483fb1d68b8dca116549c7e27385njn   - Prefer "PMPI_<foo>" over "MPI_<foo>".
140927a0024216fb483fb1d68b8dca116549c7e27385njn
1410a5cace0c2a3e212931badbf6398a0cd98393121asewardj   - Else, prefer a non-empty name over an empty one.
141127a0024216fb483fb1d68b8dca116549c7e27385njn
141227a0024216fb483fb1d68b8dca116549c7e27385njn   - Else, prefer a non-whitespace name over an all-whitespace name.
141327a0024216fb483fb1d68b8dca116549c7e27385njn
141427a0024216fb483fb1d68b8dca116549c7e27385njn   - Else, prefer the shorter symbol name.  If the symbol contains a
141527a0024216fb483fb1d68b8dca116549c7e27385njn     version symbol ('@' on Linux, other platforms may differ), which means it
141627a0024216fb483fb1d68b8dca116549c7e27385njn     is versioned, then the length up to the version symbol is used for length
141727a0024216fb483fb1d68b8dca116549c7e27385njn     comparison purposes (so "foo@GLIBC_2.4.2" is considered shorter than
141827a0024216fb483fb1d68b8dca116549c7e27385njn     "foobar").
141927a0024216fb483fb1d68b8dca116549c7e27385njn
142027a0024216fb483fb1d68b8dca116549c7e27385njn   - Else, if two symbols have the same length, prefer a versioned symbol over
142127a0024216fb483fb1d68b8dca116549c7e27385njn     a non-versioned symbol.
142227a0024216fb483fb1d68b8dca116549c7e27385njn
142327a0024216fb483fb1d68b8dca116549c7e27385njn   - Else, use alphabetical ordering.
142427a0024216fb483fb1d68b8dca116549c7e27385njn
1425a5cace0c2a3e212931badbf6398a0cd98393121asewardj   - Otherwise, they must be the same;  use the name with the lower address.
1426eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1427eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Very occasionally this goes wrong (eg. 'memcmp' and 'bcmp' are
1428eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   aliases in glibc, we choose the 'bcmp' symbol because it's shorter,
1429eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   so we can misdescribe memcmp() as bcmp()).  This is hard to avoid.
1430eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   It's mentioned in the FAQ file.
1431a5cace0c2a3e212931badbf6398a0cd98393121asewardj
1432a5cace0c2a3e212931badbf6398a0cd98393121asewardj   Returned value is True if a_name is preferred, False if b_name is
1433a5cace0c2a3e212931badbf6398a0cd98393121asewardj   preferred.
1434eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj */
1435a5cace0c2a3e212931badbf6398a0cd98393121asewardjstatic
1436518850bf0da07ed3e2244e307268ae0fd80e93a8florianBool preferName ( const DebugInfo* di,
14371ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian                  const HChar* a_name, const HChar* b_name,
1438a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  Addr sym_avma/*exposition only*/ )
1439eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1440f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word cmp;
1441f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word vlena, vlenb;		/* length without version */
14421636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar *vpa, *vpb;
1443eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool preferA = False;
1445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool preferB = False;
1446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1447a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(a_name);
1448a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(b_name);
14497293d2530f8c60c1060f9f003e214cc341d35266philippe   // vg_assert(a_name != b_name);
14507293d2530f8c60c1060f9f003e214cc341d35266philippe   // ???? now the pointers can be equal but is that
14517293d2530f8c60c1060f9f003e214cc341d35266philippe   // ???? not the indication of a latent bug ????
1452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1453a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vlena = VG_(strlen)(a_name);
1454a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vlenb = VG_(strlen)(b_name);
1455eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1456a5cace0c2a3e212931badbf6398a0cd98393121asewardj#  if defined(VGO_linux)
1457a5cace0c2a3e212931badbf6398a0cd98393121asewardj#    define VERSION_CHAR '@'
1458a5cace0c2a3e212931badbf6398a0cd98393121asewardj#  elif defined(VGO_darwin)
1459a5cace0c2a3e212931badbf6398a0cd98393121asewardj#    define VERSION_CHAR '$'
1460a5cace0c2a3e212931badbf6398a0cd98393121asewardj#  else
1461a5cace0c2a3e212931badbf6398a0cd98393121asewardj#    error Unknown OS
1462a5cace0c2a3e212931badbf6398a0cd98393121asewardj#  endif
1463a5cace0c2a3e212931badbf6398a0cd98393121asewardj
1464a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vpa = VG_(strchr)(a_name, VERSION_CHAR);
1465a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vpb = VG_(strchr)(b_name, VERSION_CHAR);
146627a0024216fb483fb1d68b8dca116549c7e27385njn
1467a5cace0c2a3e212931badbf6398a0cd98393121asewardj#  undef VERSION_CHAR
1468eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1469eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (vpa)
1470a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vlena = vpa - a_name;
1471eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (vpb)
1472a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vlenb = vpb - b_name;
1473eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1474eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* MPI hack: prefer PMPI_Foo over MPI_Foo */
1475a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (0==VG_(strncmp)(a_name, "MPI_", 4)
1476a5cace0c2a3e212931badbf6398a0cd98393121asewardj       && 0==VG_(strncmp)(b_name, "PMPI_", 5)
1477a5cace0c2a3e212931badbf6398a0cd98393121asewardj       && 0==VG_(strcmp)(a_name, 1+b_name)) {
1478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      preferB = True; goto out;
1479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1480a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (0==VG_(strncmp)(b_name, "MPI_", 4)
1481a5cace0c2a3e212931badbf6398a0cd98393121asewardj       && 0==VG_(strncmp)(a_name, "PMPI_", 5)
1482a5cace0c2a3e212931badbf6398a0cd98393121asewardj       && 0==VG_(strcmp)(b_name, 1+a_name)) {
1483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      preferA = True; goto out;
1484b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1485eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
148627a0024216fb483fb1d68b8dca116549c7e27385njn   /* Prefer non-empty name. */
148727a0024216fb483fb1d68b8dca116549c7e27385njn   if (vlena  &&  !vlenb) {
148827a0024216fb483fb1d68b8dca116549c7e27385njn      preferA = True; goto out;
148927a0024216fb483fb1d68b8dca116549c7e27385njn   }
149027a0024216fb483fb1d68b8dca116549c7e27385njn   if (vlenb  &&  !vlena) {
149127a0024216fb483fb1d68b8dca116549c7e27385njn      preferB = True; goto out;
149227a0024216fb483fb1d68b8dca116549c7e27385njn   }
149327a0024216fb483fb1d68b8dca116549c7e27385njn
149427a0024216fb483fb1d68b8dca116549c7e27385njn   /* Prefer non-whitespace name. */
149527a0024216fb483fb1d68b8dca116549c7e27385njn   {
149627a0024216fb483fb1d68b8dca116549c7e27385njn      Bool blankA = True;
149727a0024216fb483fb1d68b8dca116549c7e27385njn      Bool blankB = True;
14981ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian      const HChar *s;
1499a5cace0c2a3e212931badbf6398a0cd98393121asewardj      s = a_name;
150027a0024216fb483fb1d68b8dca116549c7e27385njn      while (*s) {
150127a0024216fb483fb1d68b8dca116549c7e27385njn         if (!VG_(isspace)(*s++)) {
150227a0024216fb483fb1d68b8dca116549c7e27385njn            blankA = False;
150327a0024216fb483fb1d68b8dca116549c7e27385njn            break;
150427a0024216fb483fb1d68b8dca116549c7e27385njn         }
150527a0024216fb483fb1d68b8dca116549c7e27385njn      }
1506a5cace0c2a3e212931badbf6398a0cd98393121asewardj      s = b_name;
150727a0024216fb483fb1d68b8dca116549c7e27385njn      while (*s) {
150827a0024216fb483fb1d68b8dca116549c7e27385njn         if (!VG_(isspace)(*s++)) {
150927a0024216fb483fb1d68b8dca116549c7e27385njn            blankB = False;
151027a0024216fb483fb1d68b8dca116549c7e27385njn            break;
151127a0024216fb483fb1d68b8dca116549c7e27385njn         }
151227a0024216fb483fb1d68b8dca116549c7e27385njn      }
151327a0024216fb483fb1d68b8dca116549c7e27385njn
151427a0024216fb483fb1d68b8dca116549c7e27385njn      if (!blankA  &&  blankB) {
151527a0024216fb483fb1d68b8dca116549c7e27385njn         preferA = True; goto out;
151627a0024216fb483fb1d68b8dca116549c7e27385njn      }
151727a0024216fb483fb1d68b8dca116549c7e27385njn      if (!blankB  &&  blankA) {
151827a0024216fb483fb1d68b8dca116549c7e27385njn         preferB = True; goto out;
151927a0024216fb483fb1d68b8dca116549c7e27385njn      }
152027a0024216fb483fb1d68b8dca116549c7e27385njn   }
152127a0024216fb483fb1d68b8dca116549c7e27385njn
1522eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Select the shortest unversioned name */
1523b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (vlena < vlenb) {
1524b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      preferA = True; goto out;
1525b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1526b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (vlenb < vlena) {
1527b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      preferB = True; goto out;
1528b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1529eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1530eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Equal lengths; select the versioned name */
1531b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (vpa && !vpb) {
1532b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      preferA = True; goto out;
1533b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1534b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (vpb && !vpa) {
1535b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      preferB = True; goto out;
1536b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1537eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1538eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Either both versioned or neither is versioned; select them
1539eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      alphabetically */
1540a5cace0c2a3e212931badbf6398a0cd98393121asewardj   cmp = VG_(strcmp)(a_name, b_name);
1541b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (cmp < 0) {
1542b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      preferA = True; goto out;
1543b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1544b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (cmp > 0) {
1545b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      preferB = True; goto out;
1546b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1547f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
154827a0024216fb483fb1d68b8dca116549c7e27385njn   /* If we get here, they are the same name. */
154927a0024216fb483fb1d68b8dca116549c7e27385njn
155027a0024216fb483fb1d68b8dca116549c7e27385njn   /* In this case we could choose either (arbitrarily), but might as
1551b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      well choose the one with the lowest DiSym* address, so as to try
1552b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      and make the comparison mechanism more stable (a la sorting
1553b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      parlance).  Also, skip the diagnostic printing in this case. */
1554a5cace0c2a3e212931badbf6398a0cd98393121asewardj   return a_name <= b_name  ? True  : False;
1555b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /*NOTREACHED*/
1557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(0);
1558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj  out:
1559b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (preferA && !preferB) {
1560a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      TRACE_SYMTAB("sym at %#lx: prefer '%s' to '%s'\n",
1561a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   sym_avma, a_name, b_name );
1562a5cace0c2a3e212931badbf6398a0cd98393121asewardj      return True;
1563b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (preferB && !preferA) {
1565a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      TRACE_SYMTAB("sym at %#lx: prefer '%s' to '%s'\n",
1566a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   sym_avma, b_name, a_name );
1567a5cace0c2a3e212931badbf6398a0cd98393121asewardj      return False;
1568b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1569b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /*NOTREACHED*/
1570b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(0);
1571eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1572eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1573a5cace0c2a3e212931badbf6398a0cd98393121asewardj
1574a5cace0c2a3e212931badbf6398a0cd98393121asewardj/* Add the names in FROM to the names in TO. */
1575a5cace0c2a3e212931badbf6398a0cd98393121asewardjstatic
1576518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid add_DiSym_names_to_from ( const DebugInfo* di, DiSym* to,
1577518850bf0da07ed3e2244e307268ae0fd80e93a8florian                               const DiSym* from )
1578a5cace0c2a3e212931badbf6398a0cd98393121asewardj{
1579a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(to->pri_name);
1580a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(from->pri_name);
1581a5cace0c2a3e212931badbf6398a0cd98393121asewardj   /* Figure out how many names there will be in the new combined
1582a5cace0c2a3e212931badbf6398a0cd98393121asewardj      secondary vector. */
15831ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian   const HChar** to_sec   = to->sec_names;
15841ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian   const HChar** from_sec = from->sec_names;
1585a5cace0c2a3e212931badbf6398a0cd98393121asewardj   Word n_new_sec = 1;
1586a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (from_sec) {
1587a5cace0c2a3e212931badbf6398a0cd98393121asewardj      while (*from_sec) {
1588a5cace0c2a3e212931badbf6398a0cd98393121asewardj         n_new_sec++;
1589a5cace0c2a3e212931badbf6398a0cd98393121asewardj         from_sec++;
1590a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
1591a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
1592a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (to_sec) {
1593a5cace0c2a3e212931badbf6398a0cd98393121asewardj      while (*to_sec) {
1594a5cace0c2a3e212931badbf6398a0cd98393121asewardj         n_new_sec++;
1595a5cace0c2a3e212931badbf6398a0cd98393121asewardj         to_sec++;
1596a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
1597a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
1598a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (0)
1599a5cace0c2a3e212931badbf6398a0cd98393121asewardj      TRACE_SYMTAB("merge: -> %ld\n", n_new_sec);
1600a5cace0c2a3e212931badbf6398a0cd98393121asewardj   /* Create the new sec and copy stuff into it, putting the new
1601a5cace0c2a3e212931badbf6398a0cd98393121asewardj      entries at the end. */
16021ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian   const HChar** new_sec = ML_(dinfo_zalloc)( "di.storage.aDntf.1",
16031ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian                                              (n_new_sec+1) * sizeof(HChar*) );
1604a5cace0c2a3e212931badbf6398a0cd98393121asewardj   from_sec = from->sec_names;
1605a5cace0c2a3e212931badbf6398a0cd98393121asewardj   to_sec   = to->sec_names;
1606a5cace0c2a3e212931badbf6398a0cd98393121asewardj   Word i = 0;
1607a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (to_sec) {
1608a5cace0c2a3e212931badbf6398a0cd98393121asewardj      while (*to_sec) {
1609a5cace0c2a3e212931badbf6398a0cd98393121asewardj         new_sec[i++] = *to_sec;
1610a5cace0c2a3e212931badbf6398a0cd98393121asewardj         to_sec++;
1611a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
1612a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
1613a5cace0c2a3e212931badbf6398a0cd98393121asewardj   new_sec[i++] = from->pri_name;
1614a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (from_sec) {
1615a5cace0c2a3e212931badbf6398a0cd98393121asewardj      while (*from_sec) {
1616a5cace0c2a3e212931badbf6398a0cd98393121asewardj         new_sec[i++] = *from_sec;
1617a5cace0c2a3e212931badbf6398a0cd98393121asewardj         from_sec++;
1618a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
1619a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
1620a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(i == n_new_sec);
1621a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(new_sec[i] == NULL);
1622a5cace0c2a3e212931badbf6398a0cd98393121asewardj   /* If we're replacing an existing secondary vector, free it. */
1623a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (to->sec_names) {
1624a5cace0c2a3e212931badbf6398a0cd98393121asewardj      ML_(dinfo_free)(to->sec_names);
1625a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
1626a5cace0c2a3e212931badbf6398a0cd98393121asewardj   to->sec_names = new_sec;
1627a5cace0c2a3e212931badbf6398a0cd98393121asewardj}
1628a5cace0c2a3e212931badbf6398a0cd98393121asewardj
1629a5cace0c2a3e212931badbf6398a0cd98393121asewardj
1630b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void canonicaliseSymtab ( struct _DebugInfo* di )
1631eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1632a5cace0c2a3e212931badbf6398a0cd98393121asewardj   Word  i, j, n_truncated;
1633a5cace0c2a3e212931badbf6398a0cd98393121asewardj   Addr  sta1, sta2, end1, end2, toc1, toc2;
16341ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian   const HChar *pri1, *pri2, **sec1, **sec2;
1635a5cace0c2a3e212931badbf6398a0cd98393121asewardj   Bool  ist1, ist2, isf1, isf2;
1636eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1637eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define SWAP(ty,aa,bb) \
1638eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0)
1639eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->symtab_used == 0)
1641eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return;
1642eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1643a5cace0c2a3e212931badbf6398a0cd98393121asewardj   /* Check initial invariants */
1644a5cace0c2a3e212931badbf6398a0cd98393121asewardj   for (i = 0; i < di->symtab_used; i++) {
1645a5cace0c2a3e212931badbf6398a0cd98393121asewardj      DiSym* sym = &di->symtab[i];
1646a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vg_assert(sym->pri_name);
1647a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vg_assert(!sym->sec_names);
1648a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
1649a5cace0c2a3e212931badbf6398a0cd98393121asewardj
1650a5cace0c2a3e212931badbf6398a0cd98393121asewardj   /* Sort by address. */
1651b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(ssort)(di->symtab, di->symtab_used,
1652b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                          sizeof(*di->symtab), compare_DiSym);
1653eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1654eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  cleanup_more:
1655eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1656426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj   /* BEGIN Detect and "fix" identical address ranges. */
1657a5cace0c2a3e212931badbf6398a0cd98393121asewardj   while (1) {
1658a5cace0c2a3e212931badbf6398a0cd98393121asewardj      Word r, w, n_merged;
1659eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_merged = 0;
1660a5cace0c2a3e212931badbf6398a0cd98393121asewardj      w = 0;
1661426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj      /* A pass merging entries together in the case where they agree
1662426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         on .isText -- that is, either: both are .isText or both are
1663426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         not .isText.  They are merged into a single entry, but both
1664426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         sets of names are preserved, so we end up knowing all the
1665426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         names for that particular address range.*/
1666a5cace0c2a3e212931badbf6398a0cd98393121asewardj      for (r = 1; r < di->symtab_used; r++) {
1667a5cace0c2a3e212931badbf6398a0cd98393121asewardj         vg_assert(w < r);
16684cace66777ca9ee73ea156210c04e9d4cc178395philippe         if (   di->symtab[w].avmas.main == di->symtab[r].avmas.main
16694cace66777ca9ee73ea156210c04e9d4cc178395philippe             && di->symtab[w].size       == di->symtab[r].size
16704cace66777ca9ee73ea156210c04e9d4cc178395philippe             && !!di->symtab[w].isText   == !!di->symtab[r].isText) {
1671eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* merge the two into one */
1672a5cace0c2a3e212931badbf6398a0cd98393121asewardj            n_merged++;
1673d483f8006a37e056d49c0fa131e5103848ce8312philippe            /* Add r names to w if r has secondary names
1674d483f8006a37e056d49c0fa131e5103848ce8312philippe               or r and w primary names differ. */
1675d483f8006a37e056d49c0fa131e5103848ce8312philippe            if (di->symtab[r].sec_names
1676d483f8006a37e056d49c0fa131e5103848ce8312philippe                || (0 != VG_(strcmp)(di->symtab[r].pri_name,
1677d483f8006a37e056d49c0fa131e5103848ce8312philippe                                     di->symtab[w].pri_name))) {
1678d483f8006a37e056d49c0fa131e5103848ce8312philippe               add_DiSym_names_to_from(di, &di->symtab[w], &di->symtab[r]);
1679d483f8006a37e056d49c0fa131e5103848ce8312philippe            }
1680732b3583236d760c7c54cfe6d5ed5b957be96d9dtom            /* mark w as an IFunc if either w or r are */
1681732b3583236d760c7c54cfe6d5ed5b957be96d9dtom            di->symtab[w].isIFunc = di->symtab[w].isIFunc || di->symtab[r].isIFunc;
1682a5cace0c2a3e212931badbf6398a0cd98393121asewardj            /* and use ::pri_names to indicate this slot is no longer in use */
1683a5cace0c2a3e212931badbf6398a0cd98393121asewardj            di->symtab[r].pri_name = NULL;
1684a5cace0c2a3e212931badbf6398a0cd98393121asewardj            if (di->symtab[r].sec_names) {
1685a5cace0c2a3e212931badbf6398a0cd98393121asewardj               ML_(dinfo_free)(di->symtab[r].sec_names);
1686a5cace0c2a3e212931badbf6398a0cd98393121asewardj               di->symtab[r].sec_names = NULL;
1687a5cace0c2a3e212931badbf6398a0cd98393121asewardj            }
1688a5cace0c2a3e212931badbf6398a0cd98393121asewardj            /* Completely zap the entry -- paranoia to make it more
1689a5cace0c2a3e212931badbf6398a0cd98393121asewardj               likely we'll notice if we inadvertantly use it
1690a5cace0c2a3e212931badbf6398a0cd98393121asewardj               again. */
1691a5cace0c2a3e212931badbf6398a0cd98393121asewardj            VG_(memset)(&di->symtab[r], 0, sizeof(DiSym));
1692eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         } else {
1693a5cace0c2a3e212931badbf6398a0cd98393121asewardj            w = r;
1694eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1695eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1696426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj
1697426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj      /* A second pass merging entries together where one .isText but
1698426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         the other isn't.  In such cases, just ignore the non-.isText
1699426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         one (a heuristic hack.) */
1700426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj      for (r = 1; r < di->symtab_used; r++) {
1701426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         /* Either of the symbols might already have been zapped by
1702426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj            the previous pass, so we first have to check that. */
1703426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         if (di->symtab[r-1].pri_name == NULL) continue;
1704426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         if (di->symtab[r-0].pri_name == NULL) continue;
1705426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         /* ok, they are both still valid.  Identical address ranges? */
1706426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         if (di->symtab[r-1].avmas.main != di->symtab[r-0].avmas.main) continue;
1707426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         if (di->symtab[r-1].size       != di->symtab[r-0].size) continue;
1708426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         /* Identical address ranges.  They must disagree on .isText
1709426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj            since if they agreed, the previous pass would have merged
1710426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj            them. */
1711426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         if (di->symtab[r-1].isText && di->symtab[r-0].isText) vg_assert(0);
1712426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         if (!di->symtab[r-1].isText && !di->symtab[r-0].isText) vg_assert(0);
1713426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         Word to_zap  = di->symtab[r-1].isText ? (r-0) : (r-1);
1714426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         Word to_keep = di->symtab[r-1].isText ? (r-1) : (r-0);
1715426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         vg_assert(!di->symtab[to_zap].isText);
1716426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         vg_assert(di->symtab[to_keep].isText);
1717426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         /* Add to_zap's names to to_keep if to_zap has secondary names
1718426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj            or to_zap's and to_keep's primary names differ. */
1719426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         if (di->symtab[to_zap].sec_names
1720426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj             || (0 != VG_(strcmp)(di->symtab[to_zap].pri_name,
1721426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj                                  di->symtab[to_keep].pri_name))) {
1722426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj            add_DiSym_names_to_from(di, &di->symtab[to_keep],
1723426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj                                        &di->symtab[to_zap]);
1724426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         }
1725426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         /* Mark to_zap as not-in use in the same way as in the
1726426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj            previous loop. */
1727426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         di->symtab[to_zap].pri_name = NULL;
1728426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         if (di->symtab[to_zap].sec_names) {
1729426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj            ML_(dinfo_free)(di->symtab[to_zap].sec_names);
1730426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj            di->symtab[to_zap].sec_names = NULL;
1731426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         }
1732426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         VG_(memset)(&di->symtab[to_zap], 0, sizeof(DiSym));
1733426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj         n_merged++;
1734426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj      }
1735426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj
1736f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      TRACE_SYMTAB( "canonicaliseSymtab: %ld symbols merged\n", n_merged);
1737a5cace0c2a3e212931badbf6398a0cd98393121asewardj      if (n_merged == 0)
1738a5cace0c2a3e212931badbf6398a0cd98393121asewardj         break;
1739a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* Now a pass to squeeze out any unused ones */
1740a5cace0c2a3e212931badbf6398a0cd98393121asewardj      w = 0;
1741a5cace0c2a3e212931badbf6398a0cd98393121asewardj      for (r = 0; r < di->symtab_used; r++) {
1742a5cace0c2a3e212931badbf6398a0cd98393121asewardj         vg_assert(w <= r);
1743a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (di->symtab[r].pri_name == NULL)
1744a5cace0c2a3e212931badbf6398a0cd98393121asewardj            continue;
1745a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (w < r) {
1746a5cace0c2a3e212931badbf6398a0cd98393121asewardj            di->symtab[w] = di->symtab[r];
1747a5cace0c2a3e212931badbf6398a0cd98393121asewardj         }
1748a5cace0c2a3e212931badbf6398a0cd98393121asewardj         w++;
1749a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
1750a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vg_assert(w + n_merged == di->symtab_used);
1751a5cace0c2a3e212931badbf6398a0cd98393121asewardj      di->symtab_used = w;
1752426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj   } /* while (1) */
1753426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj   /* END Detect and "fix" identical address ranges. */
1754eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1755426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj   /* BEGIN Detect and "fix" overlapping address ranges. */
1756eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_truncated = 0;
1757eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1758f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (i = 0; i < ((Word)di->symtab_used) -1; i++) {
1759eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
17604cace66777ca9ee73ea156210c04e9d4cc178395philippe      vg_assert(di->symtab[i].avmas.main <= di->symtab[i+1].avmas.main);
1761eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1762eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Check for common (no overlap) case. */
17634cace66777ca9ee73ea156210c04e9d4cc178395philippe      if (di->symtab[i].avmas.main + di->symtab[i].size
17644cace66777ca9ee73ea156210c04e9d4cc178395philippe          <= di->symtab[i+1].avmas.main)
1765eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
1766eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1767eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* There's an overlap.  Truncate one or the other. */
1768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->trace_symtab) {
1769eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(printf)("overlapping address ranges in symbol table\n\t");
1770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(ppSym)( i, &di->symtab[i] );
1771eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(printf)("\t");
1772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(ppSym)( i+1, &di->symtab[i+1] );
1773eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(printf)("\n");
1774eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1775eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1776eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Truncate one or the other. */
17774cace66777ca9ee73ea156210c04e9d4cc178395philippe      sta1 = di->symtab[i].avmas.main;
1778a5cace0c2a3e212931badbf6398a0cd98393121asewardj      end1 = sta1 + di->symtab[i].size - 1;
17794cace66777ca9ee73ea156210c04e9d4cc178395philippe      toc1 = GET_TOCPTR_AVMA(di->symtab[i].avmas);
17804cace66777ca9ee73ea156210c04e9d4cc178395philippe      // aren't we missing local_ep here ????
1781a5cace0c2a3e212931badbf6398a0cd98393121asewardj      pri1 = di->symtab[i].pri_name;
1782a5cace0c2a3e212931badbf6398a0cd98393121asewardj      sec1 = di->symtab[i].sec_names;
1783a5cace0c2a3e212931badbf6398a0cd98393121asewardj      ist1 = di->symtab[i].isText;
1784a5cace0c2a3e212931badbf6398a0cd98393121asewardj      isf1 = di->symtab[i].isIFunc;
1785a5cace0c2a3e212931badbf6398a0cd98393121asewardj
17864cace66777ca9ee73ea156210c04e9d4cc178395philippe      sta2 = di->symtab[i+1].avmas.main;
1787a5cace0c2a3e212931badbf6398a0cd98393121asewardj      end2 = sta2 + di->symtab[i+1].size - 1;
17884cace66777ca9ee73ea156210c04e9d4cc178395philippe      toc2 = GET_TOCPTR_AVMA(di->symtab[i+1].avmas);
17894cace66777ca9ee73ea156210c04e9d4cc178395philippe      // aren't we missing local_ep here ????
1790a5cace0c2a3e212931badbf6398a0cd98393121asewardj      pri2 = di->symtab[i+1].pri_name;
1791a5cace0c2a3e212931badbf6398a0cd98393121asewardj      sec2 = di->symtab[i+1].sec_names;
1792a5cace0c2a3e212931badbf6398a0cd98393121asewardj      ist2 = di->symtab[i+1].isText;
1793a5cace0c2a3e212931badbf6398a0cd98393121asewardj      isf2 = di->symtab[i+1].isIFunc;
1794a5cace0c2a3e212931badbf6398a0cd98393121asewardj
1795a5cace0c2a3e212931badbf6398a0cd98393121asewardj      if (sta1 < sta2) {
1796a5cace0c2a3e212931badbf6398a0cd98393121asewardj         end1 = sta2 - 1;
1797eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1798a5cace0c2a3e212931badbf6398a0cd98393121asewardj         vg_assert(sta1 == sta2);
1799a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (end1 > end2) {
1800a5cace0c2a3e212931badbf6398a0cd98393121asewardj            sta1 = end2 + 1;
1801a5cace0c2a3e212931badbf6398a0cd98393121asewardj            SWAP(Addr,sta1,sta2); SWAP(Addr,end1,end2); SWAP(Addr,toc1,toc2);
18021ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian            SWAP(const HChar*,pri1,pri2); SWAP(const HChar**,sec1,sec2);
1803a5cace0c2a3e212931badbf6398a0cd98393121asewardj            SWAP(Bool,ist1,ist2); SWAP(Bool,isf1,isf2);
1804eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         } else
1805a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (end1 < end2) {
1806a5cace0c2a3e212931badbf6398a0cd98393121asewardj            sta2 = end1 + 1;
1807eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         } else {
1808a5cace0c2a3e212931badbf6398a0cd98393121asewardj	   /* end1 == end2.  Identical addr ranges.  We'll eventually wind
1809eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              up back at cleanup_more, which will take care of it. */
1810eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
1811eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
18124cace66777ca9ee73ea156210c04e9d4cc178395philippe      di->symtab[i].avmas.main = sta1;
18134cace66777ca9ee73ea156210c04e9d4cc178395philippe      di->symtab[i].size       = end1 - sta1 + 1;
18144cace66777ca9ee73ea156210c04e9d4cc178395philippe      SET_TOCPTR_AVMA(di->symtab[i].avmas, toc1);
18154cace66777ca9ee73ea156210c04e9d4cc178395philippe      // missing local_ep ???
1816a5cace0c2a3e212931badbf6398a0cd98393121asewardj      di->symtab[i].pri_name  = pri1;
1817a5cace0c2a3e212931badbf6398a0cd98393121asewardj      di->symtab[i].sec_names = sec1;
1818a5cace0c2a3e212931badbf6398a0cd98393121asewardj      di->symtab[i].isText    = ist1;
1819a5cace0c2a3e212931badbf6398a0cd98393121asewardj      di->symtab[i].isIFunc   = isf1;
1820a5cace0c2a3e212931badbf6398a0cd98393121asewardj
18214cace66777ca9ee73ea156210c04e9d4cc178395philippe      di->symtab[i+1].avmas.main = sta2;
18224cace66777ca9ee73ea156210c04e9d4cc178395philippe      di->symtab[i+1].size       = end2 - sta2 + 1;
18234cace66777ca9ee73ea156210c04e9d4cc178395philippe      SET_TOCPTR_AVMA(di->symtab[i+1].avmas, toc2);
18244cace66777ca9ee73ea156210c04e9d4cc178395philippe      // missing local_ep ???
1825a5cace0c2a3e212931badbf6398a0cd98393121asewardj      di->symtab[i+1].pri_name  = pri2;
1826a5cace0c2a3e212931badbf6398a0cd98393121asewardj      di->symtab[i+1].sec_names = sec2;
1827a5cace0c2a3e212931badbf6398a0cd98393121asewardj      di->symtab[i+1].isText    = ist2;
1828a5cace0c2a3e212931badbf6398a0cd98393121asewardj      di->symtab[i+1].isIFunc   = isf2;
1829a5cace0c2a3e212931badbf6398a0cd98393121asewardj
1830a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vg_assert(sta1 <= sta2);
1831b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->symtab[i].size > 0);
1832b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->symtab[i+1].size > 0);
1833eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* It may be that the i+1 entry now needs to be moved further
1834eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         along to maintain the address order requirement. */
1835eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      j = i+1;
1836f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      while (j < ((Word)di->symtab_used)-1
18374cace66777ca9ee73ea156210c04e9d4cc178395philippe             && di->symtab[j].avmas.main > di->symtab[j+1].avmas.main) {
1838b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         SWAP(DiSym,di->symtab[j],di->symtab[j+1]);
1839eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         j++;
1840eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1841eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_truncated++;
1842eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1843426e6a2ca4c94127fdbb0d0f9e89a831695f6cdbsewardj   /* END Detect and "fix" overlapping address ranges. */
1844eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1845eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (n_truncated > 0) goto cleanup_more;
1846eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1847eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Ensure relevant postconditions hold. */
1848f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (i = 0; i < ((Word)di->symtab_used)-1; i++) {
1849eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* No zero-sized symbols. */
1850b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->symtab[i].size > 0);
1851eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* In order. */
18524cace66777ca9ee73ea156210c04e9d4cc178395philippe      vg_assert(di->symtab[i].avmas.main < di->symtab[i+1].avmas.main);
1853eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* No overlaps. */
18544cace66777ca9ee73ea156210c04e9d4cc178395philippe      vg_assert(di->symtab[i].avmas.main + di->symtab[i].size - 1
18554cace66777ca9ee73ea156210c04e9d4cc178395philippe                < di->symtab[i+1].avmas.main);
1856a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* Names are sane(ish) */
1857a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vg_assert(di->symtab[i].pri_name);
1858a5cace0c2a3e212931badbf6398a0cd98393121asewardj      if (di->symtab[i].sec_names) {
1859a5cace0c2a3e212931badbf6398a0cd98393121asewardj         vg_assert(di->symtab[i].sec_names[0]);
1860a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
1861a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
1862a5cace0c2a3e212931badbf6398a0cd98393121asewardj
1863a5cace0c2a3e212931badbf6398a0cd98393121asewardj   /* For each symbol that has more than one name, use preferName to
1864a5cace0c2a3e212931badbf6398a0cd98393121asewardj      select the primary name.  This is a complete kludge in that
1865a5cace0c2a3e212931badbf6398a0cd98393121asewardj      doing it properly requires making a total ordering on the
1866a5cace0c2a3e212931badbf6398a0cd98393121asewardj      candidate names, whilst what we have to work with is an ad-hoc
1867a5cace0c2a3e212931badbf6398a0cd98393121asewardj      binary relation (preferName) that certainly doesn't have the
1868a5cace0c2a3e212931badbf6398a0cd98393121asewardj      relevant transitivity etc properties that are needed to induce a
1869a5cace0c2a3e212931badbf6398a0cd98393121asewardj      legitimate total order.  Doesn't matter though if it doesn't
1870a5cace0c2a3e212931badbf6398a0cd98393121asewardj      always work right since this is only used to generate names to
1871a5cace0c2a3e212931badbf6398a0cd98393121asewardj      show the user. */
1872a5cace0c2a3e212931badbf6398a0cd98393121asewardj   for (i = 0; i < ((Word)di->symtab_used)-1; i++) {
1873a5cace0c2a3e212931badbf6398a0cd98393121asewardj      DiSym*  sym = &di->symtab[i];
18741ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian      const HChar** sec = sym->sec_names;
1875a5cace0c2a3e212931badbf6398a0cd98393121asewardj      if (!sec)
1876a5cace0c2a3e212931badbf6398a0cd98393121asewardj         continue;
1877a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* Slow but simple.  Copy all the cands into a temp array,
1878a5cace0c2a3e212931badbf6398a0cd98393121asewardj         choose the primary name, and copy them all back again. */
1879a5cace0c2a3e212931badbf6398a0cd98393121asewardj      Word n_tmp = 1;
1880a5cace0c2a3e212931badbf6398a0cd98393121asewardj      while (*sec) { n_tmp++; sec++; }
1881a5cace0c2a3e212931badbf6398a0cd98393121asewardj      j = 0;
18821ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian      const HChar** tmp = ML_(dinfo_zalloc)( "di.storage.cS.1",
18831ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian                                             (n_tmp+1) * sizeof(HChar*) );
1884a5cace0c2a3e212931badbf6398a0cd98393121asewardj      tmp[j++] = sym->pri_name;
1885a5cace0c2a3e212931badbf6398a0cd98393121asewardj      sec = sym->sec_names;
1886a5cace0c2a3e212931badbf6398a0cd98393121asewardj      while (*sec) { tmp[j++] = *sec; sec++; }
1887a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vg_assert(j == n_tmp);
1888a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vg_assert(tmp[n_tmp] == NULL); /* because of zalloc */
1889a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* Choose the most favoured. */
1890a5cace0c2a3e212931badbf6398a0cd98393121asewardj      Word best = 0;
1891a5cace0c2a3e212931badbf6398a0cd98393121asewardj      for (j = 1; j < n_tmp; j++) {
18924cace66777ca9ee73ea156210c04e9d4cc178395philippe         if (preferName(di, tmp[best], tmp[j], di->symtab[i].avmas.main)) {
1893a5cace0c2a3e212931badbf6398a0cd98393121asewardj            /* best is unchanged */
1894a5cace0c2a3e212931badbf6398a0cd98393121asewardj         } else {
1895a5cace0c2a3e212931badbf6398a0cd98393121asewardj            best = j;
1896a5cace0c2a3e212931badbf6398a0cd98393121asewardj         }
1897a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
1898a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vg_assert(best >= 0 && best < n_tmp);
1899a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* Copy back */
1900a5cace0c2a3e212931badbf6398a0cd98393121asewardj      sym->pri_name = tmp[best];
19011ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian      const HChar** cursor = sym->sec_names;
1902a5cace0c2a3e212931badbf6398a0cd98393121asewardj      for (j = 0; j < n_tmp; j++) {
1903a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (j == best)
1904a5cace0c2a3e212931badbf6398a0cd98393121asewardj            continue;
1905a5cace0c2a3e212931badbf6398a0cd98393121asewardj         *cursor = tmp[j];
1906a5cace0c2a3e212931badbf6398a0cd98393121asewardj         cursor++;
1907a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
1908a5cace0c2a3e212931badbf6398a0cd98393121asewardj      vg_assert(*cursor == NULL);
1909a5cace0c2a3e212931badbf6398a0cd98393121asewardj      ML_(dinfo_free)( tmp );
1910eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1911a5cace0c2a3e212931badbf6398a0cd98393121asewardj
1912eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef SWAP
1913eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1914eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1915eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
191659e1f3c79e870a978d24add86db6d8c5450c8b63philippestatic DiLoc* sorting_loctab = NULL;
191759e1f3c79e870a978d24add86db6d8c5450c8b63philippestatic Int compare_DiLoc_via_ix ( const void* va, const void* vb )
1918eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
19198eebf23c35d97489c0d3c8b41dd542e00ae6acbdflorian   const DiLoc* a = &sorting_loctab[*(const UInt*)va];
19208eebf23c35d97489c0d3c8b41dd542e00ae6acbdflorian   const DiLoc* b = &sorting_loctab[*(const UInt*)vb];
1921eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (a->addr < b->addr) return -1;
1922eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (a->addr > b->addr) return  1;
1923eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return 0;
1924eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
192559e1f3c79e870a978d24add86db6d8c5450c8b63philippestatic void sort_loctab_and_loctab_fndn_ix (struct _DebugInfo* di )
192659e1f3c79e870a978d24add86db6d8c5450c8b63philippe{
192759e1f3c79e870a978d24add86db6d8c5450c8b63philippe   /* We have to sort the array loctab by addr
192859e1f3c79e870a978d24add86db6d8c5450c8b63philippe      together with its "parallel" array loctab_fndn_ix.
192959e1f3c79e870a978d24add86db6d8c5450c8b63philippe      We first build sort_ix : an array of indexes in loctab,
193059e1f3c79e870a978d24add86db6d8c5450c8b63philippe      that we sort by loctab address. Then we can reorder both
193159e1f3c79e870a978d24add86db6d8c5450c8b63philippe      arrays according to sort_ix. */
193259e1f3c79e870a978d24add86db6d8c5450c8b63philippe   UInt *sort_ix = ML_(dinfo_zalloc)("di.storage.six",
193359e1f3c79e870a978d24add86db6d8c5450c8b63philippe                                     di->loctab_used*sizeof(UInt));
193459e1f3c79e870a978d24add86db6d8c5450c8b63philippe   Word i, j, k;
193559e1f3c79e870a978d24add86db6d8c5450c8b63philippe
193659e1f3c79e870a978d24add86db6d8c5450c8b63philippe   for (i = 0; i < di->loctab_used; i++) sort_ix[i] = i;
193759e1f3c79e870a978d24add86db6d8c5450c8b63philippe   sorting_loctab = di->loctab;
193859e1f3c79e870a978d24add86db6d8c5450c8b63philippe   VG_(ssort)(sort_ix, di->loctab_used,
193959e1f3c79e870a978d24add86db6d8c5450c8b63philippe              sizeof(*sort_ix), compare_DiLoc_via_ix);
194059e1f3c79e870a978d24add86db6d8c5450c8b63philippe   sorting_loctab = NULL;
194159e1f3c79e870a978d24add86db6d8c5450c8b63philippe
194259e1f3c79e870a978d24add86db6d8c5450c8b63philippe   // Permute in place, using the sort_ix.
194359e1f3c79e870a978d24add86db6d8c5450c8b63philippe   for (i=0; i < di->loctab_used; i++) {
194459e1f3c79e870a978d24add86db6d8c5450c8b63philippe      DiLoc tmp_diloc;
194559e1f3c79e870a978d24add86db6d8c5450c8b63philippe      UInt  tmp_fndn_ix;
194659e1f3c79e870a978d24add86db6d8c5450c8b63philippe
194759e1f3c79e870a978d24add86db6d8c5450c8b63philippe      if (i == sort_ix[i])
194859e1f3c79e870a978d24add86db6d8c5450c8b63philippe         continue; // i already at the good place
194959e1f3c79e870a978d24add86db6d8c5450c8b63philippe
195059e1f3c79e870a978d24add86db6d8c5450c8b63philippe      tmp_diloc = di->loctab[i];
195159e1f3c79e870a978d24add86db6d8c5450c8b63philippe      tmp_fndn_ix = ML_(fndn_ix)(di, i);
195259e1f3c79e870a978d24add86db6d8c5450c8b63philippe      j = i;
195359e1f3c79e870a978d24add86db6d8c5450c8b63philippe      for (;;) {
195459e1f3c79e870a978d24add86db6d8c5450c8b63philippe         k = sort_ix[j];
195559e1f3c79e870a978d24add86db6d8c5450c8b63philippe         sort_ix[j] = j;
195659e1f3c79e870a978d24add86db6d8c5450c8b63philippe         if (k == i)
195759e1f3c79e870a978d24add86db6d8c5450c8b63philippe            break;
195859e1f3c79e870a978d24add86db6d8c5450c8b63philippe         di->loctab[j] = di->loctab[k];
195959e1f3c79e870a978d24add86db6d8c5450c8b63philippe         set_fndn_ix (di, j, ML_(fndn_ix)(di, k));
196059e1f3c79e870a978d24add86db6d8c5450c8b63philippe         j = k;
196159e1f3c79e870a978d24add86db6d8c5450c8b63philippe      }
196259e1f3c79e870a978d24add86db6d8c5450c8b63philippe      di->loctab[j] = tmp_diloc;
196359e1f3c79e870a978d24add86db6d8c5450c8b63philippe      set_fndn_ix (di, j, tmp_fndn_ix);
196459e1f3c79e870a978d24add86db6d8c5450c8b63philippe   }
196559e1f3c79e870a978d24add86db6d8c5450c8b63philippe   ML_(dinfo_free)(sort_ix);
196659e1f3c79e870a978d24add86db6d8c5450c8b63philippe}
1967eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
196859e1f3c79e870a978d24add86db6d8c5450c8b63philippe/* Sort the location table by starting address.  Mash the table around
196959e1f3c79e870a978d24add86db6d8c5450c8b63philippe   so as to establish the property that addresses are in order and the
197059e1f3c79e870a978d24add86db6d8c5450c8b63philippe   ranges do not overlap.  This facilitates using binary search to map
197159e1f3c79e870a978d24add86db6d8c5450c8b63philippe   addresses to locations when we come to query the table.
197259e1f3c79e870a978d24add86db6d8c5450c8b63philippe*/
1973b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void canonicaliseLoctab ( struct _DebugInfo* di )
1974eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1975f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word i, j;
1976eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1977b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->loctab_used == 0)
1978eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return;
1979eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
198059e1f3c79e870a978d24add86db6d8c5450c8b63philippe   /* sort loctab and loctab_fndn_ix by addr. */
198159e1f3c79e870a978d24add86db6d8c5450c8b63philippe   sort_loctab_and_loctab_fndn_ix (di);
1982eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1983eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* If two adjacent entries overlap, truncate the first. */
1984f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (i = 0; i < ((Word)di->loctab_used)-1; i++) {
1985b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->loctab[i].size < 10000);
1986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->loctab[i].addr + di->loctab[i].size > di->loctab[i+1].addr) {
1987eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* Do this in signed int32 because the actual .size fields
1988eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            are only 12 bits. */
1989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int new_size = di->loctab[i+1].addr - di->loctab[i].addr;
1990eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (new_size < 0) {
1991b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->loctab[i].size = 0;
1992eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         } else
1993eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (new_size > MAX_LOC_SIZE) {
1994b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           di->loctab[i].size = MAX_LOC_SIZE;
1995eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         } else {
1996b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           di->loctab[i].size = (UShort)new_size;
1997eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1998eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1999eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2000eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2001eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Zap any zero-sized entries resulting from the truncation
2002eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      process. */
2003eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   j = 0;
2004f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (i = 0; i < (Word)di->loctab_used; i++) {
2005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->loctab[i].size > 0) {
200659e1f3c79e870a978d24add86db6d8c5450c8b63philippe         if (j != i) {
2007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->loctab[j] = di->loctab[i];
200859e1f3c79e870a978d24add86db6d8c5450c8b63philippe            set_fndn_ix(di, j, ML_(fndn_ix)(di, i));
200959e1f3c79e870a978d24add86db6d8c5450c8b63philippe         }
2010eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         j++;
2011eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2012eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2013b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di->loctab_used = j;
2014eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2015eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Ensure relevant postconditions hold. */
2016f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (i = 0; i < ((Word)di->loctab_used)-1; i++) {
201759e1f3c79e870a978d24add86db6d8c5450c8b63philippe      if (0)
201859e1f3c79e870a978d24add86db6d8c5450c8b63philippe         VG_(printf)("%lu  0x%p  lno:%d sz:%d fndn_ix:%d  i+1 0x%p\n",
201959e1f3c79e870a978d24add86db6d8c5450c8b63philippe                     i,
202059e1f3c79e870a978d24add86db6d8c5450c8b63philippe                     (void*)di->loctab[i].addr,
202159e1f3c79e870a978d24add86db6d8c5450c8b63philippe                     di->loctab[i].lineno,
202259e1f3c79e870a978d24add86db6d8c5450c8b63philippe                     di->loctab[i].size,
202359e1f3c79e870a978d24add86db6d8c5450c8b63philippe                     ML_(fndn_ix)(di, i),
202459e1f3c79e870a978d24add86db6d8c5450c8b63philippe                     (void*)di->loctab[i+1].addr);
202559e1f3c79e870a978d24add86db6d8c5450c8b63philippe
2026eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* No zero-sized symbols. */
2027b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->loctab[i].size > 0);
2028eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* In order. */
2029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->loctab[i].addr < di->loctab[i+1].addr);
2030eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* No overlaps. */
2031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->loctab[i].addr + di->loctab[i].size - 1
2032b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                < di->loctab[i+1].addr);
2033eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2034796e4b25100561a9e953cfe4dad83130b0153ce5sewardj
2035796e4b25100561a9e953cfe4dad83130b0153ce5sewardj   /* Free up unused space at the end of the table. */
2036796e4b25100561a9e953cfe4dad83130b0153ce5sewardj   shrinkLocTab(di);
2037eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2038eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2039a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/* Sort the inlined call table by starting address.  Mash the table around
2040a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   so as to establish the property that addresses are in order.
2041a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   This facilitates using binary search to map addresses to locations when
2042a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   we come to query the table.
2043a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Note : ranges can overlap, multiple ranges can start at an address,
2044a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   multiple ranges can end at an address.
2045a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe*/
2046a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic Int compare_DiInlLoc ( const void* va, const void* vb )
2047a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
2048a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   const DiInlLoc* a = va;
2049a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   const DiInlLoc* b = vb;
2050a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (a->addr_lo < b->addr_lo) return -1;
2051a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (a->addr_lo > b->addr_lo) return  1;
2052a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return 0;
2053a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
2054a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2055a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic void canonicaliseInltab ( struct _DebugInfo* di )
2056a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
2057a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word i;
2058a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2059a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (di->inltab_used == 0)
2060a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return;
2061a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2062a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* Sort by start address. */
2063a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   VG_(ssort)(di->inltab, di->inltab_used,
2064a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                          sizeof(*di->inltab), compare_DiInlLoc);
2065a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2066a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* Ensure relevant postconditions hold. */
2067a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (i = 0; i < ((Word)di->inltab_used)-1; i++) {
2068a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      /* No zero-sized inlined call. */
2069a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      vg_assert(di->inltab[i].addr_lo < di->inltab[i].addr_hi);
2070a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      /* In order, but we can have duplicates and overlapping ranges. */
2071a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      vg_assert(di->inltab[i].addr_lo <= di->inltab[i+1].addr_lo);
2072a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
2073a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2074a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* Free up unused space at the end of the table. */
2075a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   shrinkInlTab(di);
2076a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
2077a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2078eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
20795c3dba227192de63d86f65ec7d9597c132818c37philippe/* Sort the call-frame-info cfsi_rd by starting address.  Mash the table
2080eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   around so as to establish the property that addresses are in order
2081eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and the ranges do not overlap.  This facilitates using binary
2082eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search to map addresses to locations when we come to query the
2083eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   table.
2084eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2085eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Also, set cfisi_minaddr and cfisi_maxaddr to be the min and max of
2086eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   any of the address ranges contained in cfisi[0 .. cfisi_used-1], so
2087eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   as to facilitate rapidly skipping this SegInfo when looking for an
2088eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   address which falls outside that range.
2089eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
20906bd9dc18c043927c1196caba20a327238a179c42florianstatic Int compare_DiCfSI ( const void* va, const void* vb )
2091eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
20926bd9dc18c043927c1196caba20a327238a179c42florian   const DiCfSI* a = va;
20936bd9dc18c043927c1196caba20a327238a179c42florian   const DiCfSI* b = vb;
2094eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (a->base < b->base) return -1;
2095eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (a->base > b->base) return  1;
2096eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return 0;
2097eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2098eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2099518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic void get_cfsi_rd_stats ( const DebugInfo* di,
21005c3dba227192de63d86f65ec7d9597c132818c37philippe                                UWord *n_mergeables, UWord *n_holes )
21015c3dba227192de63d86f65ec7d9597c132818c37philippe{
21025c3dba227192de63d86f65ec7d9597c132818c37philippe   Word i;
21035c3dba227192de63d86f65ec7d9597c132818c37philippe
21045c3dba227192de63d86f65ec7d9597c132818c37philippe   *n_mergeables = 0;
21055c3dba227192de63d86f65ec7d9597c132818c37philippe   *n_holes = 0;
21065c3dba227192de63d86f65ec7d9597c132818c37philippe
21075c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert (di->cfsi_used == 0 || di->cfsi_rd);
21085c3dba227192de63d86f65ec7d9597c132818c37philippe   for (i = 1; i < (Word)di->cfsi_used; i++) {
21095c3dba227192de63d86f65ec7d9597c132818c37philippe      Addr here_min = di->cfsi_rd[i].base;
21105c3dba227192de63d86f65ec7d9597c132818c37philippe      Addr prev_max = di->cfsi_rd[i-1].base + di->cfsi_rd[i-1].len - 1;
21115c3dba227192de63d86f65ec7d9597c132818c37philippe      Addr sep = here_min - prev_max;
21125c3dba227192de63d86f65ec7d9597c132818c37philippe      if (sep > 1)
21135c3dba227192de63d86f65ec7d9597c132818c37philippe         (*n_holes)++;
21145c3dba227192de63d86f65ec7d9597c132818c37philippe      if (sep == 1 && di->cfsi_rd[i-1].cfsi_m_ix == di->cfsi_rd[i].cfsi_m_ix)
21155c3dba227192de63d86f65ec7d9597c132818c37philippe         (*n_mergeables)++;
21165c3dba227192de63d86f65ec7d9597c132818c37philippe   }
21175c3dba227192de63d86f65ec7d9597c132818c37philippe}
21185c3dba227192de63d86f65ec7d9597c132818c37philippe
21193c9cf3442185b5891e15450d6e3058aeff6796fetomvoid ML_(canonicaliseCFI) ( struct _DebugInfo* di )
2120eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2121f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word  i, j;
2122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   const Addr minAvma = 0;
2123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   const Addr maxAvma = ~minAvma;
2124eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Note: take care in here.  di->cfsi can be NULL, in which
2126eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      case _used and _size fields will be zero. */
21275c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_rd == NULL) {
2128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->cfsi_used == 0);
2129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->cfsi_size == 0);
21305c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(di->cfsi_m_pool == NULL);
21315c3dba227192de63d86f65ec7d9597c132818c37philippe   } else {
21325c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(di->cfsi_size != 0);
21335c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(di->cfsi_m_pool != NULL);
2134eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2135eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Set cfsi_minavma and cfsi_maxavma to summarise the entire
21375c3dba227192de63d86f65ec7d9597c132818c37philippe      address range contained in cfsi_rd[0 .. cfsi_used-1]. */
2138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di->cfsi_minavma = maxAvma;
2139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di->cfsi_maxavma = minAvma;
2140f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (i = 0; i < (Word)di->cfsi_used; i++) {
21415c3dba227192de63d86f65ec7d9597c132818c37philippe      Addr here_min = di->cfsi_rd[i].base;
21425c3dba227192de63d86f65ec7d9597c132818c37philippe      Addr here_max = di->cfsi_rd[i].base + di->cfsi_rd[i].len - 1;
2143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (here_min < di->cfsi_minavma)
2144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->cfsi_minavma = here_min;
2145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (here_max > di->cfsi_maxavma)
2146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->cfsi_maxavma = here_max;
2147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->trace_cfi)
2150f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      VG_(printf)("canonicaliseCfiSI: %ld entries, %#lx .. %#lx\n",
2151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  di->cfsi_used,
2152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	          di->cfsi_minavma, di->cfsi_maxavma);
2153eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
21545c3dba227192de63d86f65ec7d9597c132818c37philippe   /* Sort the cfsi_rd array by base address. */
21555c3dba227192de63d86f65ec7d9597c132818c37philippe   VG_(ssort)(di->cfsi_rd, di->cfsi_used, sizeof(*di->cfsi_rd), compare_DiCfSI);
2156eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2157eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* If two adjacent entries overlap, truncate the first. */
2158f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (i = 0; i < (Word)di->cfsi_used-1; i++) {
21595c3dba227192de63d86f65ec7d9597c132818c37philippe      if (di->cfsi_rd[i].base + di->cfsi_rd[i].len > di->cfsi_rd[i+1].base) {
21605c3dba227192de63d86f65ec7d9597c132818c37philippe         Word new_len = di->cfsi_rd[i+1].base - di->cfsi_rd[i].base;
2161eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* how could it be otherwise?  The entries are sorted by the
2162eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            .base field. */
2163eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(new_len >= 0);
21645c3dba227192de63d86f65ec7d9597c132818c37philippe	 vg_assert(new_len <= di->cfsi_rd[i].len);
21655c3dba227192de63d86f65ec7d9597c132818c37philippe         di->cfsi_rd[i].len = new_len;
2166eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2167eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2168eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2169eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Zap any zero-sized entries resulting from the truncation
2170eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      process. */
2171eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   j = 0;
2172f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (i = 0; i < (Word)di->cfsi_used; i++) {
21735c3dba227192de63d86f65ec7d9597c132818c37philippe      if (di->cfsi_rd[i].len > 0) {
2174eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (j != i)
21755c3dba227192de63d86f65ec7d9597c132818c37philippe            di->cfsi_rd[j] = di->cfsi_rd[i];
2176eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         j++;
2177eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2178eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* VG_(printf)("XXXXXXXXXXXXX %d %d\n", di->cfsi_used, j); */
2180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di->cfsi_used = j;
2181eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2182eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* Ensure relevant postconditions hold. */
2183f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (i = 0; i < (Word)di->cfsi_used; i++) {
2184eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* No zero-length ranges. */
21855c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(di->cfsi_rd[i].len > 0);
2186eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Makes sense w.r.t. summary address range */
21875c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(di->cfsi_rd[i].base >= di->cfsi_minavma);
21885c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(di->cfsi_rd[i].base + di->cfsi_rd[i].len - 1
2189b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                <= di->cfsi_maxavma);
2190eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (i < di->cfsi_used - 1) {
2192eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /*
2193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!(di->cfsi[i].base < di->cfsi[i+1].base)) {
2194eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(printf)("\nOOO cfsis:\n");
2195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            ML_(ppCfiSI)(&di->cfsi[i]);
2196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            ML_(ppCfiSI)(&di->cfsi[i+1]);
2197eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
2198eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         */
2199eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* In order. */
22005c3dba227192de63d86f65ec7d9597c132818c37philippe         vg_assert(di->cfsi_rd[i].base < di->cfsi_rd[i+1].base);
2201eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* No overlaps. */
22025c3dba227192de63d86f65ec7d9597c132818c37philippe         vg_assert(di->cfsi_rd[i].base + di->cfsi_rd[i].len - 1
22035c3dba227192de63d86f65ec7d9597c132818c37philippe                   < di->cfsi_rd[i+1].base);
22045c3dba227192de63d86f65ec7d9597c132818c37philippe      }
22055c3dba227192de63d86f65ec7d9597c132818c37philippe   }
22065c3dba227192de63d86f65ec7d9597c132818c37philippe
22072386069c3a117630ebda167cef4ce747a1511eecphilippe   if (VG_(clo_stats) && VG_(clo_verbosity) >= 3) {
22085c3dba227192de63d86f65ec7d9597c132818c37philippe      UWord n_mergeables, n_holes;
22095c3dba227192de63d86f65ec7d9597c132818c37philippe      get_cfsi_rd_stats (di, &n_mergeables, &n_holes);
22105c3dba227192de63d86f65ec7d9597c132818c37philippe      VG_(dmsg)("CFSI total %lu mergeables %lu holes %lu uniq cfsi_m %u\n",
22115c3dba227192de63d86f65ec7d9597c132818c37philippe                di->cfsi_used, n_mergeables, n_holes,
221205c459ea63c50a072cf1eb0868590e9c0b362f30philippe                di->cfsi_m_pool ? VG_(sizeDedupPA) (di->cfsi_m_pool) : 0);
22135c3dba227192de63d86f65ec7d9597c132818c37philippe   }
22145c3dba227192de63d86f65ec7d9597c132818c37philippe}
22155c3dba227192de63d86f65ec7d9597c132818c37philippe
22165c3dba227192de63d86f65ec7d9597c132818c37philippevoid ML_(finish_CFSI_arrays) ( struct _DebugInfo* di )
22175c3dba227192de63d86f65ec7d9597c132818c37philippe{
22185c3dba227192de63d86f65ec7d9597c132818c37philippe   UWord n_mergeables, n_holes;
22195c3dba227192de63d86f65ec7d9597c132818c37philippe   UWord new_used;
22205c3dba227192de63d86f65ec7d9597c132818c37philippe   UWord i;
22215c3dba227192de63d86f65ec7d9597c132818c37philippe   UWord pos;
22225c3dba227192de63d86f65ec7d9597c132818c37philippe   UWord f_mergeables, f_holes;
22235c3dba227192de63d86f65ec7d9597c132818c37philippe   UInt sz_cfsi_m_pool;
22245c3dba227192de63d86f65ec7d9597c132818c37philippe
22255c3dba227192de63d86f65ec7d9597c132818c37philippe   get_cfsi_rd_stats (di, &n_mergeables, &n_holes);
22265c3dba227192de63d86f65ec7d9597c132818c37philippe
22275c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_used == 0) {
22285c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert (di->cfsi_rd == NULL);
22295c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert (di->cfsi_m_pool == NULL);
22305c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert (n_mergeables == 0);
22315c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert (n_holes == 0);
22325c3dba227192de63d86f65ec7d9597c132818c37philippe      return;
22335c3dba227192de63d86f65ec7d9597c132818c37philippe   }
22345c3dba227192de63d86f65ec7d9597c132818c37philippe
22355c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert (di->cfsi_used > n_mergeables);
22365c3dba227192de63d86f65ec7d9597c132818c37philippe   new_used = di->cfsi_used - n_mergeables + n_holes;
22375c3dba227192de63d86f65ec7d9597c132818c37philippe
22385c3dba227192de63d86f65ec7d9597c132818c37philippe   sz_cfsi_m_pool = VG_(sizeDedupPA)(di->cfsi_m_pool);
22395c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert (sz_cfsi_m_pool > 0);
22405c3dba227192de63d86f65ec7d9597c132818c37philippe   if (sz_cfsi_m_pool <= 255)
224159e1f3c79e870a978d24add86db6d8c5450c8b63philippe      di->sizeof_cfsi_m_ix = 1;
22425c3dba227192de63d86f65ec7d9597c132818c37philippe   else if (sz_cfsi_m_pool <= 65535)
224359e1f3c79e870a978d24add86db6d8c5450c8b63philippe      di->sizeof_cfsi_m_ix = 2;
22445c3dba227192de63d86f65ec7d9597c132818c37philippe   else
224559e1f3c79e870a978d24add86db6d8c5450c8b63philippe      di->sizeof_cfsi_m_ix = 4;
22465c3dba227192de63d86f65ec7d9597c132818c37philippe
22475c3dba227192de63d86f65ec7d9597c132818c37philippe   di->cfsi_base = ML_(dinfo_zalloc)( "di.storage.finCfSI.1",
22485c3dba227192de63d86f65ec7d9597c132818c37philippe                                       new_used * sizeof(Addr) );
22495c3dba227192de63d86f65ec7d9597c132818c37philippe   di->cfsi_m_ix = ML_(dinfo_zalloc)( "di.storage.finCfSI.2",
225059e1f3c79e870a978d24add86db6d8c5450c8b63philippe                                      new_used * sizeof(UChar)*di->sizeof_cfsi_m_ix);
22515c3dba227192de63d86f65ec7d9597c132818c37philippe
22525c3dba227192de63d86f65ec7d9597c132818c37philippe   pos = 0;
22535c3dba227192de63d86f65ec7d9597c132818c37philippe   f_mergeables = 0;
22545c3dba227192de63d86f65ec7d9597c132818c37philippe   f_holes = 0;
22555c3dba227192de63d86f65ec7d9597c132818c37philippe   for (i = 0; i < (Word)di->cfsi_used; i++) {
22565c3dba227192de63d86f65ec7d9597c132818c37philippe      if (i > 0) {
22575c3dba227192de63d86f65ec7d9597c132818c37philippe         Addr here_min = di->cfsi_rd[i].base;
22585c3dba227192de63d86f65ec7d9597c132818c37philippe         Addr prev_max = di->cfsi_rd[i-1].base + di->cfsi_rd[i-1].len - 1;
22595c3dba227192de63d86f65ec7d9597c132818c37philippe         SizeT sep = here_min - prev_max;
22605c3dba227192de63d86f65ec7d9597c132818c37philippe
22615c3dba227192de63d86f65ec7d9597c132818c37philippe         // Skip a mergeable entry.
22625c3dba227192de63d86f65ec7d9597c132818c37philippe         if (sep == 1) {
22635c3dba227192de63d86f65ec7d9597c132818c37philippe            if (di->cfsi_rd[i-1].cfsi_m_ix == di->cfsi_rd[i].cfsi_m_ix) {
22645c3dba227192de63d86f65ec7d9597c132818c37philippe               f_mergeables++;
22655c3dba227192de63d86f65ec7d9597c132818c37philippe               continue;
22665c3dba227192de63d86f65ec7d9597c132818c37philippe            }
22675c3dba227192de63d86f65ec7d9597c132818c37philippe         }
22685c3dba227192de63d86f65ec7d9597c132818c37philippe         // Insert a hole if needed.
22695c3dba227192de63d86f65ec7d9597c132818c37philippe         if (sep > 1) {
22705c3dba227192de63d86f65ec7d9597c132818c37philippe            f_holes++;
22715c3dba227192de63d86f65ec7d9597c132818c37philippe            di->cfsi_base[pos] = prev_max + 1;
227259e1f3c79e870a978d24add86db6d8c5450c8b63philippe            switch (di->sizeof_cfsi_m_ix) {
22735c3dba227192de63d86f65ec7d9597c132818c37philippe               case 1: ((UChar*) di->cfsi_m_ix)[pos] = 0; break;
22745c3dba227192de63d86f65ec7d9597c132818c37philippe               case 2: ((UShort*)di->cfsi_m_ix)[pos] = 0; break;
22755c3dba227192de63d86f65ec7d9597c132818c37philippe               case 4: ((UInt*)  di->cfsi_m_ix)[pos] = 0; break;
22765c3dba227192de63d86f65ec7d9597c132818c37philippe               default: vg_assert(0);
22775c3dba227192de63d86f65ec7d9597c132818c37philippe            }
22785c3dba227192de63d86f65ec7d9597c132818c37philippe            pos++;
22795c3dba227192de63d86f65ec7d9597c132818c37philippe         }
2280eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
22815c3dba227192de63d86f65ec7d9597c132818c37philippe
22825c3dba227192de63d86f65ec7d9597c132818c37philippe      // Insert the cfsi entry i.
22835c3dba227192de63d86f65ec7d9597c132818c37philippe      di->cfsi_base[pos] = di->cfsi_rd[i].base;
228459e1f3c79e870a978d24add86db6d8c5450c8b63philippe      switch (di->sizeof_cfsi_m_ix) {
22855c3dba227192de63d86f65ec7d9597c132818c37philippe         case 1: ((UChar*) di->cfsi_m_ix)[pos] = di->cfsi_rd[i].cfsi_m_ix; break;
22865c3dba227192de63d86f65ec7d9597c132818c37philippe         case 2: ((UShort*)di->cfsi_m_ix)[pos] = di->cfsi_rd[i].cfsi_m_ix; break;
22875c3dba227192de63d86f65ec7d9597c132818c37philippe         case 4: ((UInt*)  di->cfsi_m_ix)[pos] = di->cfsi_rd[i].cfsi_m_ix; break;
22885c3dba227192de63d86f65ec7d9597c132818c37philippe         default: vg_assert(0);
22895c3dba227192de63d86f65ec7d9597c132818c37philippe      }
22905c3dba227192de63d86f65ec7d9597c132818c37philippe      pos++;
2291eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2292eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
22935c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert (f_mergeables == n_mergeables);
22945c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert (f_holes == n_holes);
22955c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert (pos == new_used);
22965c3dba227192de63d86f65ec7d9597c132818c37philippe
22975c3dba227192de63d86f65ec7d9597c132818c37philippe   di->cfsi_used = new_used;
22985c3dba227192de63d86f65ec7d9597c132818c37philippe   di->cfsi_size = new_used;
22995c3dba227192de63d86f65ec7d9597c132818c37philippe   ML_(dinfo_free) (di->cfsi_rd);
23005c3dba227192de63d86f65ec7d9597c132818c37philippe   di->cfsi_rd = NULL;
2301eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2302eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2303eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2304b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Canonicalise the tables held by 'di', in preparation for use.  Call
2305eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   this after finishing adding entries to these tables. */
2306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjvoid ML_(canonicaliseTables) ( struct _DebugInfo* di )
2307eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2308b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   canonicaliseSymtab ( di );
2309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   canonicaliseLoctab ( di );
2310a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   canonicaliseInltab ( di );
23113c9cf3442185b5891e15450d6e3058aeff6796fetom   ML_(canonicaliseCFI) ( di );
23125c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_m_pool)
23135c3dba227192de63d86f65ec7d9597c132818c37philippe      VG_(freezeDedupPA) (di->cfsi_m_pool, ML_(dinfo_shrink_block));
2314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   canonicaliseVarInfo ( di );
23157293d2530f8c60c1060f9f003e214cc341d35266philippe   if (di->strpool)
23160b9d0646949bd382758763664d3bf2d6115993aephilippe      VG_(freezeDedupPA) (di->strpool, ML_(dinfo_shrink_block));
231759e1f3c79e870a978d24add86db6d8c5450c8b63philippe   if (di->fndnpool)
231859e1f3c79e870a978d24add86db6d8c5450c8b63philippe      VG_(freezeDedupPA) (di->fndnpool, ML_(dinfo_shrink_block));
2319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
2323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Searching the tables                                 ---*/
2324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
2325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Find a symbol-table index containing the specified pointer, or -1
2327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if not found.  Binary search.  */
2328eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2329518850bf0da07ed3e2244e307268ae0fd80e93a8florianWord ML_(search_one_symtab) ( const DebugInfo* di, Addr ptr,
2330f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                              Bool match_anywhere_in_sym,
2331f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                              Bool findText )
2332eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2333eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Addr a_mid_lo, a_mid_hi;
2334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word mid, size,
2335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj        lo = 0,
2336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        hi = di->symtab_used-1;
2337eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
2338eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* current unsearched space is from lo to hi, inclusive. */
2339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (lo > hi) return -1; /* not found */
2340eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      mid      = (lo + hi) / 2;
23414cace66777ca9ee73ea156210c04e9d4cc178395philippe      a_mid_lo = di->symtab[mid].avmas.main;
2342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      size = ( match_anywhere_in_sym
2343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             ? di->symtab[mid].size
2344eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj             : 1);
23454cace66777ca9ee73ea156210c04e9d4cc178395philippe      a_mid_hi = ((Addr)di->symtab[mid].avmas.main) + size - 1;
2346eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2347eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (ptr < a_mid_lo) { hi = mid-1; continue; }
2348eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (ptr > a_mid_hi) { lo = mid+1; continue; }
2349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
2350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Found a symbol with the correct address range.  But is it
2351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of the right kind (text vs data) ? */
2352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (  findText   &&   di->symtab[mid].isText  ) return mid;
2353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if ( (!findText) && (!di->symtab[mid].isText) ) return mid;
2354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return -1;
2355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2359eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Find a location-table index containing the specified pointer, or -1
2360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if not found.  Binary search.  */
2361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2362518850bf0da07ed3e2244e307268ae0fd80e93a8florianWord ML_(search_one_loctab) ( const DebugInfo* di, Addr ptr )
2363eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2364eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Addr a_mid_lo, a_mid_hi;
2365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word mid,
2366eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj        lo = 0,
2367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        hi = di->loctab_used-1;
2368eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
2369eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* current unsearched space is from lo to hi, inclusive. */
2370eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (lo > hi) return -1; /* not found */
2371eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      mid      = (lo + hi) / 2;
2372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      a_mid_lo = di->loctab[mid].addr;
2373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      a_mid_hi = ((Addr)di->loctab[mid].addr) + di->loctab[mid].size - 1;
2374eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2375eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (ptr < a_mid_lo) { hi = mid-1; continue; }
2376eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (ptr > a_mid_hi) { lo = mid+1; continue; }
2377eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
2378eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return mid;
2379eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2380eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2381eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2382eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2383eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Find a CFI-table index containing the specified pointer, or -1
2384eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if not found.  Binary search.  */
2385eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2386518850bf0da07ed3e2244e307268ae0fd80e93a8florianWord ML_(search_one_cfitab) ( const DebugInfo* di, Addr ptr )
2387eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
23885c3dba227192de63d86f65ec7d9597c132818c37philippe   Word mid,
2389eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj        lo = 0,
2390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        hi = di->cfsi_used-1;
23915c3dba227192de63d86f65ec7d9597c132818c37philippe
23925c3dba227192de63d86f65ec7d9597c132818c37philippe   while (lo <= hi) {
23930b260824e9bea1fd6d2d6fabd4d112af124ecde6philippe      /* Invariants : hi == cfsi_used-1 || ptr < cfsi_base[hi+1]
23940b260824e9bea1fd6d2d6fabd4d112af124ecde6philippe                      lo == 0           || ptr > cfsi_base[lo-1]
23950b260824e9bea1fd6d2d6fabd4d112af124ecde6philippe         (the first part of the invariants is similar to considering
23960b260824e9bea1fd6d2d6fabd4d112af124ecde6philippe         that cfsi_base[-1] is 0 and cfsi_base[cfsi_used] is ~0) */
2397eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      mid      = (lo + hi) / 2;
23985c3dba227192de63d86f65ec7d9597c132818c37philippe      if (ptr < di->cfsi_base[mid]) { hi = mid-1; continue; }
23995c3dba227192de63d86f65ec7d9597c132818c37philippe      if (ptr > di->cfsi_base[mid]) { lo = mid+1; continue; }
24000b260824e9bea1fd6d2d6fabd4d112af124ecde6philippe      lo = mid+1; break;
2401eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
24025c3dba227192de63d86f65ec7d9597c132818c37philippe
24035c3dba227192de63d86f65ec7d9597c132818c37philippe#if 0
24045c3dba227192de63d86f65ec7d9597c132818c37philippe   for (mid = 0; mid <= di->cfsi_used-1; mid++)
24055c3dba227192de63d86f65ec7d9597c132818c37philippe      if (ptr < di->cfsi_base[mid])
24065c3dba227192de63d86f65ec7d9597c132818c37philippe         break;
24075c3dba227192de63d86f65ec7d9597c132818c37philippe   vg_assert (lo - 1 == mid - 1);
24085c3dba227192de63d86f65ec7d9597c132818c37philippe#endif
24095c3dba227192de63d86f65ec7d9597c132818c37philippe   return lo - 1;
2410eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2411eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2412eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2413c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/* Find a FPO-table index containing the specified pointer, or -1
2414c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if not found.  Binary search.  */
2415c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2416518850bf0da07ed3e2244e307268ae0fd80e93a8florianWord ML_(search_one_fpotab) ( const DebugInfo* di, Addr ptr )
2417c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
241854c45db2f978055aeca91aaccb05aac825523e6csewardj   Addr const addr = ptr - di->fpo_base_avma;
2419c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Addr a_mid_lo, a_mid_hi;
2420c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Word mid, size,
2421c8259b85b701d25d72aabe9dc0a8154517f96913sewardj        lo = 0,
2422c8259b85b701d25d72aabe9dc0a8154517f96913sewardj        hi = di->fpo_size-1;
2423c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   while (True) {
2424c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* current unsearched space is from lo to hi, inclusive. */
2425c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (lo > hi) return -1; /* not found */
2426c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      mid      = (lo + hi) / 2;
2427c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      a_mid_lo = di->fpo[mid].ulOffStart;
2428c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      size     = di->fpo[mid].cbProcSize;
2429c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      a_mid_hi = a_mid_lo + size - 1;
2430c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      vg_assert(a_mid_hi >= a_mid_lo);
2431c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (addr < a_mid_lo) { hi = mid-1; continue; }
2432c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (addr > a_mid_hi) { lo = mid+1; continue; }
2433c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      vg_assert(addr >= a_mid_lo && addr <= a_mid_hi);
2434c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return mid;
2435c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2436c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
2437c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2438eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
2439eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
2440eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
2441