* NEWS: Document additions to .gdb_index.
	* dwarf2read.c: #include "gdb/gdb-index.h".
	(DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE): New macro.
	(DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE): New macro.
	(DW2_GDB_INDEX_CU_SET_VALUE): New macro.
	(dwarf2_read_index): Recognize version 7.
	(dw2_do_expand_symtabs_matching): New args want_specific_block,
	block_kind, domain): All callers updated.
	(dw2_find_symbol_file): Handle new index CU values.
	(dw2_expand_symtabs_matching): Match symbol kind if requested.
	(add_index_entry): New args is_static, kind.  All callers updated.
	(offset_type_compare, uniquify_cu_indices): New functions
	(symbol_kind): New function.
	(write_psymtabs_to_index): Remove duplicate CU values.
	(write_psymtabs_to_index): Write .gdb_index version 7.

	doc/
	* gdb.texinfo (Index Section Format): Document version 7 format.

	include/gdb/
	* gdb-index.h: New file.
This commit is contained in:
Doug Evans 2012-06-23 22:23:47 +00:00
parent 0d8b534dde
commit 156942c7d1
7 changed files with 463 additions and 40 deletions

View file

@ -1,3 +1,22 @@
2012-06-23 Doug Evans <dje@google.com>
PR 14125
* NEWS: Document additions to .gdb_index.
* dwarf2read.c: #include "gdb/gdb-index.h".
(DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE): New macro.
(DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE): New macro.
(DW2_GDB_INDEX_CU_SET_VALUE): New macro.
(dwarf2_read_index): Recognize version 7.
(dw2_do_expand_symtabs_matching): New args want_specific_block,
block_kind, domain): All callers updated.
(dw2_find_symbol_file): Handle new index CU values.
(dw2_expand_symtabs_matching): Match symbol kind if requested.
(add_index_entry): New args is_static, kind. All callers updated.
(offset_type_compare, uniquify_cu_indices): New functions
(symbol_kind): New function.
(write_psymtabs_to_index): Remove duplicate CU values.
(write_psymtabs_to_index): Write .gdb_index version 7.
2012-06-22 Joel Brobecker <brobecker@adacore.com>
* configure.ac (build_warnings): Add -Wdeclaration-after-statement.

View file

@ -112,6 +112,12 @@
the ability to set breakpoints on inlined functions will be lost
in symbol files with older .gdb_index sections.
The .gdb_index section has also been updated to record more information
about each symbol. This speeds up the "info variables", "info functions"
and "info types" commands when used with programs having the .gdb_index
section, as well as speeding up debugging with shared libraries using
the .gdb_index section.
* Ada support for GDB/MI Variable Objects has been added.
* GDB can now support 'breakpoint always-inserted mode' in 'record'

View file

@ -1,3 +1,7 @@
2012-06-23 Doug Evans <dje@google.com>
* gdb.texinfo (Index Section Format): Document version 7 format.
2012-06-22 Yao Qi <yao@codesourcery.com>
* gdb.texinfo: Add missing cindex for some packets.

View file

