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 <cstring>
#include "block.h"
#include "symtab.h"
#include "symfile.h"
return blr;
}
+static bool
+block_ordering_predicate(struct block *b1, struct block *b2)
+{
+ CORE_ADDR start1 = b1->start ();
+ CORE_ADDR start2 = b2->start ();
+
+ if (start1 != start2)
+ return start1 < start2;
+ return (b2->end () < b1->end ());
+}
+
+/* See block.h. */
+
+void
+blockvector::add_block (struct block *block)
+{
+ if (num_blocks() <= FIRST_LOCAL_BLOCK)
+ {
+ /* No blocks (except global and static block). */
+ m_blocks.push_back (block);
+ }
+ else
+ {
+ /* blockvector already contains some blocks. Insert new block
+ to a correct place. */
+ auto first = m_blocks.begin () + FIRST_LOCAL_BLOCK;
+ auto last = m_blocks.end ();
+
+ auto insert_before = std::upper_bound (first,
+ last,
+ block,
+ block_ordering_predicate);
+
+ m_blocks.insert (insert_before, block);
+ }
+}
+
+/* See block.h. */
+
+void
+blockvector::sort ()
+{
+ if (num_blocks() > FIRST_LOCAL_BLOCK)
+ {
+ std::sort (blocks ().begin () + FIRST_LOCAL_BLOCK,
+ blocks ().end (),
+ block_ordering_predicate);
+ }
+}
+
+/* See block.h. */
+
+struct blockvector *
+allocate_blockvector(struct obstack *obstack, int nblocks, int capacity)
+{
+ return new (obstack) blockvector(obstack, nblocks, capacity);
+}
+
/* Implement 'maint info blocks' command. If passed an argument then
print a list of all blocks at the given address. With no arguments
then list all blocks at the current address of the current inferior. */
#ifndef BLOCK_H
#define BLOCK_H
+#include <algorithm>
#include "dictionary.h"
#include "gdbsupport/array-view.h"
#include "gdbsupport/next-iterator.h"
struct blockvector
{
+ void* operator new (size_t size, struct obstack *obstack)
+ {
+ return obstack_alloc (obstack, size);
+ }
+
+ void* operator new[] (size_t size, struct obstack *obstack)
+ {
+ return obstack_alloc (obstack, size);
+ }
+
+ void operator delete (void *memory) {}
+ void operator delete[] (void *memory) {}
+
+ blockvector (struct obstack *obstack, int nblocks, int capacity = 0)
+ : m_map (nullptr),
+ m_blocks (0, nullptr, obstack_allocator<struct block *> (obstack))
+ {
+ m_blocks.reserve (std::max (nblocks, capacity));
+ m_blocks.resize (nblocks, nullptr);
+ }
+
/* Return a view on the blocks of this blockvector. */
gdb::array_view<struct block *> blocks ()
{
- return gdb::array_view<struct block *> (m_blocks, m_num_blocks);
+ return gdb::array_view<struct block *> (m_blocks.data (), m_blocks.size ());
}
/* Const version of the above. */
gdb::array_view<const struct block *const> blocks () const
{
- const struct block **blocks = (const struct block **) m_blocks;
- return gdb::array_view<const struct block *const> (blocks, m_num_blocks);
+ const struct block **blocks = (const struct block **) m_blocks.data ();
+ return gdb::array_view<const struct block *const> (blocks, m_blocks.size ());
}
/* Return the block at index I. */
struct block *block (size_t i)
- { return this->blocks ()[i]; }
+ { return m_blocks[i]; }
/* Const version of the above. */
const struct block *block (size_t i) const
- { return this->blocks ()[i]; }
+ { return m_blocks[i]; }
/* Set the block at index I. */
void set_block (int i, struct block *block)
{ m_blocks[i] = block; }
- /* Set the number of blocks of this blockvector.
-
- The storage of blocks is done using a flexible array member, so the number
- of blocks set here must agree with what was effectively allocated. */
- void set_num_blocks (int num_blocks)
- { m_num_blocks = num_blocks; }
+ /* Add BLOCK, making sure blocks are ordered by code-addresses
+ as required. Update global and static block start and end
+ adresses accordingly. */
+ void add_block(struct block *block);
/* Return the number of blocks in this blockvector. */
int num_blocks () const
- { return m_num_blocks; }
+ { return m_blocks.size (); }
/* Return the global block of this blockvector. */
struct global_block *global_block ()
void set_map (addrmap_fixed *map)
{ m_map = map; }
+ void sort ();
+
private:
/* An address map mapping addresses to blocks in this blockvector.
This pointer is zero if the blocks' start and end addresses are
enough. */
addrmap_fixed *m_map;
- /* Number of blocks in the list. */
- int m_num_blocks;
-
/* The blocks themselves. */
- struct block *m_blocks[1];
+ std::vector<struct block *, obstack_allocator<struct block *>> m_blocks;
};
+/* Allocate new blockvector for NBLOCKS blocks with enough storage to
+ hold up to CAPACITY blocks. CAPACITY defaults to NBLOCKS. */
+struct blockvector *allocate_blockvector(struct obstack *obstack,
+ int nblocks, int capacity = 0);
+
extern const struct blockvector *blockvector_for_pc (CORE_ADDR,
const struct block **);
{
}
- blockvector = (struct blockvector *)
- obstack_alloc (&m_objfile->objfile_obstack,
- (sizeof (struct blockvector)
- + (i - 1) * sizeof (struct block *)));
+ blockvector = allocate_blockvector(&m_objfile->objfile_obstack, i);
/* Copy the blocks into the blockvector. This is done in reverse
order, which happens to put the blocks into the proper order
each block into the list after its subblocks in order to make
sure this is true. */
- blockvector->set_num_blocks (i);
for (next = m_pending_blocks; next; next = next->next)
blockvector->set_block (--i, next->block);
finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
{
struct compunit_symtab *cust;
- size_t blockvector_size;
CORE_ADDR begin, end;
struct blockvector *bv;
filetab->set_linetable (new_table);
}
- blockvector_size = (sizeof (struct blockvector)
- + (actual_nblocks - 1) * sizeof (struct block *));
- bv = (struct blockvector *) obstack_alloc (&objfile->objfile_obstack,
- blockvector_size);
+ bv = allocate_blockvector(&objfile->objfile_obstack, actual_nblocks);
cust->set_blockvector (bv);
/* At the end of this function, (begin, end) will contain the PC range this
entire blockvector spans. */
- bv->set_map (nullptr);
begin = stab->blocks.front ().begin;
end = stab->blocks.front ().end;
- bv->set_num_blocks (actual_nblocks);
/* First run over all the gdb_block objects, creating a real block
object for each. Simultaneously, keep setting the real_block
static struct linetable *new_linetable (int);
-static struct blockvector *new_bvect (int);
-
static struct type *parse_type (int, union aux_ext *, unsigned int, int *,
int, const char *);
/* Cast away "const", but that's ok because we're building the
symtab and blockvector here. */
struct blockvector *bv
- = (struct blockvector *) s->compunit ()->blockvector ();
-
- bv = (struct blockvector *) xrealloc ((void *) bv,
- (sizeof (struct blockvector)
- + bv->num_blocks ()
- * sizeof (struct block)));
- if (bv != s->compunit ()->blockvector ())
- s->compunit ()->set_blockvector (bv);
-
- bv->set_block (bv->num_blocks (), b);
- bv->set_num_blocks (bv->num_blocks () + 1);
+ = const_cast<struct blockvector*> (s->compunit ()->blockvector ());
+ bv->add_block (b);
}
/* Add a new linenumber entry (LINENO,ADR) to a linevector LT.
lang = cust->language ();
/* All symtabs must have at least two blocks. */
- bv = new_bvect (2);
+ bv = allocate_blockvector(&objfile->objfile_obstack, 2);
bv->set_block (GLOBAL_BLOCK, new_block (objfile, NON_FUNCTION_BLOCK, lang));
bv->set_block (STATIC_BLOCK, new_block (objfile, NON_FUNCTION_BLOCK, lang));
bv->static_block ()->set_superblock (bv->global_block ());
* sizeof (lt->item))));
}
-/* Allocate and zero a new blockvector of NBLOCKS blocks. */
-
-static struct blockvector *
-new_bvect (int nblocks)
-{
- struct blockvector *bv;
- int size;
-
- size = sizeof (struct blockvector) + nblocks * sizeof (struct block *);
- bv = (struct blockvector *) xzalloc (size);
- bv->set_num_blocks (nblocks);
-
- return bv;
-}
-
/* Allocate and zero a new block of language LANGUAGE, and set its
BLOCK_MULTIDICT. If function is non-zero, assume the block is
associated to a function, and make sure that the symbols are stored
#if !defined (GDB_OBSTACK_H)
#define GDB_OBSTACK_H 1
+#include <limits>
+#include <type_traits>
#include "obstack.h"
/* Utility macros - wrap obstack alloc into something more robust. */
void operator delete[] (void *memory) {}
};
+/* Implementation of Allocator concept using obstack to
+ allocate memory. This allows standard containers to be
+ used with obstack. */
+
+template <typename T>
+class obstack_allocator
+{
+public:
+ typedef T value_type;
+
+ obstack_allocator (struct obstack *obstack)
+ : m_obstack(obstack)
+ {}
+
+ template <typename U> constexpr obstack_allocator (const obstack_allocator<U>& allocator) noexcept
+ : m_obstack(allocator.m_obstack)
+ {}
+
+ T* allocate (std::size_t n)
+ {
+ if (n > std::numeric_limits<std::size_t>::max () / sizeof (T))
+ throw std::bad_array_new_length ();
+
+ if (auto p = static_cast<T*> (obstack_alloc (m_obstack, n * sizeof (T))))
+ {
+ return p;
+ }
+
+ throw std::bad_alloc ();
+ }
+
+ void deallocate(T* p, std::size_t n) noexcept
+ {}
+
+private:
+
+ struct obstack *m_obstack;
+};
+
+template <class T, class U>
+bool operator==(const obstack_allocator<T> &t, const obstack_allocator<U> &u)
+{
+ return (std::is_same<T, U>::value_type) && (t.m_obstack == u.m_obstack);
+}
+template <class T, class U>
+bool operator!=(const obstack_allocator<T> &t, const obstack_allocator<U> &u)
+{
+ return ! (t == u);
+}
+
#endif