2 /*--------------------------------------------------------------------*/
3 /*--- A mapping where the keys exactly cover the address space. ---*/
4 /*--- m_rangemap.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2014-2017 Mozilla Foundation
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 /* Contributed by Julian Seward <jseward@acm.org> */
31 #include "pub_core_basics.h"
32 #include "pub_core_libcassert.h"
33 #include "pub_core_libcprint.h"
34 #include "pub_core_xarray.h"
35 #include "pub_core_rangemap.h" /* self */
38 /* See pub_tool_rangemap.h for details of what this is all about. */
40 #define UWORD_MIN ((UWord)0)
41 #define UWORD_MAX (~(UWord)0)
44 struct { UWord key_min
; UWord key_max
; UWord val
; }
49 Alloc_Fn_t alloc_fn
; /* alloc fn (nofail) */
50 const HChar
* cc
; /* cost centre for alloc */
51 Free_Fn_t free_fn
; /* free fn */
57 static void preen (/*MOD*/RangeMap
* rm
);
58 static Word
find ( const RangeMap
* rm
, UWord key
);
59 static void split_at ( /*MOD*/RangeMap
* rm
, UWord key
);
60 static void show ( const RangeMap
* rm
);
63 RangeMap
* VG_(newRangeMap
) ( Alloc_Fn_t alloc_fn
,
68 /* check user-supplied info .. */
71 RangeMap
* rm
= alloc_fn(cc
, sizeof(RangeMap
));
72 rm
->alloc_fn
= alloc_fn
;
74 rm
->free_fn
= free_fn
;
75 rm
->ranges
= VG_(newXA
)( alloc_fn
, cc
, free_fn
, sizeof(Range
) );
76 /* Add the initial range */
78 r
.key_min
= UWORD_MIN
;
79 r
.key_max
= UWORD_MAX
;
81 Word i
= VG_(addToXA
)(rm
->ranges
, &r
);
83 vg_assert(VG_(sizeXA
)(rm
->ranges
) == 1);
88 void VG_(deleteRangeMap
) ( RangeMap
* rm
)
91 vg_assert(rm
->free_fn
);
92 vg_assert(rm
->ranges
);
93 VG_(deleteXA
)(rm
->ranges
);
97 void VG_(bindRangeMap
) ( RangeMap
* rm
,
98 UWord key_min
, UWord key_max
, UWord val
)
100 vg_assert(key_min
<= key_max
);
101 split_at(rm
, key_min
);
102 if (key_max
< UWORD_MAX
)
103 split_at(rm
, key_max
+ 1);
105 iMin
= find(rm
, key_min
);
106 iMax
= find(rm
, key_max
);
107 for (i
= iMin
; i
<= iMax
; i
++) {
108 Range
* rng
= VG_(indexXA
)(rm
->ranges
, i
);
114 void VG_(lookupRangeMap
) ( /*OUT*/UWord
* key_min
, /*OUT*/UWord
* key_max
,
115 /*OUT*/UWord
* val
, const RangeMap
* rm
, UWord key
)
117 Word i
= find(rm
, key
);
118 Range
* rng
= (Range
*)VG_(indexXA
)(rm
->ranges
, i
);
119 *key_min
= rng
->key_min
;
120 *key_max
= rng
->key_max
;
124 UInt
VG_(sizeRangeMap
) ( const RangeMap
* rm
)
126 vg_assert(rm
&& rm
->ranges
);
127 Word size
= VG_(sizeXA
)(rm
->ranges
);
128 vg_assert(size
>= 0);
132 void VG_(indexRangeMap
) ( /*OUT*/UWord
* key_min
, /*OUT*/UWord
* key_max
,
133 /*OUT*/UWord
* val
, const RangeMap
* rm
, Word ix
)
135 vg_assert(rm
&& rm
->ranges
);
136 Range
* rng
= (Range
*)VG_(indexXA
)(rm
->ranges
, ix
);
137 *key_min
= rng
->key_min
;
138 *key_max
= rng
->key_max
;
142 /* Helper functions, not externally visible. */
144 static void preen (/*MOD*/RangeMap
* rm
)
147 XArray
* ranges
= rm
->ranges
;
148 for (i
= 0; i
< VG_(sizeXA
)(ranges
) - 1; i
++) {
149 Range
* rng0
= VG_(indexXA
)(ranges
, i
+0);
150 Range
* rng1
= VG_(indexXA
)(ranges
, i
+1);
151 if (rng0
->val
!= rng1
->val
)
153 rng0
->key_max
= rng1
->key_max
;
154 VG_(removeIndexXA
)(ranges
, i
+1);
155 /* Back up one, so as not to miss an opportunity to merge with
156 the entry after this one. */
161 static Word
find ( const RangeMap
* rm
, UWord key
)
163 XArray
* ranges
= rm
->ranges
;
165 Word hi
= VG_(sizeXA
)(ranges
);
167 /* The unsearched space is lo .. hi inclusive */
169 /* Not found. This can't happen. */
170 VG_(core_panic
)("RangeMap::find: not found");
174 Word mid
= (lo
+ hi
) / 2;
175 Range
* mid_rng
= (Range
*)VG_(indexXA
)(ranges
, mid
);
176 UWord key_mid_min
= mid_rng
->key_min
;
177 UWord key_mid_max
= mid_rng
->key_max
;
178 if (key
< key_mid_min
) { hi
= mid
-1; continue; }
179 if (key
> key_mid_max
) { lo
= mid
+1; continue; }
184 static void split_at ( /*MOD*/RangeMap
* rm
, UWord key
)
186 XArray
* ranges
= rm
->ranges
;
187 Word i
= find(rm
, key
);
188 Range rng_i0
= *(Range
*)VG_(indexXA
)( ranges
, i
+0 );
189 if (rng_i0
.key_min
== key
)
191 VG_(insertIndexXA
)( ranges
, i
+1, &rng_i0
);
192 /* The insert could have relocated the payload, hence the
193 re-indexing of i+0 here. */
194 Range
* rng_i0p
= (Range
*)VG_(indexXA
)( ranges
, i
+0 );
195 Range
* rng_i1p
= (Range
*)VG_(indexXA
)( ranges
, i
+1 );
196 rng_i0p
->key_max
= key
-1;
197 rng_i1p
->key_min
= key
;
200 __attribute__((unused
))
201 static void show ( const RangeMap
* rm
)
204 VG_(printf
)("<< %ld entries:\n", VG_(sizeXA
)(rm
->ranges
) );
205 for (i
= 0; i
< VG_(sizeXA
)(rm
->ranges
); i
++) {
206 Range
* rng
= (Range
*)VG_(indexXA
)(rm
->ranges
, i
);
207 VG_(printf
)(" %016llx %016llx --> 0x%llx\n",
208 (ULong
)rng
->key_min
, (ULong
)rng
->key_max
, (ULong
)rng
->val
);
214 /*--------------------------------------------------------------------*/
215 /*--- end m_rangemap.c ---*/
216 /*--------------------------------------------------------------------*/