/* addrmap.c --- implementation of address map data structure.

   Copyright (C) 2007-2026 Free Software Foundation, Inc.

   This file is part of GDB.

   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 3 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/>.  */

#include "event-top.h"
#include "gdbsupport/gdb_obstack.h"
#include "addrmap.h"
#include "gdbsupport/selftest.h"

/* Make sure splay trees can actually hold the values we want to
   store in them.  */
static_assert (sizeof (splay_tree_key) >= sizeof (CORE_ADDR *));
static_assert (sizeof (splay_tree_value) >= sizeof (void *));


/* Fixed address maps.  */

void *
addrmap_fixed::do_find (CORE_ADDR addr) const
{
  const struct addrmap_transition *bottom = &transitions[0];
  const struct addrmap_transition *top = &transitions[num_transitions - 1];

  while (bottom < top)
    {
      /* This needs to round towards top, or else when top = bottom +
	 1 (i.e., two entries are under consideration), then mid ==
	 bottom, and then we may not narrow the range when (mid->addr
	 < addr).  */
      const addrmap_transition *mid = top - (top - bottom) / 2;

      if (mid->addr == addr)
	{
	  bottom = mid;
	  break;
	}
      else if (mid->addr < addr)
	/* We don't eliminate mid itself here, since each transition
	   covers all subsequent addresses until the next.  This is why
	   we must round up in computing the midpoint.  */
	bottom = mid;
      else
	top = mid - 1;
    }

  return bottom->value;
}


void
addrmap_fixed::relocate (CORE_ADDR offset)
{
  size_t i;

  for (i = 0; i < num_transitions; i++)
    transitions[i].addr += offset;
}


int
addrmap_fixed::do_foreach (addrmap_foreach_fn fn) const
{
  size_t i;

  for (i = 0; i < num_transitions; i++)
    {
      int res = fn (transitions[i].addr, transitions[i].value);

      if (res != 0)
	return res;
    }

  return 0;
}



/* Mutable address maps.  */

/* Allocate a copy of CORE_ADDR.  */
splay_tree_key
addrmap_mutable::allocate_key (CORE_ADDR addr)
{
  CORE_ADDR *key = XNEW (CORE_ADDR);

  *key = addr;
  return (splay_tree_key) key;
}


/* Type-correct wrappers for splay tree access.  */
splay_tree_node
addrmap_mutable::splay_tree_lookup (CORE_ADDR addr) const
{
  return ::splay_tree_lookup (tree, (splay_tree_key) &addr);
}


splay_tree_node
addrmap_mutable::splay_tree_predecessor (CORE_ADDR addr) const
{
  return ::splay_tree_predecessor (tree, (splay_tree_key) &addr);
}


splay_tree_node
addrmap_mutable::splay_tree_successor (CORE_ADDR addr)
{
  return ::splay_tree_successor (tree, (splay_tree_key) &addr);
}


void
addrmap_mutable::splay_tree_remove (CORE_ADDR addr)
{
  ::splay_tree_remove (tree, (splay_tree_key) &addr);
}


static CORE_ADDR
addrmap_node_key (splay_tree_node node)
{
  return * (CORE_ADDR *) node->key;
}


static void *
addrmap_node_value (splay_tree_node node)
{
  return (void *) node->value;
}


static void
addrmap_node_set_value (splay_tree_node node, void *value)
{
  node->value = (splay_tree_value) value;
}


void
addrmap_mutable::splay_tree_insert (CORE_ADDR key, void *value)
{
  ::splay_tree_insert (tree,
		       allocate_key (key),
		       (splay_tree_value) value);
}


/* Without changing the mapping of any address, ensure that there is a
   tree node at ADDR, even if it would represent a "transition" from
   one value to the same value.  */
void
addrmap_mutable::force_transition (CORE_ADDR addr)
{
  splay_tree_node n = splay_tree_lookup (addr);

  if (! n)
    {
      n = splay_tree_predecessor (addr);
      splay_tree_insert (addr, n ? addrmap_node_value (n) : NULL);
    }
}


/* Compare keys as CORE_ADDR * values.  */
static int
splay_compare_CORE_ADDR_ptr (splay_tree_key ak, splay_tree_key bk)
{
  CORE_ADDR a = * (CORE_ADDR *) ak;
  CORE_ADDR b = * (CORE_ADDR *) bk;

  /* We can't just return a-b here, because of over/underflow.  */
  if (a < b)
    return -1;
  else if (a == b)
    return 0;
  else
    return 1;
}


static void
xfree_wrapper (splay_tree_key key)
{
  xfree ((void *) key);
}

