LCOV - code coverage report
Current view: top level - gcc/analyzer - store.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.7 % 162 155
Test Date: 2024-11-30 13:30:02 Functions: 96.2 % 26 25
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Classes for modeling the state of memory.
       2                 :             :    Copyright (C) 2020-2024 Free Software Foundation, Inc.
       3                 :             :    Contributed by David Malcolm <dmalcolm@redhat.com>.
       4                 :             : 
       5                 :             : This file is part of GCC.
       6                 :             : 
       7                 :             : GCC is free software; you can redistribute it and/or modify it
       8                 :             : under the terms of the GNU General Public License as published by
       9                 :             : the Free Software Foundation; either version 3, or (at your option)
      10                 :             : any later version.
      11                 :             : 
      12                 :             : GCC is distributed in the hope that it will be useful, but
      13                 :             : WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :             : General Public License for more details.
      16                 :             : 
      17                 :             : You should have received a copy of the GNU General Public License
      18                 :             : along with GCC; see the file COPYING3.  If not see
      19                 :             : <http://www.gnu.org/licenses/>.  */
      20                 :             : 
      21                 :             : #ifndef GCC_ANALYZER_STORE_H
      22                 :             : #define GCC_ANALYZER_STORE_H
      23                 :             : 
      24                 :             : #include "text-art/tree-widget.h"
      25                 :             : 
      26                 :             : /* Implementation of the region-based ternary model described in:
      27                 :             :      "A Memory Model for Static Analysis of C Programs"
      28                 :             :       (Zhongxing Xu, Ted Kremenek, and Jian Zhang)
      29                 :             :      http://lcs.ios.ac.cn/~xuzb/canalyze/memmodel.pdf  */
      30                 :             : 
      31                 :             : /* The store models memory as a collection of "clusters", where regions
      32                 :             :    are partitioned into clusters via their base region.
      33                 :             : 
      34                 :             :    For example, given:
      35                 :             :      int a, b, c;
      36                 :             :      struct coord { double x; double y; } verts[3];
      37                 :             :    then "verts[0].y" and "verts[1].x" both have "verts" as their base region.
      38                 :             :    Each of a, b, c, and verts will have their own clusters, so that we
      39                 :             :    know that writes to e.g. "verts[1].x".don't affect e.g. "a".
      40                 :             : 
      41                 :             :    Within each cluster we store a map of bindings to values, where the
      42                 :             :    binding keys can be either concrete or symbolic.
      43                 :             : 
      44                 :             :    Concrete bindings affect a specific range of bits relative to the start
      45                 :             :    of the base region of the cluster, whereas symbolic bindings affect
      46                 :             :    a specific subregion within the cluster.
      47                 :             : 
      48                 :             :    Consider (from the symbolic-1.c testcase):
      49                 :             : 
      50                 :             :      char arr[1024];
      51                 :             :      arr[2] = a;  (1)
      52                 :             :      arr[3] = b;  (2)
      53                 :             :        After (1) and (2), the cluster for "arr" has concrete bindings
      54                 :             :        for bits 16-23 and for bits 24-31, with svalues "INIT_VAL(a)"
      55                 :             :        and "INIT_VAL(b)" respectively:
      56                 :             :        cluster: {bits 16-23: "INIT_VAL(a)",
      57                 :             :                  bits 24-31: "INIT_VAL(b)";
      58                 :             :                  flags: {}}
      59                 :             :        Attempting to query unbound subregions e.g. arr[4] will
      60                 :             :        return "UNINITIALIZED".
      61                 :             :        "a" and "b" are each in their own clusters, with no explicit
      62                 :             :        bindings, and thus implicitly have value INIT_VAL(a) and INIT_VAL(b).
      63                 :             : 
      64                 :             :      arr[3] = c;  (3)
      65                 :             :        After (3), the concrete binding for bits 24-31 is replaced with the
      66                 :             :        svalue "INIT_VAL(c)":
      67                 :             :        cluster: {bits 16-23: "INIT_VAL(a)",  (from before)
      68                 :             :                  bits 24-31: "INIT_VAL(c)";  (updated)
      69                 :             :                  flags: {}}
      70                 :             : 
      71                 :             :      arr[i] = d;  (4)
      72                 :             :        After (4), we lose the concrete bindings and replace them with a
      73                 :             :        symbolic binding for "arr[i]", with svalue "INIT_VAL(d)".  We also
      74                 :             :        mark the cluster as having been "symbolically touched": future
      75                 :             :        attempts to query the values of subregions other than "arr[i]",
      76                 :             :        such as "arr[3]" are "UNKNOWN", since we don't know if the write
      77                 :             :        to arr[i] affected them.
      78                 :             :        cluster: {symbolic_key(arr[i]): "INIT_VAL(d)";
      79                 :             :                  flags: {TOUCHED}}
      80                 :             : 
      81                 :             :      arr[j] = e;  (5)
      82                 :             :        After (5), we lose the symbolic binding for "arr[i]" since we could
      83                 :             :        have overwritten it, and add a symbolic binding for "arr[j]".
      84                 :             :        cluster: {symbolic_key(arr[j]): "INIT_VAL(d)"; (different symbolic
      85                 :             :                  flags: {TOUCHED}}                     binding)
      86                 :             : 
      87                 :             :      arr[3] = f;  (6)
      88                 :             :        After (6), we lose the symbolic binding for "arr[j]" since we could
      89                 :             :        have overwritten it, and gain a concrete binding for bits 24-31
      90                 :             :        again, this time with svalue "INIT_VAL(e)":
      91                 :             :        cluster: {bits 24-31: "INIT_VAL(d)";
      92                 :             :                  flags: {TOUCHED}}
      93                 :             :        The cluster is still flagged as touched, so that we know that
      94                 :             :        accesses to other elements are "UNKNOWN" rather than
      95                 :             :        "UNINITIALIZED".
      96                 :             : 
      97                 :             :    Handling symbolic regions requires us to handle aliasing.
      98                 :             : 
      99                 :             :    In the first example above, each of a, b, c and verts are non-symbolic
     100                 :             :    base regions and so their clusters are "concrete clusters", whereas given:
     101                 :             :        struct coord *p, *q;
     102                 :             :    then "*p" and "*q" are symbolic base regions, and thus "*p" and "*q"
     103                 :             :    have "symbolic clusters".
     104                 :             : 
     105                 :             :    In the above, "verts[i].x" will have a symbolic *binding* within a
     106                 :             :    concrete cluster for "verts", whereas "*p" is a symbolic *cluster*.
     107                 :             : 
     108                 :             :    Writes to concrete clusters can't affect other concrete clusters,
     109                 :             :    but can affect symbolic clusters; e.g. after:
     110                 :             :        verts[0].x = 42;
     111                 :             :    we bind 42 in the cluster for "verts", but the clusters for "b" and "c"
     112                 :             :    can't be affected.  Any symbolic clusters for *p and for *q can be
     113                 :             :    affected, *p and *q could alias verts.
     114                 :             : 
     115                 :             :    Writes to a symbolic cluster can affect other clusters, both
     116                 :             :    concrete and symbolic; e.g. after:
     117                 :             :        p->x = 17;
     118                 :             :    we bind 17 within the cluster for "*p".  The concrete clusters for a, b,
     119                 :             :    c, and verts could be affected, depending on whether *p aliases them.
     120                 :             :    Similarly, the symbolic cluster to *q could be affected.  */
     121                 :             : 
     122                 :             : namespace ana {
     123                 :             : 
     124                 :             : /* A class for keeping track of aspects of a program_state that we don't
     125                 :             :    know about, to avoid false positives about leaks.
     126                 :             : 
     127                 :             :    Consider:
     128                 :             : 
     129                 :             :       p->field = malloc (1024);
     130                 :             :       q->field = NULL;
     131                 :             : 
     132                 :             :    where we don't know whether or not p and q point to the same memory,
     133                 :             :    and:
     134                 :             : 
     135                 :             :       p->field = malloc (1024);
     136                 :             :       unknown_fn (p);
     137                 :             : 
     138                 :             :    In both cases, the svalue for the address of the allocated buffer
     139                 :             :    goes from being bound to p->field to not having anything explicitly bound
     140                 :             :    to it.
     141                 :             : 
     142                 :             :    Given that we conservatively discard bindings due to possible aliasing or
     143                 :             :    calls to unknown function, the store loses references to svalues,
     144                 :             :    but these svalues could still be live.  We don't want to warn about
     145                 :             :    them leaking - they're effectively in a "maybe live" state.
     146                 :             : 
     147                 :             :    This "maybe live" information is somewhat transient.
     148                 :             : 
     149                 :             :    We don't want to store this "maybe live" information in the program_state,
     150                 :             :    region_model, or store, since we don't want to bloat these objects (and
     151                 :             :    potentially bloat the exploded_graph with more nodes).
     152                 :             :    However, we can't store it in the region_model_context, as these context
     153                 :             :    objects sometimes don't last long enough to be around when comparing the
     154                 :             :    old vs the new state.
     155                 :             : 
     156                 :             :    This class is a way to track a set of such svalues, so that we can
     157                 :             :    temporarily capture that they are in a "maybe live" state whilst
     158                 :             :    comparing old and new states.  */
     159                 :             : 
     160                 :      760201 : class uncertainty_t
     161                 :             : {
     162                 :             : public:
     163                 :             :   typedef hash_set<const svalue *>::iterator iterator;
     164                 :             : 
     165                 :       27130 :   void on_maybe_bound_sval (const svalue *sval)
     166                 :             :   {
     167                 :       27130 :     m_maybe_bound_svals.add (sval);
     168                 :             :   }
     169                 :       35498 :   void on_mutable_sval_at_unknown_call (const svalue *sval)
     170                 :             :   {
     171                 :       35498 :     m_mutable_at_unknown_call_svals.add (sval);
     172                 :             :   }
     173                 :             : 
     174                 :      585552 :   bool unknown_sm_state_p (const svalue *sval)
     175                 :             :   {
     176                 :      585552 :     return (m_maybe_bound_svals.contains (sval)
     177                 :      585552 :             || m_mutable_at_unknown_call_svals.contains (sval));
     178                 :             :   }
     179                 :             : 
     180                 :             :   void dump_to_pp (pretty_printer *pp, bool simple) const;
     181                 :             :   void dump (bool simple) const;
     182                 :             : 
     183                 :      573739 :   iterator begin_maybe_bound_svals () const
     184                 :             :   {
     185                 :      573739 :     return m_maybe_bound_svals.begin ();
     186                 :             :   }
     187                 :      663256 :   iterator end_maybe_bound_svals () const
     188                 :             :   {
     189                 :      663256 :     return m_maybe_bound_svals.end ();
     190                 :             :   }
     191                 :             : 
     192                 :             : private:
     193                 :             : 
     194                 :             :   /* svalues that might or might not still be bound.  */
     195                 :             :   hash_set<const svalue *> m_maybe_bound_svals;
     196                 :             : 
     197                 :             :   /* svalues that have mutable sm-state at unknown calls.  */
     198                 :             :   hash_set<const svalue *> m_mutable_at_unknown_call_svals;
     199                 :             : };
     200                 :             : 
     201                 :             : class byte_range;
     202                 :             : class concrete_binding;
     203                 :             : class symbolic_binding;
     204                 :             : 
     205                 :             : /* Abstract base class for describing ranges of bits within a binding_map
     206                 :             :    that can have svalues bound to them.  */
     207                 :             : 
     208                 :   106102593 : class binding_key
     209                 :             : {
     210                 :             : public:
     211                 :      382066 :   virtual ~binding_key () {}
     212                 :             :   virtual bool concrete_p () const = 0;
     213                 :    10809381 :   bool symbolic_p () const { return !concrete_p (); }
     214                 :             : 
     215                 :             :   static const binding_key *make (store_manager *mgr, const region *r);
     216                 :             : 
     217                 :             :   virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
     218                 :             :   void dump (bool simple) const;
     219                 :             :   label_text get_desc (bool simple=true) const;
     220                 :             : 
     221                 :             :   static int cmp_ptrs (const void *, const void *);
     222                 :             :   static int cmp (const binding_key *, const binding_key *);
     223                 :             : 
     224                 :        7869 :   virtual const concrete_binding *dyn_cast_concrete_binding () const
     225                 :        7869 :   { return NULL; }
     226                 :      497958 :   virtual const symbolic_binding *dyn_cast_symbolic_binding () const
     227                 :      497958 :   { return NULL; }
     228                 :             : };
     229                 :             : 
     230                 :             : /* A concrete range of bits.  */
     231                 :             : 
     232                 :             : struct bit_range
     233                 :             : {
     234                 :     1902912 :   bit_range (bit_offset_t start_bit_offset, bit_size_t size_in_bits)
     235                 :     4360958 :   : m_start_bit_offset (start_bit_offset),
     236                 :     2059337 :     m_size_in_bits (size_in_bits)
     237                 :             :   {}
     238                 :             : 
     239                 :             :   void dump_to_pp (pretty_printer *pp) const;
     240                 :             :   void dump () const;
     241                 :             : 
     242                 :             :   std::unique_ptr<json::object> to_json () const;
     243                 :             : 
     244                 :     1297532 :   bool empty_p () const
     245                 :             :   {
     246                 :     1267334 :     return m_size_in_bits == 0;
     247                 :             :   }
     248                 :             : 
     249                 :     1024532 :   bit_offset_t get_start_bit_offset () const
     250                 :             :   {
     251                 :      724655 :     return m_start_bit_offset;
     252                 :             :   }
     253                 :      675430 :   bit_offset_t get_next_bit_offset () const
     254                 :             :   {
     255                 :      825801 :     return m_start_bit_offset + m_size_in_bits;
     256                 :             :   }
     257                 :       30814 :   bit_offset_t get_last_bit_offset () const
     258                 :             :   {
     259                 :       30814 :     gcc_assert (!empty_p ());
     260                 :       30814 :     return get_next_bit_offset () - 1;
     261                 :             :   }
     262                 :             : 
     263                 :       71424 :   bool contains_p (bit_offset_t offset) const
     264                 :             :   {
     265                 :       71424 :     return (offset >= get_start_bit_offset ()
     266                 :      133277 :             && offset < get_next_bit_offset ());
     267                 :             :   }
     268                 :             : 
     269                 :             :   bool contains_p (const bit_range &other, bit_range *out) const;
     270                 :             : 
     271                 :    10654672 :   bool operator== (const bit_range &other) const
     272                 :             :   {
     273                 :    10654672 :     return (m_start_bit_offset == other.m_start_bit_offset
     274                 :    10654672 :             && m_size_in_bits == other.m_size_in_bits);
     275                 :             :   }
     276                 :             : 
     277                 :      107296 :   bool intersects_p (const bit_range &other) const
     278                 :             :   {
     279                 :      107296 :     return (get_start_bit_offset () < other.get_next_bit_offset ()
     280                 :      195761 :             && other.get_start_bit_offset () < get_next_bit_offset ());
     281                 :             :   }
     282                 :             :   bool intersects_p (const bit_range &other,
     283                 :             :                      bit_size_t *out_num_overlap_bits) const;
     284                 :             :   bool intersects_p (const bit_range &other,
     285                 :             :                      bit_range *out_this,
     286                 :             :                      bit_range *out_other) const;
     287                 :             : 
     288                 :             :   bool exceeds_p (const bit_range &other,
     289                 :             :                   bit_range *out_overhanging_bit_range) const;
     290                 :             : 
     291                 :             :   bool falls_short_of_p (bit_offset_t offset,
     292                 :             :                          bit_range *out_fall_short_bits) const;
     293                 :             : 
     294                 :             :   static int cmp (const bit_range &br1, const bit_range &br2);
     295                 :             : 
     296                 :             :   bit_range operator- (bit_offset_t offset) const;
     297                 :             : 
     298                 :             :   static bool from_mask (unsigned HOST_WIDE_INT mask, bit_range *out);
     299                 :             : 
     300                 :             :   bool as_byte_range (byte_range *out) const;
     301                 :             : 
     302                 :             :   bit_offset_t m_start_bit_offset;
     303                 :             :   bit_size_t m_size_in_bits;
     304                 :             : };
     305                 :             : 
     306                 :             : /* A concrete range of bytes.  */
     307                 :             : 
     308                 :             : struct byte_range
     309                 :             : {
     310                 :       21836 :   byte_range (byte_offset_t start_byte_offset, byte_size_t size_in_bytes)
     311                 :       21682 :   : m_start_byte_offset (start_byte_offset),
     312                 :       17815 :     m_size_in_bytes (size_in_bytes)
     313                 :             :   {}
     314                 :             : 
     315                 :             :   void dump_to_pp (pretty_printer *pp) const;
     316                 :             :   void dump () const;
     317                 :             : 
     318                 :             :   std::unique_ptr<json::object> to_json () const;
     319                 :             : 
     320                 :        2530 :   bool empty_p () const
     321                 :             :   {
     322                 :        5060 :     return m_size_in_bytes == 0;
     323                 :             :   }
     324                 :             : 
     325                 :        2580 :   bool contains_p (byte_offset_t offset) const
     326                 :             :   {
     327                 :        7740 :     return (offset >= get_start_byte_offset ()
     328                 :        5158 :             && offset < get_next_byte_offset ());
     329                 :             :   }
     330                 :             :   bool contains_p (const byte_range &other, byte_range *out) const;
     331                 :             : 
     332                 :             :   bool operator== (const byte_range &other) const
     333                 :             :   {
     334                 :             :     return (m_start_byte_offset == other.m_start_byte_offset
     335                 :             :             && m_size_in_bytes == other.m_size_in_bytes);
     336                 :             :   }
     337                 :             : 
     338                 :       16471 :   byte_offset_t get_start_byte_offset () const
     339                 :             :   {
     340                 :       16471 :     return m_start_byte_offset;
     341                 :             :   }
     342                 :        3730 :   byte_offset_t get_next_byte_offset () const
     343                 :             :   {
     344                 :        3730 :     return m_start_byte_offset + m_size_in_bytes;
     345                 :             :   }
     346                 :        2530 :   byte_offset_t get_last_byte_offset () const
     347                 :             :   {
     348                 :        2530 :     gcc_assert (!empty_p ());
     349                 :        2530 :     return m_start_byte_offset + m_size_in_bytes - 1;
     350                 :             :   }
     351                 :             : 
     352                 :         737 :   bit_range as_bit_range () const
     353                 :             :   {
     354                 :        2211 :     return bit_range (m_start_byte_offset * BITS_PER_UNIT,
     355                 :         737 :                       m_size_in_bytes * BITS_PER_UNIT);
     356                 :             :   }
     357                 :             : 
     358                 :           0 :   bit_offset_t get_start_bit_offset () const
     359                 :             :   {
     360                 :           0 :     return m_start_byte_offset * BITS_PER_UNIT;
     361                 :             :   }
     362                 :           0 :   bit_offset_t get_next_bit_offset () const
     363                 :             :   {
     364                 :           0 :     return get_next_byte_offset () * BITS_PER_UNIT;
     365                 :             :   }
     366                 :             : 
     367                 :             :   static int cmp (const byte_range &br1, const byte_range &br2);
     368                 :             : 
     369                 :             :   byte_offset_t m_start_byte_offset;
     370                 :             :   byte_size_t m_size_in_bytes;
     371                 :             : };
     372                 :             : 
     373                 :             : /* Concrete subclass of binding_key, for describing a non-empty
     374                 :             :    concrete range of bits within the binding_map (e.g. "bits 8-15").  */
     375                 :             : 
     376                 :    63247850 : class concrete_binding : public binding_key
     377                 :             : {
     378                 :             : public:
     379                 :             :   /* This class is its own key for the purposes of consolidation.  */
     380                 :             :   typedef concrete_binding key_t;
     381                 :             : 
     382                 :     2294926 :   concrete_binding (bit_offset_t start_bit_offset, bit_size_t size_in_bits)
     383                 :     2294926 :   : m_bit_range (start_bit_offset, size_in_bits)
     384                 :             :   {
     385                 :     2294926 :     gcc_assert (m_bit_range.m_size_in_bits > 0);
     386                 :     2294926 :   }
     387                 :     9825703 :   bool concrete_p () const final override { return true; }
     388                 :             : 
     389                 :    11231888 :   hashval_t hash () const
     390                 :             :   {
     391                 :    11231888 :     inchash::hash hstate;
     392                 :    11231888 :     hstate.add_wide_int (m_bit_range.m_start_bit_offset);
     393                 :    11231888 :     hstate.add_wide_int (m_bit_range.m_size_in_bits);
     394                 :    11231888 :     return hstate.end ();
     395                 :             :   }
     396                 :    10622357 :   bool operator== (const concrete_binding &other) const
     397                 :             :   {
     398                 :    10622357 :     return m_bit_range == other.m_bit_range;
     399                 :             :   }
     400                 :             : 
     401                 :             :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
     402                 :             : 
     403                 :      428211 :   const concrete_binding *dyn_cast_concrete_binding () const final override
     404                 :      428211 :   { return this; }
     405                 :             : 
     406                 :      139858 :   const bit_range &get_bit_range () const { return m_bit_range; }
     407                 :             :   bool get_byte_range (byte_range *out) const;
     408                 :             : 
     409                 :      193045 :   bit_offset_t get_start_bit_offset () const
     410                 :             :   {
     411                 :      184345 :     return m_bit_range.m_start_bit_offset;
     412                 :             :   }
     413                 :      107200 :   bit_size_t get_size_in_bits () const
     414                 :             :   {
     415                 :      107200 :     return m_bit_range.m_size_in_bits;
     416                 :             :   }
     417                 :             :   /* Return the next bit offset after the end of this binding.  */
     418                 :        1776 :   bit_offset_t get_next_bit_offset () const
     419                 :             :   {
     420                 :      178985 :     return m_bit_range.get_next_bit_offset ();
     421                 :             :   }
     422                 :             : 
     423                 :             :   bool overlaps_p (const concrete_binding &other) const;
     424                 :             : 
     425                 :             :   static int cmp_ptr_ptr (const void *, const void *);
     426                 :             : 
     427                 :             :   void mark_deleted () { m_bit_range.m_size_in_bits = -1; }
     428                 :       56408 :   void mark_empty () { m_bit_range.m_size_in_bits = -2; }
     429                 :    11807047 :   bool is_deleted () const { return m_bit_range.m_size_in_bits == -1; }
     430                 :    40183289 :   bool is_empty () const { return m_bit_range.m_size_in_bits == -2; }
     431                 :             : 
     432                 :             : private:
     433                 :             :   bit_range m_bit_range;
     434                 :             : };
     435                 :             : 
     436                 :             : } // namespace ana
     437                 :             : 
     438                 :             : template <>
     439                 :             : template <>
     440                 :             : inline bool
     441                 :           0 : is_a_helper <const ana::concrete_binding *>::test (const ana::binding_key *key)
     442                 :             : {
     443                 :           0 :   return key->concrete_p ();
     444                 :             : }
     445                 :             : 
     446                 :             : template <> struct default_hash_traits<ana::concrete_binding>
     447                 :             : : public member_function_hash_traits<ana::concrete_binding>
     448                 :             : {
     449                 :             :   static const bool empty_zero_p = false;
     450                 :             : };
     451                 :             : 
     452                 :             : namespace ana {
     453                 :             : 
     454                 :             : /* Concrete subclass of binding_key, for describing a symbolic set of
     455                 :             :    bits within the binding_map in terms of a region (e.g. "arr[i]").  */
     456                 :             : 
     457                 :    30145103 : class symbolic_binding : public binding_key
     458                 :             : {
     459                 :             : public:
     460                 :             :   /* This class is its own key for the purposes of consolidation.  */
     461                 :             :   typedef symbolic_binding key_t;
     462                 :             : 
     463                 :     1288164 :   symbolic_binding (const region *region) : m_region (region) {}
     464                 :      996002 :   bool concrete_p () const final override { return false; }
     465                 :             : 
     466                 :     7225724 :   hashval_t hash () const
     467                 :             :   {
     468                 :     7225724 :     return (intptr_t)m_region;
     469                 :             :   }
     470                 :     7203387 :   bool operator== (const symbolic_binding &other) const
     471                 :             :   {
     472                 :     7203387 :     return m_region == other.m_region;
     473                 :             :   }
     474                 :             : 
     475                 :             :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
     476                 :             : 
     477                 :       65581 :   const symbolic_binding *dyn_cast_symbolic_binding () const final override
     478                 :       65581 :   { return this; }
     479                 :             : 
     480                 :       65653 :   const region *get_region () const { return m_region; }
     481                 :             : 
     482                 :             :   static int cmp_ptr_ptr (const void *, const void *);
     483                 :             : 
     484                 :             :   void mark_deleted () { m_region = reinterpret_cast<const region *> (1); }
     485                 :           0 :   void mark_empty () { m_region = NULL; }
     486                 :     7785840 :   bool is_deleted () const
     487                 :     7785840 :   { return m_region == reinterpret_cast<const region *> (1); }
     488                 :             :   bool is_empty () const { return m_region == NULL; }
     489                 :             : 
     490                 :             : private:
     491                 :             :   const region *m_region;
     492                 :             : };
     493                 :             : 
     494                 :             : } // namespace ana
     495                 :             : 
     496                 :             : template <> struct default_hash_traits<ana::symbolic_binding>
     497                 :             : : public member_function_hash_traits<ana::symbolic_binding>
     498                 :             : {
     499                 :             :   static const bool empty_zero_p = true;
     500                 :             : };
     501                 :             : 
     502                 :             : namespace ana {
     503                 :             : 
     504                 :             : /* A mapping from binding_keys to svalues, for use by binding_cluster
     505                 :             :    and compound_svalue.  */
     506                 :             : 
     507                 :      100859 : class binding_map
     508                 :             : {
     509                 :             : public:
     510                 :             :   typedef hash_map <const binding_key *, const svalue *> map_t;
     511                 :             :   typedef map_t::iterator iterator_t;
     512                 :             : 
     513                 :     1656156 :   binding_map () : m_map () {}
     514                 :             :   binding_map (const binding_map &other);
     515                 :             :   binding_map& operator=(const binding_map &other);
     516                 :             : 
     517                 :             :   bool operator== (const binding_map &other) const;
     518                 :     1941424 :   bool operator!= (const binding_map &other) const
     519                 :             :   {
     520                 :     1941424 :     return !(*this == other);
     521                 :             :   }
     522                 :             : 
     523                 :             :   hashval_t hash () const;
     524                 :             : 
     525                 :     3988767 :   const svalue *get (const binding_key *key) const
     526                 :             :   {
     527                 :     3988767 :     const svalue **slot = const_cast<map_t &> (m_map).get (key);
     528                 :     3988767 :     if (slot)
     529                 :     3484525 :       return *slot;
     530                 :             :     else
     531                 :             :       return NULL;
     532                 :             :   }
     533                 :     1711798 :   bool put (const binding_key *k, const svalue *v)
     534                 :             :   {
     535                 :     1711798 :     gcc_assert (v);
     536                 :     1711798 :     return m_map.put (k, v);
     537                 :             :   }
     538                 :             : 
     539                 :      178736 :   void remove (const binding_key *k) { m_map.remove (k); }
     540                 :     1092774 :   void empty () { m_map.empty (); }
     541                 :             : 
     542                 :    17624468 :   iterator_t begin () const { return m_map.begin (); }
     543                 :    26317033 :   iterator_t end () const { return m_map.end (); }
     544                 :      652689 :   size_t elements () const { return m_map.elements (); }
     545                 :             : 
     546                 :             :   void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const;
     547                 :             :   void dump (bool simple) const;
     548                 :             : 
     549                 :             :   std::unique_ptr<json::object> to_json () const;
     550                 :             : 
     551                 :             :   void add_to_tree_widget (text_art::tree_widget &parent_widget,
     552                 :             :                            const text_art::dump_widget_info &dwi) const;
     553                 :             : 
     554                 :             :   bool apply_ctor_to_region (const region *parent_reg, tree ctor,
     555                 :             :                              region_model_manager *mgr);
     556                 :             : 
     557                 :             :   static int cmp (const binding_map &map1, const binding_map &map2);
     558                 :             : 
     559                 :             :   void remove_overlapping_bindings (store_manager *mgr,
     560                 :             :                                     const binding_key *drop_key,
     561                 :             :                                     uncertainty_t *uncertainty,
     562                 :             :                                     svalue_set *maybe_live_values,
     563                 :             :                                     bool always_overlap);
     564                 :             : 
     565                 :             : private:
     566                 :             :   void get_overlapping_bindings (const binding_key *key,
     567                 :             :                                  auto_vec<const binding_key *> *out);
     568                 :             :   bool apply_ctor_val_to_range (const region *parent_reg,
     569                 :             :                                 region_model_manager *mgr,
     570                 :             :                                 tree min_index, tree max_index,
     571                 :             :                                 tree val);
     572                 :             :   bool apply_ctor_pair_to_child_region (const region *parent_reg,
     573                 :             :                                         region_model_manager *mgr,
     574                 :             :                                         tree index, tree val);
     575                 :             : 
     576                 :             :   map_t m_map;
     577                 :             : };
     578                 :             : 
     579                 :             : /* Concept: BindingVisitor, for use by binding_cluster::for_each_binding
     580                 :             :    and store::for_each_binding.
     581                 :             : 
     582                 :             :    Should implement:
     583                 :             :      void on_binding (const binding_key *key, const svalue *&sval);
     584                 :             : */
     585                 :             : 
     586                 :             : /* All of the bindings within a store for regions that share the same
     587                 :             :    base region.  */
     588                 :             : 
     589                 :    25318781 : class binding_cluster
     590                 :             : {
     591                 :             : public:
     592                 :             :   friend class store;
     593                 :             : 
     594                 :             :   typedef hash_map <const binding_key *, const svalue *> map_t;
     595                 :             :   typedef map_t::iterator iterator_t;
     596                 :             : 
     597                 :             :   binding_cluster (const region *base_region);
     598                 :             :   binding_cluster (const binding_cluster &other);
     599                 :             :   binding_cluster& operator=(const binding_cluster &other);
     600                 :             : 
     601                 :             :   bool operator== (const binding_cluster &other) const;
     602                 :     1941424 :   bool operator!= (const binding_cluster &other) const
     603                 :             :   {
     604                 :     1941424 :     return !(*this == other);
     605                 :             :   }
     606                 :             : 
     607                 :             :   hashval_t hash () const;
     608                 :             : 
     609                 :             :   bool symbolic_p () const;
     610                 :             : 
     611                 :       89058 :   const region *get_base_region () const { return m_base_region; }
     612                 :             : 
     613                 :             :   void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const;
     614                 :             :   void dump (bool simple) const;
     615                 :             : 
     616                 :             :   void validate () const;
     617                 :             : 
     618                 :             :   std::unique_ptr<json::object> to_json () const;
     619                 :             : 
     620                 :             :   std::unique_ptr<text_art::tree_widget>
     621                 :             :   make_dump_widget (const text_art::dump_widget_info &dwi,
     622                 :             :                     store_manager *mgr) const;
     623                 :             : 
     624                 :             :   void bind (store_manager *mgr, const region *, const svalue *);
     625                 :             : 
     626                 :             :   void clobber_region (store_manager *mgr, const region *reg);
     627                 :             :   void purge_region (store_manager *mgr, const region *reg);
     628                 :             :   void fill_region (store_manager *mgr, const region *reg, const svalue *sval);
     629                 :             :   void zero_fill_region (store_manager *mgr, const region *reg);
     630                 :             :   void mark_region_as_unknown (store_manager *mgr,
     631                 :             :                                const region *reg_to_bind,
     632                 :             :                                const region *reg_for_overlap,
     633                 :             :                                uncertainty_t *uncertainty,
     634                 :             :                                svalue_set *maybe_live_values);
     635                 :             :   void purge_state_involving (const svalue *sval,
     636                 :             :                               region_model_manager *sval_mgr);
     637                 :             : 
     638                 :             :   const svalue *get_binding (store_manager *mgr, const region *reg) const;
     639                 :             :   const svalue *get_binding_recursive (store_manager *mgr,
     640                 :             :                                         const region *reg) const;
     641                 :             :   const svalue *get_any_binding (store_manager *mgr,
     642                 :             :                                   const region *reg) const;
     643                 :             :   const svalue *maybe_get_compound_binding (store_manager *mgr,
     644                 :             :                                              const region *reg) const;
     645                 :             : 
     646                 :             :   void remove_overlapping_bindings (store_manager *mgr, const region *reg,
     647                 :             :                                     uncertainty_t *uncertainty,
     648                 :             :                                     svalue_set *maybe_live_values);
     649                 :             : 
     650                 :             :   template <typename T>
     651                 :     7506752 :   void for_each_value (void (*cb) (const svalue *sval, T user_data),
     652                 :             :                        T user_data) const
     653                 :             :   {
     654                 :    23659702 :     for (map_t::iterator iter = m_map.begin (); iter != m_map.end (); ++iter)
     655                 :     8076475 :       cb ((*iter).second, user_data);
     656                 :     7506752 :   }
     657                 :             : 
     658                 :             :   static bool can_merge_p (const binding_cluster *cluster_a,
     659                 :             :                            const binding_cluster *cluster_b,
     660                 :             :                            binding_cluster *out_cluster,
     661                 :             :                            store *out_store,
     662                 :             :                            store_manager *mgr,
     663                 :             :                            model_merger *merger);
     664                 :             :   void make_unknown_relative_to (const binding_cluster *other_cluster,
     665                 :             :                                  store *out_store,
     666                 :             :                                  store_manager *mgr);
     667                 :             : 
     668                 :             :   void mark_as_escaped ();
     669                 :             :   void on_unknown_fncall (const gcall *call, store_manager *mgr,
     670                 :             :                           const conjured_purge &p);
     671                 :             :   void on_asm (const gasm *stmt, store_manager *mgr,
     672                 :             :                const conjured_purge &p);
     673                 :             : 
     674                 :             :   bool escaped_p () const;
     675                 :      278025 :   bool touched_p () const { return m_touched; }
     676                 :             : 
     677                 :             :   bool redundant_p () const;
     678                 :      226592 :   bool empty_p () const { return m_map.elements () == 0; }
     679                 :             : 
     680                 :             :   void get_representative_path_vars (const region_model *model,
     681                 :             :                                      svalue_set *visited,
     682                 :             :                                      const region *base_reg,
     683                 :             :                                      const svalue *sval,
     684                 :             :                                      logger *logger,
     685                 :             :                                      auto_vec<path_var> *out_pvs) const;
     686                 :             : 
     687                 :             :   const svalue *maybe_get_simple_value (store_manager *mgr) const;
     688                 :             : 
     689                 :             :   template <typename BindingVisitor>
     690                 :      108723 :   void for_each_binding (BindingVisitor &v) const
     691                 :             :   {
     692                 :      221773 :     for (map_t::iterator iter = m_map.begin (); iter != m_map.end (); ++iter)
     693                 :             :       {
     694                 :      113050 :         const binding_key *key = (*iter).first;
     695                 :      113050 :         const svalue *&sval = (*iter).second;
     696                 :      113050 :         v.on_binding (key, sval);
     697                 :             :       }
     698                 :      108723 :   }
     699                 :             : 
     700                 :        8050 :   iterator_t begin () const { return m_map.begin (); }
     701                 :        8050 :   iterator_t end () const { return m_map.end (); }
     702                 :             : 
     703                 :         239 :   const binding_map &get_map () const { return m_map; }
     704                 :             : 
     705                 :             : private:
     706                 :             :   const svalue *get_any_value (const binding_key *key) const;
     707                 :             :   void bind_compound_sval (store_manager *mgr,
     708                 :             :                            const region *reg,
     709                 :             :                            const compound_svalue *compound_sval);
     710                 :             :   void bind_key (const binding_key *key, const svalue *sval);
     711                 :             : 
     712                 :             :   const region *m_base_region;
     713                 :             : 
     714                 :             :   binding_map m_map;
     715                 :             : 
     716                 :             :   /* Has a pointer to this cluster "escaped" into a part of the program
     717                 :             :      we don't know about (via a call to a function with an unknown body,
     718                 :             :      or by being passed in as a pointer param of a "top-level" function call).
     719                 :             :      Such regions could be overwritten when other such functions are called,
     720                 :             :      even if the region is no longer reachable by pointers that we are
     721                 :             :      tracking. */
     722                 :             :   bool m_escaped;
     723                 :             : 
     724                 :             :   /* Has this cluster been written to via a symbolic binding?
     725                 :             :      If so, then we don't know anything about unbound subregions,
     726                 :             :      so we can't use initial_svalue, treat them as uninitialized, or
     727                 :             :      inherit values from a parent region.  */
     728                 :             :   bool m_touched;
     729                 :             : };
     730                 :             : 
     731                 :             : /* The mapping from regions to svalues.
     732                 :             :    This is actually expressed by subdividing into clusters, to better
     733                 :             :    handle aliasing.  */
     734                 :             : 
     735                 :             : class store
     736                 :             : {
     737                 :             : public:
     738                 :             :   typedef hash_map <const region *, binding_cluster *> cluster_map_t;
     739                 :             : 
     740                 :             :   store ();
     741                 :             :   store (const store &other);
     742                 :             :   ~store ();
     743                 :             : 
     744                 :             :   store &operator= (const store &other);
     745                 :             : 
     746                 :             :   bool operator== (const store &other) const;
     747                 :      431154 :   bool operator!= (const store &other) const
     748                 :             :   {
     749                 :      431154 :     return !(*this == other);
     750                 :             :   }
     751                 :             : 
     752                 :             :   hashval_t hash () const;
     753                 :             : 
     754                 :             :   void dump_to_pp (pretty_printer *pp, bool summarize, bool multiline,
     755                 :             :                    store_manager *mgr) const;
     756                 :             :   void dump (bool simple) const;
     757                 :             :   void summarize_to_pp (pretty_printer *pp, bool simple) const;
     758                 :             : 
     759                 :             :   void validate () const;
     760                 :             : 
     761                 :             :   std::unique_ptr<json::object> to_json () const;
     762                 :             : 
     763                 :             :   std::unique_ptr<text_art::tree_widget>
     764                 :             :   make_dump_widget (const text_art::dump_widget_info &dwi,
     765                 :             :                     store_manager *mgr) const;
     766                 :             : 
     767                 :             :   const svalue *get_any_binding (store_manager *mgr, const region *reg) const;
     768                 :             : 
     769                 :      296296 :   bool called_unknown_fn_p () const { return m_called_unknown_fn; }
     770                 :             : 
     771                 :             :   void set_value (store_manager *mgr, const region *lhs_reg,
     772                 :             :                   const svalue *rhs_sval,
     773                 :             :                   uncertainty_t *uncertainty);
     774                 :             :   void clobber_region (store_manager *mgr, const region *reg);
     775                 :             :   void purge_region (store_manager *mgr, const region *reg);
     776                 :             :   void fill_region (store_manager *mgr, const region *reg, const svalue *sval);
     777                 :             :   void zero_fill_region (store_manager *mgr, const region *reg);
     778                 :             :   void mark_region_as_unknown (store_manager *mgr, const region *reg,
     779                 :             :                                uncertainty_t *uncertainty,
     780                 :             :                                svalue_set *maybe_live_values);
     781                 :             :   void purge_state_involving (const svalue *sval,
     782                 :             :                               region_model_manager *sval_mgr);
     783                 :             : 
     784                 :             :   const binding_cluster *get_cluster (const region *base_reg) const;
     785                 :             :   binding_cluster *get_cluster (const region *base_reg);
     786                 :             :   binding_cluster *get_or_create_cluster (const region *base_reg);
     787                 :             :   void purge_cluster (const region *base_reg);
     788                 :             : 
     789                 :             :   template <typename T>
     790                 :     1779916 :   void for_each_cluster (void (*cb) (const region *base_reg, T user_data),
     791                 :             :                          T user_data) const
     792                 :             :   {
     793                 :    13087290 :     for (cluster_map_t::iterator iter = m_cluster_map.begin ();
     794                 :    24394664 :          iter != m_cluster_map.end (); ++iter)
     795                 :    11307374 :       cb ((*iter).first, user_data);
     796                 :     1779916 :   }
     797                 :             : 
     798                 :             :   static bool can_merge_p (const store *store_a, const store *store_b,
     799                 :             :                            store *out_store, store_manager *mgr,
     800                 :             :                            model_merger *merger);
     801                 :             : 
     802                 :             :   void mark_as_escaped (const region *base_reg);
     803                 :             :   void on_unknown_fncall (const gcall *call, store_manager *mgr,
     804                 :             :                           const conjured_purge &p);
     805                 :             :   bool escaped_p (const region *reg) const;
     806                 :             : 
     807                 :             :   void get_representative_path_vars (const region_model *model,
     808                 :             :                                      svalue_set *visited,
     809                 :             :                                      const svalue *sval,
     810                 :             :                                      logger *logger,
     811                 :             :                                      auto_vec<path_var> *out_pvs) const;
     812                 :             : 
     813                 :     1206047 :   cluster_map_t::iterator begin () const { return m_cluster_map.begin (); }
     814                 :     8992278 :   cluster_map_t::iterator end () const { return m_cluster_map.end (); }
     815                 :             : 
     816                 :             :   tristate eval_alias (const region *base_reg_a,
     817                 :             :                        const region *base_reg_b) const;
     818                 :             : 
     819                 :             :   template <typename BindingVisitor>
     820                 :       29064 :   void for_each_binding (BindingVisitor &v)
     821                 :             :   {
     822                 :      137787 :     for (cluster_map_t::iterator iter = m_cluster_map.begin ();
     823                 :      137787 :          iter != m_cluster_map.end (); ++iter)
     824                 :      108723 :       (*iter).second->for_each_binding (v);
     825                 :       29064 :   }
     826                 :             : 
     827                 :             :   void canonicalize (store_manager *mgr);
     828                 :             :   void loop_replay_fixup (const store *other_store,
     829                 :             :                           region_model_manager *mgr);
     830                 :             : 
     831                 :             :   void replay_call_summary (call_summary_replay &r,
     832                 :             :                             const store &summary);
     833                 :             :   void replay_call_summary_cluster (call_summary_replay &r,
     834                 :             :                                     const store &summary,
     835                 :             :                                     const region *base_reg);
     836                 :             :   void on_maybe_live_values (const svalue_set &maybe_live_values);
     837                 :             : 
     838                 :             : private:
     839                 :             :   void remove_overlapping_bindings (store_manager *mgr, const region *reg,
     840                 :             :                                     uncertainty_t *uncertainty);
     841                 :             :   tristate eval_alias_1 (const region *base_reg_a,
     842                 :             :                          const region *base_reg_b) const;
     843                 :             : 
     844                 :             :   cluster_map_t m_cluster_map;
     845                 :             : 
     846                 :             :   /* If this is true, then unknown code has been called, and so
     847                 :             :      any global variable that isn't currently modelled by the store
     848                 :             :      has unknown state, rather than being in an "initial state".
     849                 :             :      This is to avoid having to mark (and thus explicitly track)
     850                 :             :      every global when an unknown function is called; instead, they
     851                 :             :      can be tracked implicitly.  */
     852                 :             :   bool m_called_unknown_fn;
     853                 :             : };
     854                 :             : 
     855                 :             : /* A class responsible for owning and consolidating binding keys
     856                 :             :    (both concrete and symbolic).
     857                 :             :    Key instances are immutable as far as clients are concerned, so they
     858                 :             :    are provided as "const" ptrs.  */
     859                 :             : 
     860                 :        3773 : class store_manager
     861                 :             : {
     862                 :             : public:
     863                 :        3773 :   store_manager (region_model_manager *mgr) : m_mgr (mgr) {}
     864                 :             : 
     865                 :             :   logger *get_logger () const;
     866                 :             : 
     867                 :             :   /* binding consolidation.  */
     868                 :             :   const concrete_binding *
     869                 :             :   get_concrete_binding (bit_offset_t start_bit_offset,
     870                 :             :                         bit_offset_t size_in_bits);
     871                 :             :   const concrete_binding *
     872                 :       27523 :   get_concrete_binding (const bit_range &bits)
     873                 :             :   {
     874                 :       27523 :     return get_concrete_binding (bits.get_start_bit_offset (),
     875                 :       27523 :                                  bits.m_size_in_bits);
     876                 :             :   }
     877                 :             :   const concrete_binding *
     878                 :           8 :   get_concrete_binding (const byte_range &bytes)
     879                 :             :   {
     880                 :           8 :     bit_range bits = bytes.as_bit_range ();
     881                 :           8 :     return get_concrete_binding (bits);
     882                 :             :   }
     883                 :             :   const symbolic_binding *
     884                 :             :   get_symbolic_binding (const region *region);
     885                 :             : 
     886                 :     5445478 :   region_model_manager *get_svalue_manager () const
     887                 :             :   {
     888                 :     5445478 :     return m_mgr;
     889                 :             :   }
     890                 :             : 
     891                 :             :   void log_stats (logger *logger, bool show_objs) const;
     892                 :             : 
     893                 :             : private:
     894                 :             :   region_model_manager *m_mgr;
     895                 :             :   consolidation_map<concrete_binding> m_concrete_binding_key_mgr;
     896                 :             :   consolidation_map<symbolic_binding> m_symbolic_binding_key_mgr;
     897                 :             : };
     898                 :             : 
     899                 :             : } // namespace ana
     900                 :             : 
     901                 :             : #endif /* GCC_ANALYZER_STORE_H */
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.