/* Self tests for blockvectors Copyright (C) 2025 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 . */ #include "gdbsupport/selftest.h" #include "block.h" #include "addrmap.h" namespace selftests { /* Create and add new block to given blockvector. */ static struct block * make_block (struct blockvector &bv, struct obstack &ob, CORE_ADDR start, CORE_ADDR end, struct block *superblock = nullptr) { auto b = new (&ob) struct block; b->set_start (start); b->set_end (end); b->set_superblock (superblock); b->set_multidict (mdict_create_linear_expandable (language_unknown)); bv.append_block (b); return b; } /* A helper to create and set address map given a blockvector. */ static void make_map (struct blockvector &bv, struct obstack &ob) { struct addrmap_mutable map; for (int i = bv.num_blocks () - 1; i > STATIC_BLOCK; i--) { auto b = bv.block (i); map.set_empty (b->start (), b->end () - 1, b); } bv.set_map (new (&ob) addrmap_fixed (&ob, &map)); } /* Create and return blockvector with following blocks: B0 0x1000 - 0x4000 (global block) B1 0x1000 - 0x4000 (static block) B2 0x1000 - 0x2000 (hole) B3 0x3000 - 0x4000 If USE_MAP is true, then also set blockvector's address map. */ static blockvector_up make_blockvector (struct obstack &ob, bool use_map) { auto bv = std::make_unique (0); auto global_block = make_block (*bv.get (), ob, 0x1000, 0x4000); auto static_block = make_block (*bv.get (), ob, 0x1000, 0x4000, global_block); make_block (*bv.get (), ob, 0x1000, 0x2000, static_block); make_block (*bv.get (), ob, 0x3000, 0x4000, static_block); if (use_map) make_map (*bv.get (), ob); return bv; } static void test_blockvector_lookup_contains () { for (bool with_map : { false, true }) { /* Test blockvector without an address map. */ auto_obstack ob; blockvector_up bv = make_blockvector (ob, with_map); /* Test address outside global block's range. */ SELF_CHECK (bv->lookup (0x0500) == nullptr); SELF_CHECK (bv->contains (0x0500) == false); /* Test address falling into a block. */ SELF_CHECK (bv->lookup (0x1500) == bv->block (2)); SELF_CHECK (bv->contains (0x1500) == true); /* Test address falling into a "hole". If BV has an address map, lookup () returns nullptr. If not, lookup () return static block. contains() returns false in both cases. */ if (with_map) SELF_CHECK (bv->lookup (0x2500) == nullptr); else SELF_CHECK (bv->lookup (0x2500) == bv->block (STATIC_BLOCK)); SELF_CHECK (bv->contains (0x2500) == false); /* Test address falling into a block above the "hole". */ SELF_CHECK (bv->lookup (0x3500) == bv->block (3)); SELF_CHECK (bv->contains (0x3500) == true); /* Test address outside global block's range. */ SELF_CHECK (bv->lookup (0x4000) == nullptr); SELF_CHECK (bv->contains (0x4000) == false); } } } /* namespace selftests */ INIT_GDB_FILE (block_selftest) { selftests::register_test ("blockvector-lookup-contains", selftests::test_blockvector_lookup_contains); }