@ -40378,7 +40378,7 @@ index version:
@item Version 4
The formula is @code{r = r * 67 + c - 113}.
@item Versions 5 and 6
@item Versions 5 to 7
The formula is @code{r = r * 67 + tolower (c) - 113}.
@end table
@ -40402,13 +40402,103 @@ strings.
A CU vector in the constant pool is a sequence of @code{offset_type}
values. The first value is the number of CU indices in the vector.
Each subsequent value is the index of a CU in the CU list. This
element in the hash table is used to indicate which CUs define the
symbol.
Each subsequent value is the index and symbol attributes of a CU in
the CU list. This element in the hash table is used to indicate which
CUs define the symbol and how the symbol is used.
See below for the format of each CU index+attributes entry.
A string in the constant pool is zero-terminated.
@end enumerate
Attributes were added to CU index values in @code{.gdb_index} version 7.
If a symbol has multiple uses within a CU then there is one
CU index+attributes value for each use.
The format of each CU index+attributes entry is as follows
(bit 0 = LSB):
@table @asis
@item Bits 0-23
This is the index of the CU in the CU list.
@item Bits 24-27
These bits are reserved for future purposes and must be zero.
@item Bits 28-30
The kind of the symbol in the CU.
@table @asis
@item 0
This value is reserved and should not be used.
By reserving zero the full @code{offset_type} value is backwards compatible
with previous versions of the index.
@item 1
The symbol is a type.
@item 2
The symbol is a variable or an enum value.
@item 3
The symbol is a function.
@item 4
Any other kind of symbol.
@item 5,6,7
These values are reserved.
@end table
@item Bit 31
This bit is zero if the value is global and one if it is static.
The determination of whether a symbol is global or static is complicated.
The authorative reference is the file @file{dwarf2read.c} in
@value{GDBN} sources.
@end table
This pseudo-code describes the computation of a symbol's kind and
global/static attributes in the index.
@smallexample
is_external = get_attribute (die, DW_AT_external);
language = get_attribute (cu_die, DW_AT_language);
switch (die->tag)
@{
case DW_TAG_typedef:
case DW_TAG_base_type:
case DW_TAG_subrange_type:
kind = TYPE;
is_static = 1;
break;
case DW_TAG_enumerator:
kind = VARIABLE;
is_static = (language != CPLUS && language != JAVA);
break;
case DW_TAG_subprogram:
kind = FUNCTION;
is_static = ! (is_external || language == ADA);
break;
case DW_TAG_constant:
kind = VARIABLE;
is_static = ! is_external;
break;
case DW_TAG_variable:
kind = VARIABLE;
is_static = ! is_external;
break;
case DW_TAG_namespace:
kind = TYPE;
is_static = 0;
break;
case DW_TAG_class_type:
case DW_TAG_interface_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
kind = TYPE;
is_static = (language != CPLUS && language != JAVA);
break;
default:
assert (0);
@}
@end smallexample
@include gpl.texi
@node GNU Free Documentation License

View file

