Skip to content

Commit 76dae9e

Browse files
committed
Add block range data structure for blocks with non-contiguous address ranges
This patch does the following: - Introduces a block range data structure which is accessed via a new field in struct block. - Defines several macros for accessing block ranges. - Defines a new function, make_blockrange, which is responsible for creating the new data structure. It should be noted that some support for non-contiguous ranges already existed in GDB in the form of blockvector addrmaps. This support allowed GDB to quickly find a block containing a particular address even when the block consists of non-contiguous addresses. See find_block_in_blockvector() in block.c, dwarf2_record_block_ranges() in dwarf2read.c, and record_block_range() in buildsym.c. Addrmaps do not provide a convenient way to examine address ranges associated with a particular block. This data structure (and its interface) is set up for quickly finding the value (which in this case is a block) associated with a particular address. The interface does not include a method for doing a reverse mapping from blocks to addresses. A linear time mapping might be attempted via use of the addrmap's foreach method, but this is not as straightforward as it might first appear due to the fact that blocks corresponding to inline function instances and lexical blocks w/ variables end up getting interspersed in in the set of transitions. Note: If this approach is deemed to be too expensive in terms of space, an alternate approach might be to attempt the linear time mapping noted above. find_pc_partial_function() needs to be able to quickly know whether there are discontiguous ranges, so a flag for this property would have to be added to struct block. Also integral to this set of changes is the concept of an "entry pc" which might be different from the block's start address. An entry_pc field would also need to be added to struct block. This does not result in any space savings in struct block though since the space for the flag and entry_pc use more space than the blockranges struct pointer that I've added. There would, however, be some space savings due to the fact that the new data structures that I've added for this patch would not need to be allocated. (I happen to like the approach I've come up with, but I wanted to mention another possibility just in case someone does not.) gdb/ChangeLog: * block.h (blockrange, blockranges): New struct declarations. (struct block): Add new field named `ranges'. (BLOCK_RANGES, BLOCK_NRANGES, BLOCK_RANGE, BLOCK_CONTIGUOUS_P) (BLOCK_RANGE_START, BLOCK_RANGE_END, BLOCK_ENTRY_PC): New macros for accessing ranges in struct block. (make_blockranges): New declaration. block.c (make_blockranges): New function.
1 parent 35f0c5a commit 76dae9e

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed

gdb/ChangeLog

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
2018-08-24 Kevin Buettner <[email protected]>
2+
3+
PR gdb/23021
4+
* block.h (blockrange, blockranges): New struct declarations.
5+
(struct block): Add new field named `ranges'.
6+
(BLOCK_RANGES, BLOCK_NRANGES, BLOCK_RANGE, BLOCK_CONTIGUOUS_P)
7+
(BLOCK_RANGE_START, BLOCK_RANGE_END, BLOCK_ENTRY_PC): New
8+
macros for accessing ranges in struct block.
9+
(make_blockranges): New declaration.
10+
block.c (make_blockranges): New function.
11+
112
2018-08-24 Pedro Alves <[email protected]>
213
Simon Marchi <[email protected]>
314

gdb/block.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,3 +807,24 @@ block_find_non_opaque_type_preferred (struct symbol *sym, void *data)
807807
*best = sym;
808808
return 0;
809809
}
810+
811+
/* See block.h. */
812+
813+
struct blockranges *
814+
make_blockranges (struct objfile *objfile,
815+
const std::vector<blockrange> &rangevec)
816+
{
817+
struct blockranges *blr;
818+
size_t n = rangevec.size();
819+
820+
blr = (struct blockranges *)
821+
obstack_alloc (&objfile->objfile_obstack,
822+
sizeof (struct blockranges)
823+
+ (n - 1) * sizeof (struct blockrange));
824+
825+
blr->nranges = n;
826+
for (int i = 0; i < n; i++)
827+
blr->range[i] = rangevec[i];
828+
return blr;
829+
}
830+

gdb/block.h

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,37 @@ struct using_direct;
3131
struct obstack;
3232
struct addrmap;
3333

34+
/* Blocks can occupy non-contiguous address ranges. When this occurs,
35+
startaddr and endaddr within struct block (still) specify the lowest
36+
and highest addresses of all ranges, but each individual range is
37+
specified by the addresses in struct blockrange. */
38+
39+
struct blockrange
40+
{
41+
blockrange (CORE_ADDR startaddr_, CORE_ADDR endaddr_)
42+
: startaddr (startaddr_),
43+
endaddr (endaddr_)
44+
{
45+
}
46+
47+
/* Lowest address in this range. */
48+
49+
CORE_ADDR startaddr;
50+
51+
/* One past the highest address in the range. */
52+
53+
CORE_ADDR endaddr;
54+
};
55+
56+
/* Two or more non-contiguous ranges in the same order as that provided
57+
via the debug info. */
58+
59+
struct blockranges
60+
{
61+
int nranges;
62+
struct blockrange range[1];
63+
};
64+
3465
/* All of the name-scope contours of the program
3566
are represented by `struct block' objects.
3667
All of these objects are pointed to by the blockvector.
@@ -86,6 +117,12 @@ struct block
86117
using directives and the current namespace scope. */
87118

88119
struct block_namespace_info *namespace_info;
120+
121+
/* Address ranges for blocks with non-contiguous ranges. If this
122+
is NULL, then there is only one range which is specified by
123+
startaddr and endaddr above. */
124+
125+
struct blockranges *ranges;
89126
};
90127

