From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8031 invoked by alias); 19 Jun 2012 07:49:53 -0000 Received: (qmail 7997 invoked by uid 22791); 19 Jun 2012 07:49:48 -0000 X-SWARE-Spam-Status: No, hits=-3.3 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,KAM_STOCKGEN,KHOP_RCVD_TRUST,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE,TW_BJ,TW_QU,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail-vc0-f201.google.com (HELO mail-vc0-f201.google.com) (209.85.220.201) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 19 Jun 2012 07:49:33 +0000 Received: by vcqp1 with SMTP id p1so526378vcq.0 for ; Tue, 19 Jun 2012 00:49:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=to:cc:subject:message-id:date:from:x-gm-message-state; bh=OhuCPYqosploo/6JQUx+6PqLQCVDZyDIfFdvRwxOZd0=; b=VHpdSmhbZBV2cOODljH1Zq1HGV3fqy61mbXzktgSq5XcVcairVeR8oDTpXECCI5TUL TT59lyYy1zvxn2/YjgopF1+zUjqswGFrZAiqp8ON02oz2h9DuziFBPrntsk8j9O6qqfq /pRxLaichCmqB1MHJ1cMpAJ+zUmTyliFfUYH3k801zUpjDU+f3OyZjFvGqguFczIeQSA aelviRVkM6TDJsp7X+BarNJfjixIJiHmDS1q+nsibpcomCv4EMFaP8UE89Or8ohpPbPZ nmNh7GBBmokEusBbc8dWWmvN1VqC1VsiK2uGnyIpC31G1tEwRWstQNSKFWLIYI7+WhGe SbnQ== Received: by 10.236.79.164 with SMTP id i24mr6104385yhe.8.1340092172062; Tue, 19 Jun 2012 00:49:32 -0700 (PDT) Received: by 10.236.79.164 with SMTP id i24mr6104376yhe.8.1340092172018; Tue, 19 Jun 2012 00:49:32 -0700 (PDT) Received: from wpzn4.hot.corp.google.com (216-239-44-65.google.com [216.239.44.65]) by gmr-mx.google.com with ESMTPS id a57si14173774yhh.5.2012.06.19.00.49.32 (version=TLSv1/SSLv3 cipher=AES128-SHA); Tue, 19 Jun 2012 00:49:32 -0700 (PDT) Received: from ruffy2.mtv.corp.google.com (ruffy2.mtv.corp.google.com [172.18.110.129]) by wpzn4.hot.corp.google.com (Postfix) with ESMTP id C5E9F1E004D; Tue, 19 Jun 2012 00:49:31 -0700 (PDT) Received: by ruffy2.mtv.corp.google.com (Postfix, from userid 67641) id 6F0B41E136F; Tue, 19 Jun 2012 00:49:31 -0700 (PDT) To: tromey@redhat.com, gdb-patches@sourceware.org cc: ccoutant@google.com Subject: [RFA] Add global/static and symbol kind indicator to .gdb_index Message-Id: <20120619074931.6F0B41E136F@ruffy2.mtv.corp.google.com> Date: Tue, 19 Jun 2012 07:49:00 -0000 From: dje@google.com (Doug Evans) X-Gm-Message-State: ALoCoQmCC2s8WGRdHf641bJj9M30e7MPUIuI6ce/uDRVF3hH2myW9no4Rwty5ixlk8QcO5UXfS/VJsyQGiGrFyj5wdnl0BdTG/ShKXYsL1DUtYx+OIKs0bFUAH+3smKfvDpjs4ZLl4r4IvKpDGBWYurysn/fACO94g== X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-06/txt/msg00607.txt.bz2 Hi. This patch adds a global/static bit and a symbol kind indicator to CU values in .gdb_index. The global/static bit massively speeds up looking up things like "int" when debugging with lots of shared libraries (all having .gdb_index). PR 14125 [In my canonical large app, I don't know how much the speed up is because I kill gdb when it starts to page (on my 16GB machine). With the patch the lookup takes < 1sec.] The symbol kind indicator speeds up things like "info fun|var foo". [One example is ~500MB/67sec -> ~250MB/30sec.] Regression tested with/without .gdb_index on amd64-linux. It needs a good review, ok to check in? [The patch adds include/gdb/gdb-index.h which technically needs approval from binutils@, but no point in submitting it there until the gdb parts are approved.] 2012-06-18 Doug Evans PR 14125 * 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. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index a14e322..7532ce7 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -40355,7 +40355,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 @@ -40379,13 +40379,104 @@ 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 different 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 not to 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. +Enum values are also included. +@item 3 +The symbol is a function. +@item 4 +The symbol is not covered by the other kinds. +@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 diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 097ee7f..cd72340 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -62,6 +62,7 @@ #include "go-lang.h" #include "valprint.h" #include "gdbcore.h" /* for gnutarget */ +#include "gdb/gdb-index.h" #include #include @@ -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,65 @@ 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_table; + dw2_setup (objfile); + index_table = dwarf2_per_objfile->index_table; + /* index_table is NULL if OBJF_READNOW. */ - if (dwarf2_per_objfile->index_table) + if (index_table) { offset_type *vec; - if (find_slot_in_mapped_hash (dwarf2_per_objfile->index_table, - name, &vec)) + if (find_slot_in_mapped_hash (index_table, 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 kind = + GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs); + + if (want_specific_block + && index_table->version >= 7 + && want_static != is_static) + continue; + + switch (domain) + { + case VAR_DOMAIN: + if (kind != GDB_INDEX_SYMBOL_KIND_VARIABLE + && kind != GDB_INDEX_SYMBOL_KIND_FUNCTION + /* Some types are also in VAR_DOMAIN. */ + && kind != GDB_INDEX_SYMBOL_KIND_TYPE) + continue; + break; + case STRUCT_DOMAIN: + if (kind != GDB_INDEX_SYMBOL_KIND_TYPE) + continue; + break; + case LABEL_DOMAIN: + if (kind != GDB_INDEX_SYMBOL_KIND_OTHER) + continue; + break; + default: + break; + } dw2_instantiate_symtab (per_cu); } @@ -2748,7 +2810,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 +2848,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 +2965,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 +3089,36 @@ 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); + + /* Don't crash on bad data. */ + if (cu_index >= (dwarf2_per_objfile->n_comp_units + + dwarf2_per_objfile->n_comp_units)) + continue; - per_cu = dw2_get_cu (MAYBE_SWAP (vec[vec_idx + 1])); + /* If we're looking for a specific kind, check the symbol's kind. */ + 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 +17509,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 +17530,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 +17813,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 +17863,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 +18100,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 +18116,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. */ diff --git a/include/gdb/gdb-index.h b/include/gdb/gdb-index.h new file mode 100644 index 0000000..92c3398 --- /dev/null +++ b/include/gdb/gdb-index.h @@ -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 . */ + +/* 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 */