@ -62,6 +62,7 @@
#include "go-lang.h"
#include "valprint.h"
#include "gdbcore.h" /* for gnutarget */
#include "gdb/gdb-index.h"
#include <ctype.h>
#include <fcntl.h>
@ -122,6 +123,28 @@ typedef uint32_t offset_type;
DEF_VEC_I (offset_type);
/* Ensure only legit values are used. */
#define DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value) \
do { \
gdb_assert ((unsigned int) (value) <= 1); \
GDB_INDEX_SYMBOL_STATIC_SET_VALUE((cu_index), (value)); \
} while (0)
/* Ensure only legit values are used. */
#define DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE(cu_index, value) \
do { \
gdb_assert ((value) >= GDB_INDEX_SYMBOL_KIND_TYPE \
&& (value) <= GDB_INDEX_SYMBOL_KIND_OTHER); \
GDB_INDEX_SYMBOL_KIND_SET_VALUE((cu_index), (value)); \
} while (0)
/* Ensure we don't use more than the alloted nuber of bits for the CU. */
#define DW2_GDB_INDEX_CU_SET_VALUE(cu_index, value) \
do { \
gdb_assert (((value) & ~GDB_INDEX_CU_MASK) == 0); \
GDB_INDEX_CU_SET_VALUE((cu_index), (value)); \
} while (0)
/* A description of the mapped index. The file format is described in
a comment by the code that writes the index. */
struct mapped_index
@ -2350,7 +2373,7 @@ dwarf2_read_index (struct objfile *objfile)
}
/* Indexes with higher version than the one supported by GDB may be no
longer backward compatible. */
if (version > 6)
if (version > 7)
return 0;
map = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct mapped_index);
@ -2716,26 +2739,70 @@ dw2_lookup_symbol (struct objfile *objfile, int block_index,
}
/* A helper function that expands all symtabs that hold an object
named NAME. */
named NAME. If WANT_SPECIFIC_BLOCK is non-zero, only look for
symbols in block BLOCK_KIND. */
static void
dw2_do_expand_symtabs_matching (struct objfile *objfile, const char *name)
dw2_do_expand_symtabs_matching (struct objfile *objfile,
int want_specific_block,
enum block_enum block_kind,
const char *name, domain_enum domain)
{
struct mapped_index *index;
dw2_setup (objfile);
index = dwarf2_per_objfile->index_table;
/* index_table is NULL if OBJF_READNOW. */
if (dwarf2_per_objfile->index_table)
if (index)
{
offset_type *vec;
if (find_slot_in_mapped_hash (dwarf2_per_objfile->index_table,
name, &vec))
if (find_slot_in_mapped_hash (index, name, &vec))
{
offset_type i, len = MAYBE_SWAP (*vec);
for (i = 0; i < len; ++i)
{
offset_type cu_index = MAYBE_SWAP (vec[i + 1]);
offset_type cu_index_and_attrs = MAYBE_SWAP (vec[i + 1]);
offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (cu_index);
int want_static = block_kind != GLOBAL_BLOCK;
/* This value is only valid for index versions >= 7. */
int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
gdb_index_symbol_kind symbol_kind =
GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
if (want_specific_block
&& index->version >= 7
&& want_static != is_static)
continue;
/* Only check the symbol's kind if it has one.
Indices prior to version 7 don't record it. */
if (index->version >= 7)
{
switch (domain)
{
case VAR_DOMAIN:
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION
/* Some types are also in VAR_DOMAIN. */
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
continue;
break;
case STRUCT_DOMAIN:
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
continue;
break;
case LABEL_DOMAIN:
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
continue;
break;
default:
break;
}
}
dw2_instantiate_symtab (per_cu);
}
@ -2748,7 +2815,7 @@ dw2_pre_expand_symtabs_matching (struct objfile *objfile,
enum block_enum block_kind, const char *name,
domain_enum domain)
{
dw2_do_expand_symtabs_matching (objfile, name);
dw2_do_expand_symtabs_matching (objfile, 1, block_kind, name, domain);
}
static void
@ -2786,7 +2853,9 @@ static void
dw2_expand_symtabs_for_function (struct objfile *objfile,
const char *func_name)
{
dw2_do_expand_symtabs_matching (objfile, func_name);
/* Note: It doesn't matter what we pass for block_kind here. */
dw2_do_expand_symtabs_matching (objfile, 0, GLOBAL_BLOCK, func_name,
VAR_DOMAIN);
}
static void
@ -2901,7 +2970,7 @@ dw2_find_symbol_file (struct objfile *objfile, const char *name)
should be rewritten so that it doesn't require a custom hook. It
could just use the ordinary symbol tables. */
/* vec[0] is the length, which must always be >0. */
per_cu = dw2_get_cu (MAYBE_SWAP (vec[1]));
per_cu = dw2_get_cu (GDB_INDEX_CU_VALUE (MAYBE_SWAP (vec[1])));
if (per_cu->v.quick->symtab != NULL)
return per_cu->v.quick->symtab->filename;
@ -3025,8 +3094,40 @@ dw2_expand_symtabs_matching
for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
{
struct dwarf2_per_cu_data *per_cu;
offset_type cu_index_and_attrs = MAYBE_SWAP (vec[vec_idx + 1]);
gdb_index_symbol_kind symbol_kind =
GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
per_cu = dw2_get_cu (MAYBE_SWAP (vec[vec_idx + 1]));
/* Don't crash on bad data. */
if (cu_index >= (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_comp_units))
continue;
/* Only check the symbol's kind if it has one.
Indices prior to version 7 don't record it. */
if (index->version >= 7)
{
switch (kind)
{
case VARIABLES_DOMAIN:
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE)
continue;
break;
case FUNCTIONS_DOMAIN:
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION)
continue;
break;
case TYPES_DOMAIN:
if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
continue;
break;
default:
break;
}
}
per_cu = dw2_get_cu (cu_index);
if (file_matcher == NULL || per_cu->v.quick->mark)
dw2_instantiate_symtab (per_cu);
}
@ -17417,14 +17518,17 @@ hash_expand (struct mapped_symtab *symtab)
xfree (old_entries);
}
/* Add an entry to SYMTAB. NAME is the name of the symbol. CU_INDEX
is the index of the CU in which the symbol appears. */
/* Add an entry to SYMTAB. NAME is the name of the symbol.
CU_INDEX is the index of the CU in which the symbol appears.
IS_STATIC is one if the symbol is static, otherwise zero (global). */
static void
add_index_entry (struct mapped_symtab *symtab, const char *name,
int is_static, gdb_index_symbol_kind kind,
offset_type cu_index)
{
struct symtab_index_entry **slot;
offset_type cu_index_and_attrs;
++symtab->n_elements;
if (4 * symtab->n_elements / 3 >= symtab->size)
@ -17435,13 +17539,76 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
{
*slot = XNEW (struct symtab_index_entry);
(*slot)->name = name;
/* index_offset is set later. */
(*slot)->cu_indices = NULL;
}
/* Don't push an index twice. Due to how we add entries we only
have to check the last one. */
if (VEC_empty (offset_type, (*slot)->cu_indices)
|| VEC_last (offset_type, (*slot)->cu_indices) != cu_index)
VEC_safe_push (offset_type, (*slot)->cu_indices, cu_index);
cu_index_and_attrs = 0;
DW2_GDB_INDEX_CU_SET_VALUE (cu_index_and_attrs, cu_index);
DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE (cu_index_and_attrs, is_static);
DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE (cu_index_and_attrs, kind);
/* We don't want to record an index value twice as we want to avoid the
duplication.
We process all global symbols and then all static symbols
(which would allow us to avoid the duplication by only having to check
the last entry pushed), but a symbol could have multiple kinds in one CU.
To keep things simple we don't worry about the duplication here and
sort and uniqufy the list after we've processed all symbols. */
VEC_safe_push (offset_type, (*slot)->cu_indices, cu_index_and_attrs);
}
/* qsort helper routine for uniquify_cu_indices. */
static int
offset_type_compare (const void *ap, const void *bp)
{
offset_type a = *(offset_type *) ap;
offset_type b = *(offset_type *) bp;
return (a > b) - (b > a);
}
/* Sort and remove duplicates of all symbols' cu_indices lists. */
static void
uniquify_cu_indices (struct mapped_symtab *symtab)
{
int i;
for (i = 0; i < symtab->size; ++i)
{
struct symtab_index_entry *entry = symtab->data[i];
if (entry
&& entry->cu_indices != NULL)
{
unsigned int next_to_insert, next_to_check;
offset_type last_value;
qsort (VEC_address (offset_type, entry->cu_indices),
VEC_length (offset_type, entry->cu_indices),
sizeof (offset_type), offset_type_compare);
last_value = VEC_index (offset_type, entry->cu_indices, 0);
next_to_insert = 1;
for (next_to_check = 1;
next_to_check < VEC_length (offset_type, entry->cu_indices);
++next_to_check)
{
if (VEC_index (offset_type, entry->cu_indices, next_to_check)
!= last_value)
{
last_value = VEC_index (offset_type, entry->cu_indices,
next_to_check);
VEC_replace (offset_type, entry->cu_indices, next_to_insert,
last_value);
++next_to_insert;
}
}
VEC_truncate (offset_type, entry->cu_indices, next_to_insert);
}
}
}
/* Add a vector of indices to the constant pool. */
@ -17655,6 +17822,44 @@ write_address_map (struct objfile *objfile, struct obstack *obstack,
addrmap_index_data.previous_cu_index);
}
/* Return the symbol kind of PSYM. */
static gdb_index_symbol_kind
symbol_kind (struct partial_symbol *psym)
{
domain_enum domain = PSYMBOL_DOMAIN (psym);
enum address_class aclass = PSYMBOL_CLASS (psym);
switch (domain)
{
case VAR_DOMAIN:
switch (aclass)
{
case LOC_BLOCK:
return GDB_INDEX_SYMBOL_KIND_FUNCTION;
case LOC_TYPEDEF:
return GDB_INDEX_SYMBOL_KIND_TYPE;
case LOC_COMPUTED:
case LOC_CONST_BYTES:
case LOC_OPTIMIZED_OUT:
case LOC_STATIC:
return GDB_INDEX_SYMBOL_KIND_VARIABLE;
case LOC_CONST:
/* Note: It's currently impossible to recognize psyms as enum values
short of reading the type info. For now punt. */
return GDB_INDEX_SYMBOL_KIND_VARIABLE;
default:
/* There are other LOC_FOO values that one might want to classify
as variables, but dwarf2read.c doesn't currently use them. */
return GDB_INDEX_SYMBOL_KIND_OTHER;
}
case STRUCT_DOMAIN:
return GDB_INDEX_SYMBOL_KIND_TYPE;
default:
return GDB_INDEX_SYMBOL_KIND_OTHER;
}
}
/* Add a list of partial symbols to SYMTAB. */
static void
@ -17667,29 +17872,21 @@ write_psymbols (struct mapped_symtab *symtab,
{
for (; count-- > 0; ++psymp)
{
void **slot, *lookup;
struct partial_symbol *psym = *psymp;
void **slot;
if (SYMBOL_LANGUAGE (*psymp) == language_ada)
if (SYMBOL_LANGUAGE (psym) == language_ada)
error (_("Ada is not currently supported by the index"));
/* We only want to add a given psymbol once. However, we also
want to account for whether it is global or static. So, we
may add it twice, using slightly different values. */
if (is_static)
{
uintptr_t val = 1 | (uintptr_t) *psymp;
lookup = (void *) val;
}
else
lookup = *psymp;
/* Only add a given psymbol once. */
slot = htab_find_slot (psyms_seen, lookup, INSERT);
slot = htab_find_slot (psyms_seen, psym, INSERT);
if (!*slot)
{
*slot = lookup;
add_index_entry (symtab, SYMBOL_SEARCH_NAME (*psymp), cu_index);
gdb_index_symbol_kind kind = symbol_kind (psym);
*slot = psym;
add_index_entry (symtab, SYMBOL_SEARCH_NAME (psym),
is_static, kind, cu_index);
}
}
}
@ -17912,6 +18109,10 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
write_one_signatured_type, &sig_data);
}
/* Now that we've processed all symbols we can shrink their cu_indices
lists. */
uniquify_cu_indices (symtab);
obstack_init (&constant_pool);
make_cleanup_obstack_free (&constant_pool);
obstack_init (&symtab_obstack);
@ -17924,7 +18125,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
total_len = size_of_contents;
/* The version number. */
val = MAYBE_SWAP (6);
val = MAYBE_SWAP (7);
obstack_grow (&contents, &val, sizeof (val));
/* The offset of the CU list from the start of the file. */

