mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-03 10:05:29 +00:00
Sync VEX/LICENSE.GPL with top-level COPYING file. We used 3 different addresses for writing to the FSF to receive a copy of the GPL. Replace all different variants with an URL <http://www.gnu.org/licenses/>. The following files might still have some slightly different (L)GPL copyright notice because they were derived from other programs: - files under coregrind/m_demangle which come from libiberty: cplus-dem.c, d-demangle.c, demangle.h, rust-demangle.c, safe-ctype.c and safe-ctype.h - coregrind/m_demangle/dyn-string.[hc] derived from GCC. - coregrind/m_demangle/ansidecl.h derived from glibc. - VEX files for FMA detived from glibc: host_generic_maddf.h and host_generic_maddf.c - files under coregrin/m_debuginfo derived from LZO: lzoconf.h, lzodefs.h, minilzo-inl.c and minilzo.h - files under coregrind/m_gdbserver detived from GDB: gdb/signals.h, inferiors.c, regcache.c, regcache.h, regdef.h, remote-utils.c, server.c, server.h, signals.c, target.c, target.h and utils.c Plus the following test files: - none/tests/ppc32/testVMX.c derived from testVMX. - ppc tests derived from QEMU: jm-insns.c, ppc64_helpers.h and test_isa_3_0.c - tests derived from bzip2 (with embedded GPL text in code): hackedbz2.c, origin5-bz2.c, varinfo6.c - tests detived from glibc: str_tester.c, pth_atfork1.c - test detived from GCC libgomp: tc17_sembar.c - performance tests derived from bzip2 or tinycc (with embedded GPL text in code): bz2.c, test_input_for_tinycc.c and tinycc.c
217 lines
6.4 KiB
C
217 lines
6.4 KiB
C
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- A mapping where the keys exactly cover the address space. ---*/
|
|
/*--- m_rangemap.c ---*/
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/*
|
|
This file is part of Valgrind, a dynamic binary instrumentation
|
|
framework.
|
|
|
|
Copyright (C) 2014-2017 Mozilla Foundation
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
The GNU General Public License is contained in the file COPYING.
|
|
*/
|
|
|
|
/* Contributed by Julian Seward <jseward@acm.org> */
|
|
|
|
#include "pub_core_basics.h"
|
|
#include "pub_core_libcassert.h"
|
|
#include "pub_core_libcprint.h"
|
|
#include "pub_core_xarray.h"
|
|
#include "pub_core_rangemap.h" /* self */
|
|
|
|
|
|
/* See pub_tool_rangemap.h for details of what this is all about. */
|
|
|
|
#define UWORD_MIN ((UWord)0)
|
|
#define UWORD_MAX (~(UWord)0)
|
|
|
|
typedef
|
|
struct { UWord key_min; UWord key_max; UWord val; }
|
|
Range;
|
|
|
|
|
|
struct _RangeMap {
|
|
Alloc_Fn_t alloc_fn; /* alloc fn (nofail) */
|
|
const HChar* cc; /* cost centre for alloc */
|
|
Free_Fn_t free_fn; /* free fn */
|
|
XArray* ranges;
|
|
};
|
|
|
|
|
|
/* fwds */
|
|
static void preen (/*MOD*/RangeMap* rm);
|
|
static Word find ( const RangeMap* rm, UWord key );
|
|
static void split_at ( /*MOD*/RangeMap* rm, UWord key );
|
|
static void show ( const RangeMap* rm );
|
|
|
|
|
|
RangeMap* VG_(newRangeMap) ( Alloc_Fn_t alloc_fn,
|
|
const HChar* cc,
|
|
Free_Fn_t free_fn,
|
|
UWord initialVal )
|
|
{
|
|
/* check user-supplied info .. */
|
|
vg_assert(alloc_fn);
|
|
vg_assert(free_fn);
|
|
RangeMap* rm = alloc_fn(cc, sizeof(RangeMap));
|
|
rm->alloc_fn = alloc_fn;
|
|
rm->cc = cc;
|
|
rm->free_fn = free_fn;
|
|
rm->ranges = VG_(newXA)( alloc_fn, cc, free_fn, sizeof(Range) );
|
|
/* Add the initial range */
|
|
Range r;
|
|
r.key_min = UWORD_MIN;
|
|
r.key_max = UWORD_MAX;
|
|
r.val = initialVal;
|
|
Word i = VG_(addToXA)(rm->ranges, &r);
|
|
vg_assert(i == 0);
|
|
vg_assert(VG_(sizeXA)(rm->ranges) == 1);
|
|
/* */
|
|
return rm;
|
|
}
|
|
|
|
void VG_(deleteRangeMap) ( RangeMap* rm )
|
|
{
|
|
vg_assert(rm);
|
|
vg_assert(rm->free_fn);
|
|
vg_assert(rm->ranges);
|
|
VG_(deleteXA)(rm->ranges);
|
|
rm->free_fn(rm);
|
|
}
|
|
|
|
void VG_(bindRangeMap) ( RangeMap* rm,
|
|
UWord key_min, UWord key_max, UWord val )
|
|
{
|
|
vg_assert(key_min <= key_max);
|
|
split_at(rm, key_min);
|
|
if (key_max < UWORD_MAX)
|
|
split_at(rm, key_max + 1);
|
|
Word iMin, iMax, i;
|
|
iMin = find(rm, key_min);
|
|
iMax = find(rm, key_max);
|
|
for (i = iMin; i <= iMax; i++) {
|
|
Range* rng = VG_(indexXA)(rm->ranges, i);
|
|
rng->val = val;
|
|
}
|
|
preen(rm);
|
|
}
|
|
|
|
void VG_(lookupRangeMap) ( /*OUT*/UWord* key_min, /*OUT*/UWord* key_max,
|
|
/*OUT*/UWord* val, const RangeMap* rm, UWord key )
|
|
{
|
|
Word i = find(rm, key);
|
|
Range* rng = (Range*)VG_(indexXA)(rm->ranges, i);
|
|
*key_min = rng->key_min;
|
|
*key_max = rng->key_max;
|
|
*val = rng->val;
|
|
}
|
|
|
|
UInt VG_(sizeRangeMap) ( const RangeMap* rm )
|
|
{
|
|
vg_assert(rm && rm->ranges);
|
|
Word size = VG_(sizeXA)(rm->ranges);
|
|
vg_assert(size >= 0);
|
|
return size;
|
|
}
|
|
|
|
void VG_(indexRangeMap) ( /*OUT*/UWord* key_min, /*OUT*/UWord* key_max,
|
|
/*OUT*/UWord* val, const RangeMap* rm, Word ix )
|
|
{
|
|
vg_assert(rm && rm->ranges);
|
|
Range* rng = (Range*)VG_(indexXA)(rm->ranges, ix);
|
|
*key_min = rng->key_min;
|
|
*key_max = rng->key_max;
|
|
*val = rng->val;
|
|
}
|
|
|
|
/* Helper functions, not externally visible. */
|
|
|
|
static void preen (/*MOD*/RangeMap* rm)
|
|
{
|
|
Word i;
|
|
XArray* ranges = rm->ranges;
|
|
for (i = 0; i < VG_(sizeXA)(ranges) - 1; i++) {
|
|
Range* rng0 = VG_(indexXA)(ranges, i+0);
|
|
Range* rng1 = VG_(indexXA)(ranges, i+1);
|
|
if (rng0->val != rng1->val)
|
|
continue;
|
|
rng0->key_max = rng1->key_max;
|
|
VG_(removeIndexXA)(ranges, i+1);
|
|
/* Back up one, so as not to miss an opportunity to merge with
|
|
the entry after this one. */
|
|
i--;
|
|
}
|
|
}
|
|
|
|
static Word find ( const RangeMap* rm, UWord key )
|
|
{
|
|
XArray* ranges = rm->ranges;
|
|
Word lo = 0;
|
|
Word hi = VG_(sizeXA)(ranges);
|
|
while (True) {
|
|
/* The unsearched space is lo .. hi inclusive */
|
|
if (lo > hi) {
|
|
/* Not found. This can't happen. */
|
|
VG_(core_panic)("RangeMap::find: not found");
|
|
/*NOTREACHED*/
|
|
return -1;
|
|
}
|
|
Word mid = (lo + hi) / 2;
|
|
Range* mid_rng = (Range*)VG_(indexXA)(ranges, mid);
|
|
UWord key_mid_min = mid_rng->key_min;
|
|
UWord key_mid_max = mid_rng->key_max;
|
|
if (key < key_mid_min) { hi = mid-1; continue; }
|
|
if (key > key_mid_max) { lo = mid+1; continue; }
|
|
return mid;
|
|
}
|
|
}
|
|
|
|
static void split_at ( /*MOD*/RangeMap* rm, UWord key )
|
|
{
|
|
XArray* ranges = rm->ranges;
|
|
Word i = find(rm, key);
|
|
Range rng_i0 = *(Range*)VG_(indexXA)( ranges, i+0 );
|
|
if (rng_i0.key_min == key)
|
|
return;
|
|
VG_(insertIndexXA)( ranges, i+1, &rng_i0 );
|
|
/* The insert could have relocated the payload, hence the
|
|
re-indexing of i+0 here. */
|
|
Range* rng_i0p = (Range*)VG_(indexXA)( ranges, i+0 );
|
|
Range* rng_i1p = (Range*)VG_(indexXA)( ranges, i+1 );
|
|
rng_i0p->key_max = key-1;
|
|
rng_i1p->key_min = key;
|
|
}
|
|
|
|
__attribute__((unused))
|
|
static void show ( const RangeMap* rm )
|
|
{
|
|
Word i;
|
|
VG_(printf)("<< %ld entries:\n", VG_(sizeXA)(rm->ranges) );
|
|
for (i = 0; i < VG_(sizeXA)(rm->ranges); i++) {
|
|
Range* rng = (Range*)VG_(indexXA)(rm->ranges, i);
|
|
VG_(printf)(" %016llx %016llx --> 0x%llx\n",
|
|
(ULong)rng->key_min, (ULong)rng->key_max, (ULong)rng->val);
|
|
}
|
|
VG_(printf)(">>\n");
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- end m_rangemap.c ---*/
|
|
/*--------------------------------------------------------------------*/
|