bool
addrmap_mutable::set_empty (CORE_ADDR start, CORE_ADDR end_inclusive,
			    void *obj)
{
  bool full_range = true;
  splay_tree_node n, next;
  void *prior_value;

  if (tree == nullptr)
    tree = splay_tree_new (splay_compare_CORE_ADDR_ptr, xfree_wrapper,
			   nullptr /* no delete value */);

  /* If we're being asked to set all empty portions of the given
     address range to empty, then probably the caller is confused.
     (If that turns out to be useful in some cases, then we can change
     this to simply return, since overriding NULL with NULL is a
     no-op.)  */
  gdb_assert (obj);

  /* We take a two-pass approach, for simplicity.
     - Establish transitions where we think we might need them.
     - First pass: change all NULL regions to OBJ.
     - Second pass: remove any unnecessary transitions.  */

  /* Establish transitions at the start and end.  */
  force_transition (start);
  if (end_inclusive < CORE_ADDR_MAX)
    force_transition (end_inclusive + 1);

  /* Walk the area, changing all NULL regions to OBJ.  */
  for (n = splay_tree_lookup (start), gdb_assert (n);
       n && addrmap_node_key (n) <= end_inclusive;
       n = splay_tree_successor (addrmap_node_key (n)))
    {
      if (addrmap_node_value (n))
	{
	  /* Already mapped.  */
	  full_range = false;
	}
      else
	addrmap_node_set_value (n, obj);
    }

  /* Walk the area again, removing transitions from any value to
     itself.  Be sure to visit both the transitions we forced
     above.  */
  n = splay_tree_predecessor (start);
  prior_value = n ? addrmap_node_value (n) : NULL;
  for (n = splay_tree_lookup (start), gdb_assert (n);
       n && (end_inclusive == CORE_ADDR_MAX
	     || addrmap_node_key (n) <= end_inclusive + 1);
       n = next)
    {
      next = splay_tree_successor (addrmap_node_key (n));
      if (addrmap_node_value (n) == prior_value)
	splay_tree_remove (addrmap_node_key (n));
      else
	prior_value = addrmap_node_value (n);
    }

  return full_range;
}


void *
addrmap_mutable::do_find (CORE_ADDR addr) const
{
  if (tree == nullptr)
    return nullptr;

  splay_tree_node n = splay_tree_lookup (addr);
  if (n != nullptr)
    {
      gdb_assert (addrmap_node_key (n) == addr);
      return addrmap_node_value (n);
    }

  n = splay_tree_predecessor (addr);
  if (n != nullptr)
    {
      gdb_assert (addrmap_node_key (n) < addr);
      return addrmap_node_value (n);
    }

  return nullptr;
}


addrmap_fixed::addrmap_fixed (struct obstack *obstack,
			      const addrmap_mutable *mut)
{
  size_t transition_count = 0;

  /* Count the number of transitions in the tree.  */
  mut->foreach ([&] (CORE_ADDR start, const void *obj)
    {
      ++transition_count;
      return 0;
    });

  /* Include an extra entry for the transition at zero (which fixed
     maps have, but mutable maps do not.)  */
  transition_count++;

  num_transitions = 1;
  transitions = XOBNEWVEC (obstack, struct addrmap_transition,
			   transition_count);
  transitions[0].addr = 0;
  transitions[0].value = NULL;

  /* Copy all entries from the splay tree to the array, in order
     of increasing address.  */
  mut->foreach ([&] (CORE_ADDR start, const void *obj)
    {
      transitions[num_transitions].addr = start;
      transitions[num_transitions].value = const_cast<void *> (obj);
      ++num_transitions;
      return 0;
    });

  /* We should have filled the array.  */
  gdb_assert (num_transitions == transition_count);
}

/* This is a splay_tree_foreach_fn.  */

static int
addrmap_mutable_foreach_worker (splay_tree_node node, void *data)
{
  addrmap_foreach_fn *fn = (addrmap_foreach_fn *) data;

  return (*fn) (addrmap_node_key (node), addrmap_node_value (node));
}


int
addrmap_mutable::do_foreach (addrmap_foreach_fn fn) const
{
  if (tree == nullptr)
    return 0;
  return splay_tree_foreach (tree, addrmap_mutable_foreach_worker, &fn);
}


void
addrmap_mutable::clear ()
{
  if (tree != nullptr)
    {
      splay_tree_delete (tree);
      tree = nullptr;
    }
}


/* See addrmap.h.  */