91128
/* The global block is singled out so that we can provide a back-link
@@ -109,6 +146,49 @@ struct global_block
109146
#define BLOCK_DICT(bl) (bl)->dict
110147
#define BLOCK_NAMESPACE(bl) (bl)->namespace_info
111148

149+
/* Accessor for ranges field within block BL. */
150+
151+
#define BLOCK_RANGES(bl) (bl)->ranges
152+
153+
/* Number of ranges within a block. */
154+
155+
#define BLOCK_NRANGES(bl) (bl)->ranges->nranges
156+
157+
/* Access range array for block BL. */
158+
159+
#define BLOCK_RANGE(bl) (bl)->ranges->range
160+
161+
/* Are all addresses within a block contiguous? */
162+
163+
#define BLOCK_CONTIGUOUS_P(bl) (BLOCK_RANGES (bl) == nullptr \
164+
|| BLOCK_NRANGES (bl) <= 1)
165+
166+
/* Obtain the start address of the Nth range for block BL. */
167+
168+
#define BLOCK_RANGE_START(bl,n) (BLOCK_RANGE (bl)[n].startaddr)
169+
170+
/* Obtain the end address of the Nth range for block BL. */
171+
172+
#define BLOCK_RANGE_END(bl,n) (BLOCK_RANGE (bl)[n].endaddr)
173+
174+
/* Define the "entry pc" for a block BL to be the lowest (start) address
175+
for the block when all addresses within the block are contiguous. If
176+
non-contiguous, then use the start address for the first range in the
177+
block.
178+
179+
At the moment, this almost matches what DWARF specifies as the entry
180+
pc. (The missing bit is support for DW_AT_entry_pc which should be
181+
preferred over range data and the low_pc.)
182+
183+
Once support for DW_AT_entry_pc is added, I expect that an entry_pc
184+
field will be added to one of these data structures. Once that's done,
185+
the entry_pc field can be set from the dwarf reader (and other readers
186+
too). BLOCK_ENTRY_PC can then be redefined to be less DWARF-centric. */
187+
188+
#define BLOCK_ENTRY_PC(bl) (BLOCK_CONTIGUOUS_P (bl) \
189+
? BLOCK_START (bl) \
190+
: BLOCK_RANGE_START (bl,0))
191+
112192
struct blockvector
113193
{
114194
/* Number of blocks in the list. */
@@ -322,4 +402,9 @@ extern int block_find_non_opaque_type_preferred (struct symbol *sym,
322402
(sym) != NULL; \
323403
(sym) = block_iter_match_next ((name), &(iter)))
324404

405+
/* Given a vector of pairs, allocate and build an obstack allocated
406+
blockranges struct for a block. */
407+
struct blockranges *make_blockranges (struct objfile *objfile,
408+
const std::vector<blockrange> &rangevec);
409+
325410
#endif /* BLOCK_H */

0 commit comments

Comments
 (0)