View file

@ -1,3 +1,7 @@
2012-06-23 Doug Evans <dje@google.com>
* gdb-index.h: New file.
2012-05-24 Pedro Alves <palves@redhat.com>
PR gdb/7205

99
include/gdb/gdb-index.h Normal file
View file

@ -0,0 +1,99 @@
/* Public attributes of the .gdb_index section.
Copyright 2012 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/>. */
/* This file contains values for understanding the .gdb_index section
needed by more than just GDB, e.g. readelf. */
#ifndef GDB_INDEX_H
#define GDB_INDEX_H
/* Each symbol in .gdb_index refers to a set of CUs that defines the symbol.
Each CU is represented by a 32 bit number that is the index of the CU in
the CU table, plus some attributes of the use of the symbol in that CU.
The values are defined such that if all the bits are zero, then no
special meaning is assigned to any of them. This is done to preserve
compatibility with older indices. The way this is done is to specify
that if the GDB_INDEX_SYMBOL_KIND value is zero then all other attribute
bits must be zero.
0-23 CU index
24-27 reserved
28-30 symbol kind
31 0 == global, 1 == static
Bits 24-27 are reserved because it's easier to relax restrictions than
it is to impose them after the fact. At present 24 bits to represent
the CU index is plenty. If we need more bits for the CU index or for
attributes then we have them. */
/* Whether the symbol is in GLOBAL_BLOCK (== 0) or STATIC_BLOCK (== 1). */
#define GDB_INDEX_SYMBOL_STATIC_SHIFT 31
#define GDB_INDEX_SYMBOL_STATIC_MASK 1
#define GDB_INDEX_SYMBOL_STATIC_VALUE(cu_index) \
(((cu_index) >> GDB_INDEX_SYMBOL_STATIC_SHIFT) & GDB_INDEX_SYMBOL_STATIC_MASK)
#define GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value) \
do { \
(cu_index) |= (((value) & GDB_INDEX_SYMBOL_STATIC_MASK) \
<< GDB_INDEX_SYMBOL_STATIC_SHIFT); \
} while (0)
/* The kind of the symbol.
We don't use GDB's internal values as these numbers are published
so that other tools can build and read .gdb_index. */
typedef enum {
/* Special value to indicate no attributes are present. */
GDB_INDEX_SYMBOL_KIND_NONE = 0,
GDB_INDEX_SYMBOL_KIND_TYPE = 1,
GDB_INDEX_SYMBOL_KIND_VARIABLE = 2,
GDB_INDEX_SYMBOL_KIND_FUNCTION = 3,
GDB_INDEX_SYMBOL_KIND_OTHER = 4,
/* We currently allocate 3 bits to record the symbol kind.
Give the unused bits a value so gdb will print them sensibly. */
GDB_INDEX_SYMBOL_KIND_UNUSED5 = 5,
GDB_INDEX_SYMBOL_KIND_UNUSED6 = 6,
GDB_INDEX_SYMBOL_KIND_UNUSED7 = 7,
} gdb_index_symbol_kind;
#define GDB_INDEX_SYMBOL_KIND_SHIFT 28
#define GDB_INDEX_SYMBOL_KIND_MASK 7
#define GDB_INDEX_SYMBOL_KIND_VALUE(cu_index) \
((gdb_index_symbol_kind) (((cu_index) >> GDB_INDEX_SYMBOL_KIND_SHIFT) \
& GDB_INDEX_SYMBOL_KIND_MASK))
#define GDB_INDEX_SYMBOL_KIND_SET_VALUE(cu_index, value) \
do { \
(cu_index) |= (((value) & GDB_INDEX_SYMBOL_KIND_MASK) \
<< GDB_INDEX_SYMBOL_KIND_SHIFT); \
} while (0)
#define GDB_INDEX_RESERVED_SHIFT 24
#define GDB_INDEX_RESERVED_MASK 15
#define GDB_INDEX_RESERVED_VALUE(cu_index) \
(((cu_index) >> GDB_INDEX_RESERVED_SHIFT) & GDB_INDEX_RESERVED_MASK)
/* CU index. */
#define GDB_INDEX_CU_BITSIZE 24
#define GDB_INDEX_CU_MASK ((1 << GDB_INDEX_CU_BITSIZE) - 1)
#define GDB_INDEX_CU_VALUE(cu_index) ((cu_index) & GDB_INDEX_CU_MASK)
#define GDB_INDEX_CU_SET_VALUE(cu_index, value) \
do { \
(cu_index) |= (value) & GDB_INDEX_CU_MASK; \
} while (0)
#endif /* GDB_INDEX_H */