void
addrmap_dump (struct addrmap *map, struct ui_file *outfile, void *payload,
	      gdb::function_view<void (struct ui_file *outfile,
				       CORE_ADDR start_addr,
				       const void *value)> annotate_value)
{
  /* True if the previously printed addrmap entry was for PAYLOAD.
     If so, we want to print the next one as well (since the next
     addrmap entry defines the end of the range).  */
  bool previous_matched = false;

  auto callback = [&] (CORE_ADDR start_addr, const void *obj)
  {
    QUIT;

    bool matches = payload == nullptr || payload == obj;
    const char *addr_str = nullptr;
    if (matches)
      addr_str = host_address_to_string (obj);
    else if (previous_matched)
      addr_str = "<ends here>";

    if (matches || previous_matched)
      {
	gdb_printf (outfile, "  %s%s %s",
		    payload != nullptr ? "  " : "",
		    core_addr_to_string (start_addr),
		    addr_str);
	if (annotate_value != nullptr)
	  annotate_value (outfile, start_addr, obj);

	gdb_printf (outfile, "\n");
      }

    previous_matched = matches;

    return 0;
  };

  map->foreach (callback);
}

#if GDB_SELF_TEST
namespace selftests {

/* Convert P to CORE_ADDR.  */

static CORE_ADDR
core_addr (const void *p)
{
  return (CORE_ADDR) (uintptr_t) p;
}

/* Check that &ARRAY[LOW]..&ARRAY[HIGH] has VAL in MAP.  */

static void
check_addrmap_find (const addrmap &map, const char *array, unsigned int low,
		    unsigned int high, const void *val)
{
  for (unsigned int i = low; i <= high; ++i)
    SELF_CHECK (map.find (core_addr (&array[i])) == val);
}

/* Entry point for addrmap unit tests.  */

static void
test_addrmap ()
{
  /* We'll verify using the addresses of the elements of this array.  */
  char array[20];

  /* We'll verify using these values stored into the map.  */
  void *val1 = &array[1];
  void *val2 = &array[2];

  /* Create mutable addrmap.  */
  auto_obstack temp_obstack;
  addrmap_mutable map;

  /* Check initial state.  */
  check_addrmap_find (map, array, 0, 19, nullptr);

  /* Insert address range into mutable addrmap.  */
  bool full_range_p
    = map.set_empty (core_addr (&array[10]), core_addr (&array[12]), val1);
  SELF_CHECK (full_range_p);
  check_addrmap_find (map, array, 0, 9, nullptr);
  check_addrmap_find (map, array, 10, 12, val1);
  check_addrmap_find (map, array, 13, 19, nullptr);

  /* Create corresponding fixed addrmap.  */
  addrmap_fixed *map2
    = new (&temp_obstack) addrmap_fixed (&temp_obstack, &map);
  SELF_CHECK (map2 != nullptr);
  check_addrmap_find (*map2, array, 0, 9, nullptr);
  check_addrmap_find (*map2, array, 10, 12, val1);
  check_addrmap_find (*map2, array, 13, 19, nullptr);

  /* Iterate over both addrmaps.  */
  auto callback = [&] (CORE_ADDR start_addr, void *obj)
    {
      if (start_addr == core_addr (nullptr))
	SELF_CHECK (obj == nullptr);
      else if (start_addr == core_addr (&array[10]))
	SELF_CHECK (obj == val1);
      else if (start_addr == core_addr (&array[13]))
	SELF_CHECK (obj == nullptr);
      else
	SELF_CHECK (false);
      return 0;
    };
  SELF_CHECK (map.foreach (callback) == 0);
  SELF_CHECK (map2->foreach (callback) == 0);

  /* Relocate fixed addrmap.  */
  map2->relocate (1);
  check_addrmap_find (*map2, array, 0, 10, nullptr);
  check_addrmap_find (*map2, array, 11, 13, val1);
  check_addrmap_find (*map2, array, 14, 19, nullptr);

  /* Insert partially overlapping address range into mutable addrmap.  */
  full_range_p
    = map.set_empty (core_addr (&array[11]), core_addr (&array[13]), val2);
  SELF_CHECK (!full_range_p);
  check_addrmap_find (map, array, 0, 9, nullptr);
  check_addrmap_find (map, array, 10, 12, val1);
  check_addrmap_find (map, array, 13, 13, val2);
  check_addrmap_find (map, array, 14, 19, nullptr);
}

} /* namespace selftests */
#endif /* GDB_SELF_TEST */

INIT_GDB_FILE (addrmap)
{
#if GDB_SELF_TEST
  selftests::register_test ("addrmap", selftests::test_addrmap);
#endif /* GDB_SELF_TEST */
}
