From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 73154 invoked by alias); 19 Nov 2019 04:46:48 -0000 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 Received: (qmail 73135 invoked by uid 89); 19 Nov 2019 04:46:45 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.0 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy=justify, releasing, cu, sk:partial X-HELO: mail-pf1-f201.google.com Received: from mail-pf1-f201.google.com (HELO mail-pf1-f201.google.com) (209.85.210.201) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 19 Nov 2019 04:46:34 +0000 Received: by mail-pf1-f201.google.com with SMTP id h67so15885218pfb.7 for ; Mon, 18 Nov 2019 20:46:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=/JdcQjp/kbateOj9v6Fy86j1y7qfARqbMosa09cYHGQ=; b=jCvhIgwBU/4CjhQP7RAY/SjmpyXqc3x90qC0/5lH+E5JYFW5WNv0f+B2xcbi3zr1mj R4Lgqfr1NEzd+NP4VRXMbMGzFS+e8ZzmTQvkJIS+VbS7UqPW12juZcza6xn2FK2MvC5O wSluj899bR/iLxB84hnRLpTC5UrjzOSKowctS8jKc1FeAPJ2vV/dyaGiXTrxrVlckdy7 k9Grow/BqpvNpjqy054tMXgmZSZmouZdEtOGZTlkaPhBRBUXshR7DO319JibLBCKHM7I fkLjpxDlMMbRQNrHNjgoakp7QZ510voIVXmkZkTeCOvHz4jFSQRBvSELsth67jGt2pKQ ayyg== Date: Tue, 19 Nov 2019 04:46:00 -0000 In-Reply-To: <7f64573b-adef-f991-cc6c-6174b1c24d39@polymtl.ca> Message-Id: <20191119044628.178151-1-tamur@google.com> Mime-Version: 1.0 References: <7f64573b-adef-f991-cc6c-6174b1c24d39@polymtl.ca> Subject: [PATCH] Dwarf 5: Handle debug_str_offsets and indexed attributes that have base offsets. From: "Ali Tamur via gdb-patches" Reply-To: Ali Tamur To: gdb-patches@sourceware.org Cc: Simon Marchi , Ali Tamur Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2019-11/txt/msg00580.txt.bz2 Hi Simon, Thanks for the review. Please see my replies below. > - ULONGEST ranges_base =3D 0; > + gdb::optional ranges_base =3D 0; *** I am probably missing something, but I don't really understand the log= ic of making this field optional and initializing it to 0, or the need to make= it optional at all. If the CU does not have a DW_AT_rnglists_base attribute, doesn't it implicitly mean that this CU's ranges offset is 0? So it would = seem fine to just leave it at 0 and keep the arithmetic as before. Ok, I changed the initial value to 'no value' and thank you, it's better. It seems a good idea to differentiate between an unexisting value and an exist= ing value of 0 even if the math stays the same. For example, for str_offsets_ba= se, there are different code paths depending on whether there is a value (not depending whether the value is 0). It seems to me all of [addr_base, ranges_base, str_offsets_base] should have similar semantics. But I agree t= hat currently there is no behavioral difference in ranges_base case, do you pre= fer it ULONGEST? *** Two spaces after period. Done. > +#define DW_STRING_IS_STR_INDEX(attr) ((attr)->string_is_str_index) *** I don't really see the advantage of those macros. I agree and I don't like these macros at all. But I wanted to be consistent. (Maybe I should clear all of them as a separate refactoring cl sometime) > +static gdb::optional > +lookup_addr_base (struct dwarf2_cu *cu, struct die_info* comp_unit_die, > + bool will_follow) *** Please provide a comment for this function. Done. *** The curly braces scopes above are missing an indentation level. Done. > +static gdb::optional > +lookup_ranges_base (struct dwarf2_cu *cu, struct die_info* comp_unit_die) *** Please provide a comment for this function too. Done. > + struct attribute *attr =3D dwarf2_attr (comp_unit_die, > + DW_AT_str_offsets_base, cu); > + if (attr) *** Use: if (attr !=3D nullptr) Done and sent another patch to replace all "if (attr)" with=20 "if (attr !=3D nullptr)" in this file (there were 48 occurences). > +/* Read CU/TU THIS_CU but do not follow DW_AT_GNU_dwo_name (DW_AT_GNU_dw= o_name) *** You listed DW_AT_GNU_dwo_name twice, I don't think that was the intent. Done. > static void > init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu, > + struct dwarf2_cu *parent_cu, *** Please document this new parameter. Since "parent" is passed only to g= et the base offsets, I think it would be clearer to pass the offsets directly.= =20 If I look at the signature of the function and see "dwarf2_cu *parent_cu", I can't really tell what it's for (though a comment might help). But if I see "ULONGEST str_offsets_base" and "ULONGEST addr_base", it's more self-explan= atory. I wrote a comment, I hope it's good. I prefer not changing the parameters to ULONGEST str_offsets_base and ULONGEST addr_base, because I am confused a l= ittle too: there is a case where there is no parent_cu and in that case I believe= any existing value should not be overridden and it is difficult to do that on t= he caller site. *** Remove the curly braces. DONE > - if (sibling_ptr < info_ptr) > - complaint (_("DW_AT_sibling points backwards")); > - else if (sibling_ptr > reader->buffer_end) > + if (sibling_ptr > reader->buffer_end) *** Improvements like this one look good, but if they are not directly rela= ted to the patch, please submit them in their own patch, it's easier to review = and justify that way. OK. I need to dig up the exact case how the code failed and I made this cha= nge, until then I am reverting this part. *** I'm a bit confused with those different cases, could you please add a = bit of comments to explain the logic for each case? Why is it not possible to obtain the string value at this point? If cu->str_offsets_base has no valu= e, doesn't it mean that the offset is 0? Maybe it would be more obvious if I saw the actual DWARF being parsed. Cou= ld you suggest some gcc or clang commands to obtain some DWARF where we have a DW_AT_dwo_name that is an indirect string? Reply: Sure, here's an example. $ cd /tmp/dw5 && echo "int calculate() { return 4; } int main(int argc, ch= ar** argv) { return calculate(); }" >>main.cc $ clang -gdwarf-5 -gsplit-dwarf main.cc $ ls a.out main.cc main.dwo=20 $ llvm-dwarfdump --all a.out a.out: file format ELF64-x86-64 .debug_abbrev contents: Abbrev table for offset: 0x00000000 [1] DW_TAG_compile_unit DW_CHILDREN_no DW_AT_stmt_list DW_FORM_sec_offset DW_AT_str_offsets_base DW_FORM_sec_offset DW_AT_comp_dir DW_FORM_strx1 DW_AT_GNU_pubnames DW_FORM_flag_present DW_AT_GNU_dwo_name DW_FORM_strx1 DW_AT_low_pc DW_FORM_addrx DW_AT_high_pc DW_FORM_data4 DW_AT_addr_base DW_FORM_sec_offset .debug_info contents: 0x00000000: Compile Unit: length =3D 0x00000024 version =3D 0x0005 unit_typ= e =3D DW_UT_skeleton abbr_offset =3D 0x0000 addr_size =3D 0x08 DWO_id =3D 0= xee1d4b42a2f0ca0b (next unit at 0x00000028) 0x00000014: DW_TAG_compile_unit DW_AT_stmt_list (0x00000000) DW_AT_str_offsets_base (0x00000008) DW_AT_comp_dir ("/tmp/dw5") DW_AT_GNU_pubnames (true) DW_AT_GNU_dwo_name ("main.dwo") DW_AT_low_pc (0x0000000000401110) DW_AT_high_pc (0x0000000000401141) DW_AT_addr_base (0x00000008) .... .debug_str contents: 0x00000000: "/tmp/dw5" 0x00000009: "main.dwo" .... .debug_str_offsets contents: 0x00000000: Contribution size =3D 12, Format =3D DWARF32, Version =3D 5 0x00000008: 00000000 "/tmp/dw5" 0x0000000c: 00000009 "main.dwo" Here is what happens. gdb starts to parse DW_TAG_compile_unit DIE. It comes to DW_AT_GNU_dwo_name. It is of form DW_FORM_strx1 and it has a value of 1. The actual value is somewhere in .debug_str section. To find it we need to process .debug_str_offsets (refer to 1st index somewhere within) and also k= now the value of DW_AT_str_offsets_base. However, we are in the middle of parsi= ng the die and there is no guarantee that we have yet processed DW_AT_str_offsets_base, it may be parsed later.=20 My solution is to temporarily write "1" as the value of the attribute DW_AT_GNU_dwo_name, and mark it as 'needs reprocessing'. After all the attributes of the die have been processed, DW_AT_str_offsets_base will hold= the correct value if it exists. Then, we revisit the marked attributes. During reprocess, we don't need to read the binary file again, because we had alre= ady written the value we need (1) in the first pass. We calculate the correct address using that value, the contents of .debug_str* sections and DW_AT_str_offsets_base value. I am not claiming this is the only or the best solution, but I think it is intuitive and changes relatively few lines of code. --- * Process debug_str_offsets section. Handle DW_AT_str_offsets_base attribut= e and keep the value in dwarf2_cu. * Make addr_base and ranges_base fields in dwarf2_cu optional to disambigua= te 0 value (absent or present and 0). * During parsing, there is no guarantee that DW_AT_str_offsets_base and DW_AT_rnglists_base fields will be processed before the attributes that need those values for correct computation. So make two passes, on the first one = mark the attributes that depend on *_base attributes and process only the others. On the second pass, only process the attributes that are marked on the first pass. * For string attributes, differentiate between addresses that directly poin= t to a string and those that point to an offset in debug_str_offsets section. * There are now two attributes, DW_AT_addr_base and DW_AT_GNU_addr_base to = read address offset base. Likewise, there are two attributes, DW_AT_rnglists_base and DW_AT_GNU_ranges_base to read ranges base. Since there is no guarantee = which ones the compiler will generate, create helper functions to handle all case= s. Tested with CC=3D/usr/bin/gcc (version 8.3.0) against master branch (also w= ith -gsplit-dwarf and -gdwarf-4 flags) and there was no increase in the set of tests that fails. (gdb still cannot debug a 'hello world' program with DWAR= F 5, so for the time being, this is all we care about). This is part of an effort to support DWARF-5 in gdb. gdb/ChangeLog * dwarf2read.c (dwarf2_debug_sections): Add debug_str_offsets sections (dwarf2_cu): Add str_offsets_base field. Change the type of addr_base and ranges_base to gdb::optional. Update comments. (dwo_file): Update comments. (attribute): Add string_is_str_index field. (DW_STRING_IS_STR_INDEX): New macro (to comply with local standard). (read_attribute): Update API to take an additional out parameter, need_reprocess. This is used to mark attributes that need other attributes (e.g. str_offsets_base) for correct computation which may not have been read yet. (read_addr_index): New function. (read_dwo_str_index): Likewise. (read_stub_str_index): Likewise. (get_comp_dir_attr): Likewise. (get_stub_string_attr): Likewise. (dwarf2_per_objfile::locate_sections): Handle debug_str_offsets section. (lookup_addr_base): New function. (lookup_ranges_base): Likewise. (read_cutu_die_from_dwo): Use the new functions: lookup_addr_base, lookup_ranges_base, DW_STRING_IS_STR_INDEX, get_comp_dir_attr. (init_cutu_and_read_dies): Initialize str_offsets_base fields. (init_cutu_and_read_dies_no_follow): Change API to take parent compile unit. This is used to inherit parent's str_offsets_base and addr_base. Update comments. (init_cutu_and_read_dies_simple): Reflect API changes. (skip_one_die): Likewise. Support DW_FORM_rnglistx. (create_cus_hash_table): Reflect API changes. (open_and_init_dwo_file): Likewise. (dwarf2_get_pc_bounds): Likewise. (dwarf2_record_block_ranges): Likewise. (read_full_die_1): Change implementation to reprocess attributes that need str_offsets_base and addr_base. (partial_die_info::read): Change implementation to reprocess attributes that need str_offsets_base and addr_base. Update Api change of addr_base field. (read_attribute_reprocess): New method. (read_attribute_value): Change API to take an additional out parameter, need_reprocess. Initialize string_is_str_index field. No longer mark an error when a non-dwo compile unit has index based attributes. (read_attribute): Reflect API changes. (read_addr_index_1): Reflect API changes. Update comments. (dwarf2_read_addr_index_data): Reflect API changes. (read_str_index): Change API and implementation. This becomes a helper to be used by the new string index related methods. * dwarf2read.h (dwarf2_per_objfile): Add str_offsets field. * symfile.h (dwarf2_debug_sections): Likewise. * xcoffread.c (dwarf2_xcoff_names): Likewise. --- gdb/dwarf2read.c | 428 ++++++++++++++++++++++++++++++++++++----------- gdb/dwarf2read.h | 1 + gdb/symfile.h | 1 + gdb/xcoffread.c | 1 + 4 files changed, 330 insertions(+), 101 deletions(-) diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 4372a47c6d..6d6c76b748 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -287,6 +287,7 @@ static const struct dwarf2_debug_sections dwarf2_elf_na= mes =3D { ".debug_macinfo", ".zdebug_macinfo" }, { ".debug_macro", ".zdebug_macro" }, { ".debug_str", ".zdebug_str" }, + { ".debug_str_offsets", ".zdebug_str_offsets" }, { ".debug_line_str", ".zdebug_line_str" }, { ".debug_ranges", ".zdebug_ranges" }, { ".debug_rnglists", ".zdebug_rnglists" }, @@ -500,29 +501,27 @@ public: There is an invariant here that is important to remember: Except for attributes copied from the top level DIE in the "main" (or "stub") file in preparation for reading the DWO file - (e.g., DW_AT_GNU_addr_base), we KISS: there is only *one* CU. + (e.g., DW_AT_addr_base), we KISS: there is only *one* CU. Either there isn't a DWO file (in which case this is NULL and the poi= nt is moot), or there is and either we're not going to read it (in which case this is NULL) or there is and we are reading it (in which case t= his is non-NULL). */ struct dwo_unit *dwo_unit =3D nullptr; =20 - /* The DW_AT_addr_base attribute if present, zero otherwise - (zero is a valid value though). + /* The DW_AT_addr_base (DW_AT_GNU_addr_base) attribute if present. Note this value comes from the Fission stub CU/TU's DIE. */ - ULONGEST addr_base =3D 0; + gdb::optional addr_base {}; =20 - /* The DW_AT_ranges_base attribute if present, zero otherwise - (zero is a valid value though). + /* The DW_AT_rnglists_base attribute if present. Note this value comes from the Fission stub CU/TU's DIE. Also note that the value is zero in the non-DWO case so this value can be used without needing to know whether DWO files are in use or not. N.B. This does not apply to DW_AT_ranges appearing in DW_TAG_compile_unit dies. This is a bit of a wart, consider if ever DW_AT_ranges appeared in the DW_TAG_compile_unit of DWO DIEs: then - DW_AT_ranges_base *would* have to be applied, and we'd have to care + DW_AT_rnglists_base *would* have to be applied, and we'd have to care whether the DW_AT_ranges attribute came from the skeleton or DWO. */ - ULONGEST ranges_base =3D 0; + gdb::optional ranges_base {}; =20 /* When reading debug info generated by older versions of rustc, we have to rewrite some union types to be struct types with a @@ -532,6 +531,12 @@ public: all such types here and process them after expansion. */ std::vector rust_unions; =20 + /* The DW_AT_str_offsets_base attribute if present. For DWARF 4 version= DWO + files, the value is implicitly zero. For DWARF 5 version DWO files, t= he + value is often implicit and is the size of the header of + .debug_str_offsets section (8 or 4, depending on the address size). = */ + gdb::optional str_offsets_base {}; + /* Mark used when releasing cached dies. */ bool mark : 1; =20 @@ -697,7 +702,7 @@ struct dwo_file dwo_file () =3D default; DISABLE_COPY_AND_ASSIGN (dwo_file); =20 - /* The DW_AT_GNU_dwo_name attribute. + /* The DW_AT_GNU_dwo_name or DW_AT_dwo_name attribute. For virtual DWO files the name is constructed from the section offsets of abbrev,line,loc,str_offsets so that we combine virtual DWO files from related CU+TUs. */ @@ -1272,6 +1277,18 @@ struct attribute here for better struct attribute alignment. */ unsigned int string_is_canonical : 1; =20 + /* For strings in non-DWO files, was a string recorded with + DW_AT_GNU_str_index before we knew the value of DW_AT_str_offsets_b= ase? + If non-zero, then the "value" of the string is in u.unsnd, and + read_dwo_str_index must be called to obtain the actual string. + This is necessary for DW_AT_comp_dir and DW_AT_GNU_dwo_name (or + DW_AT_dwo_name) attributes: To save a relocation DW_AT_GNU_str_inde= x is + used, but because all .o file .debug_str_offsets sections are + concatenated together in the executable each .o has its own offset = into + this section. So if DW_AT_str_offsets_base comes later in the DIE, = we + need to reprocess these attributes later. */ + bool string_is_str_index; + union { const char *str; @@ -1324,6 +1341,7 @@ struct die_info =20 #define DW_STRING(attr) ((attr)->u.str) #define DW_STRING_IS_CANONICAL(attr) ((attr)->string_is_canonical) +#define DW_STRING_IS_STR_INDEX(attr) ((attr)->string_is_str_index) #define DW_UNSND(attr) ((attr)->u.unsnd) #define DW_BLOCK(attr) ((attr)->u.blk) #define DW_SND(attr) ((attr)->u.snd) @@ -1519,7 +1537,12 @@ static const struct cu_partial_die_info find_partial= _die (sect_offset, int, =20 static const gdb_byte *read_attribute (const struct die_reader_specs *, struct attribute *, struct attr_abbrev *, - const gdb_byte *); + const gdb_byte *, bool *need_reprocess); + +static void read_attribute_reprocess (const struct die_reader_specs *reade= r, + struct attribute *attr); + +static CORE_ADDR read_addr_index (struct dwarf2_cu *cu, unsigned int addr_= index); =20 static unsigned int read_1_byte (bfd *, const gdb_byte *); =20 @@ -1578,8 +1601,17 @@ static CORE_ADDR read_addr_index_from_leb128 (struct= dwarf2_cu *, const gdb_byte *, unsigned int *); =20 -static const char *read_str_index (const struct die_reader_specs *reader, - ULONGEST str_index); +static const char *read_dwo_str_index (const struct die_reader_specs *read= er, + ULONGEST str_index); + +static const char *read_stub_str_index (struct dwarf2_cu *cu, + ULONGEST str_index); + +static const char *get_comp_dir_attr (struct die_info *die, + struct dwarf2_cu *cu); + +static const char *get_stub_string_attr (struct dwarf2_cu *cu, + const struct attribute *attr); =20 static void set_cu_language (unsigned int, struct dwarf2_cu *); =20 @@ -2409,6 +2441,11 @@ dwarf2_per_objfile::locate_sections (bfd *abfd, asec= tion *sectp, this->str.s.section =3D sectp; this->str.size =3D bfd_section_size (sectp); } + else if (section_is_p (sectp->name, &names.str_offsets)) + { + this->str_offsets.s.section =3D sectp; + this->str_offsets.size =3D bfd_section_size (sectp); + } else if (section_is_p (sectp->name, &names.line_str)) { this->line_str.s.section =3D sectp; @@ -7154,7 +7191,47 @@ lookup_signatured_type (struct dwarf2_cu *cu, ULONGE= ST sig) return entry; } } -=0C + +/* Return the address base of the compile unit, which, if exists, is stored + either at the attribute DW_AT_GNU_addr_base, or DW_AT_addr_base. Also = takes + as parameter whether it should follow DW_AT_specification. See the com= ments + on dwarf2_attr_no_follow and dwarf2_attr for the difference. */ +static gdb::optional +lookup_addr_base (struct dwarf2_cu *cu, struct die_info* comp_unit_die, + bool will_follow) +{ + struct attribute *attr; + if (will_follow) + { + attr =3D dwarf2_attr (comp_unit_die, DW_AT_addr_base, cu); + if (attr =3D=3D nullptr) + attr =3D dwarf2_attr (comp_unit_die, DW_AT_GNU_addr_base, cu); + } + else + { + attr =3D dwarf2_attr_no_follow (comp_unit_die, DW_AT_addr_base); + if (attr =3D=3D nullptr) + attr =3D dwarf2_attr_no_follow (comp_unit_die, DW_AT_GNU_addr_base= ); + } + if (attr =3D=3D nullptr) + return gdb::optional (); + return DW_UNSND (attr); +} + +/* Return range lists base of the compile unit, which, if exists, is stored + either at the attribute DW_AT_rnglists_base or DW_AT_GNU_ranges_base. = */ +static gdb::optional +lookup_ranges_base (struct dwarf2_cu *cu, struct die_info* comp_unit_die) +{ + struct attribute *attr; + attr =3D dwarf2_attr (comp_unit_die, DW_AT_rnglists_base, cu); + if (attr =3D=3D nullptr) + attr =3D dwarf2_attr (comp_unit_die, DW_AT_GNU_ranges_base, cu); + if (attr =3D=3D nullptr) + return gdb::optional (); + return DW_UNSND (attr); +} + /* Low level DIE reading support. */ =20 /* Initialize a die_reader_specs struct from a dwarf2_cu struct. */ @@ -7215,7 +7292,6 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *th= is_cu, struct attribute *comp_dir, *stmt_list, *low_pc, *high_pc, *ranges; int i,num_extra_attrs; struct dwarf2_section_info *dwo_abbrev_section; - struct attribute *attr; struct die_info *comp_unit_die; =20 /* At most one of these may be provided. */ @@ -7246,20 +7322,14 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *= this_cu, ranges =3D dwarf2_attr (stub_comp_unit_die, DW_AT_ranges, cu); comp_dir =3D dwarf2_attr (stub_comp_unit_die, DW_AT_comp_dir, cu); =20 - /* There should be a DW_AT_addr_base attribute here (if needed). - We need the value before we can process DW_FORM_GNU_addr_index - or DW_FORM_addrx. */ - cu->addr_base =3D 0; - attr =3D dwarf2_attr (stub_comp_unit_die, DW_AT_GNU_addr_base, cu); - if (attr) - cu->addr_base =3D DW_UNSND (attr); + auto maybe_addr_base =3D lookup_addr_base (cu, stub_comp_unit_die, t= rue); + if (maybe_addr_base.has_value ()) + cu->addr_base =3D *maybe_addr_base; =20 - /* There should be a DW_AT_ranges_base attribute here (if needed). - We need the value before we can process DW_AT_ranges. */ - cu->ranges_base =3D 0; - attr =3D dwarf2_attr (stub_comp_unit_die, DW_AT_GNU_ranges_base, cu); - if (attr) - cu->ranges_base =3D DW_UNSND (attr); + /* There should be a DW_AT_rnglists_base (DW_AT_GNU_ranges_base) att= ribute + here (if needed). We need the value before we can process + DW_AT_ranges. */ + cu->ranges_base =3D lookup_ranges_base (cu, stub_comp_unit_die); } else if (stub_comp_dir !=3D NULL) { @@ -7268,6 +7338,7 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *th= is_cu, comp_dir->name =3D DW_AT_comp_dir; comp_dir->form =3D DW_FORM_string; DW_STRING_IS_CANONICAL (comp_dir) =3D 0; + DW_STRING_IS_STR_INDEX (comp_dir) =3D false; DW_STRING (comp_dir) =3D stub_comp_dir; } =20 @@ -7368,8 +7439,7 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *th= is_cu, TUs by skipping the stub and going directly to the entry in the DWO f= ile. However, skipping the stub means we won't get DW_AT_comp_dir, so we h= ave to get it via circuitous means. Blech. */ - if (comp_dir !=3D NULL) - result_reader->comp_dir =3D DW_STRING (comp_dir); + result_reader->comp_dir =3D get_comp_dir_attr (comp_unit_die, cu); =20 /* Skip dummy compilation units. */ if (info_ptr >=3D begin_info_ptr + dwo_unit->length @@ -7667,6 +7737,13 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *= this_cu, init_cu_die_reader (&reader, cu, section, NULL, abbrev_table); info_ptr =3D read_full_die (&reader, &comp_unit_die, info_ptr, &has_chil= dren); =20 + /* DWO_AT_GNU_dwo_name and DW_AT_comp_dir in the stub may be using + DW_FORM_GNU_str_index which needs DW_AT_str_offsets_base. */ + struct attribute *attr =3D dwarf2_attr (comp_unit_die, + DW_AT_str_offsets_base, cu); + if (attr !=3D nullptr) + cu->str_offsets_base =3D DW_UNSND (attr); + if (skip_partial && comp_unit_die->tag =3D=3D DW_TAG_partial_unit) return; =20 @@ -7730,9 +7807,9 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *t= his_cu, } } =20 -/* Read CU/TU THIS_CU but do not follow DW_AT_GNU_dwo_name if present. - DWO_FILE, if non-NULL, is the DWO file to read (the caller is assumed - to have already done the lookup to find the DWO file). +/* Read CU/TU THIS_CU but do not follow DW_AT_GNU_dwo_name (DW_AT_dwo_name) + if present. DWO_FILE, if non-NULL, is the DWO file to read (the caller = is + assumed to have already done the lookup to find the DWO file). =20 The caller is required to fill in THIS_CU->section, THIS_CU->offset, and THIS_CU->is_debug_types, but nothing else. @@ -7744,10 +7821,14 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data = *this_cu, =20 THIS_CU->cu is always freed when done. This is done in order to not leave THIS_CU->cu in a state where we have - to care whether it refers to the "main" CU or the DWO CU. */ + to care whether it refers to the "main" CU or the DWO CU. + + When parent_cu is passed, it is used to provide a default value for + str_offsets_base and addr_base from the parent. */ =20 static void init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu, + struct dwarf2_cu *parent_cu, struct dwo_file *dwo_file, die_reader_func_ftype *die_reader_func, void *data) @@ -7786,6 +7867,11 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per= _cu_data *this_cu, ? rcuh_kind::TYPE : rcuh_kind::COMPILE)); =20 + if (parent_cu !=3D nullptr) + { + cu.str_offsets_base =3D parent_cu->str_offsets_base; + cu.addr_base =3D parent_cu->addr_base; + } this_cu->length =3D get_cu_length (&cu.header); =20 /* Skip dummy compilation units. */ @@ -7803,8 +7889,8 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_= cu_data *this_cu, die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data); } =20 -/* Read a CU/TU, except that this does not look for DW_AT_GNU_dwo_name and - does not lookup the specified DWO file. +/* Read a CU/TU, except that this does not look for DW_AT_GNU_dwo_name + (DW_AT_dwo_name) and does not lookup the specified DWO file. This cannot be used to read DWO files. =20 THIS_CU->cu is always freed when done. @@ -7817,7 +7903,7 @@ init_cutu_and_read_dies_simple (struct dwarf2_per_cu_= data *this_cu, die_reader_func_ftype *die_reader_func, void *data) { - init_cutu_and_read_dies_no_follow (this_cu, NULL, die_reader_func, data); + init_cutu_and_read_dies_no_follow (this_cu, NULL, NULL, die_reader_func,= data); } =0C /* Type Unit Groups. @@ -9327,7 +9413,9 @@ skip_one_die (const struct die_reader_specs *reader, = const gdb_byte *info_ptr, /* The only abbrev we care about is DW_AT_sibling. */ if (abbrev->attrs[i].name =3D=3D DW_AT_sibling) { - read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr); + bool ignored; + read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr, + &ignored); if (attr.form =3D=3D DW_FORM_ref_addr) complaint (_("ignoring absolute DW_AT_sibling")); else @@ -9423,6 +9511,7 @@ skip_one_die (const struct die_reader_specs *reader, = const gdb_byte *info_ptr, case DW_FORM_ref_udata: case DW_FORM_GNU_addr_index: case DW_FORM_GNU_str_index: + case DW_FORM_rnglistx: info_ptr =3D safe_skip_leb128 (info_ptr, buffer_end); break; case DW_FORM_indirect: @@ -11968,8 +12057,8 @@ create_dwo_cu_reader (const struct die_reader_specs= *reader, =20 static void create_cus_hash_table (struct dwarf2_per_objfile *dwarf2_per_objfile, - struct dwo_file &dwo_file, dwarf2_section_info §ion, - htab_t &cus_htab) + dwarf2_cu *cu, struct dwo_file &dwo_file, + dwarf2_section_info §ion, htab_t &cus_htab) { struct objfile *objfile =3D dwarf2_per_objfile->objfile; const gdb_byte *info_ptr, *end_ptr; @@ -12006,7 +12095,7 @@ create_cus_hash_table (struct dwarf2_per_objfile *d= warf2_per_objfile, create_dwo_cu_data.dwo_file =3D &dwo_file; =20 init_cutu_and_read_dies_no_follow ( - &per_cu, &dwo_file, create_dwo_cu_reader, &create_dwo_cu_data); + &per_cu, cu, &dwo_file, create_dwo_cu_reader, &create_dwo_cu_data); info_ptr +=3D per_cu.length; =20 // If the unit could not be parsed, skip it. @@ -13040,8 +13129,8 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *= per_cu, bfd_map_over_sections (dwo_file->dbfd.get (), dwarf2_locate_dwo_sections, &dwo_file->sections); =20 - create_cus_hash_table (dwarf2_per_objfile, *dwo_file, dwo_file->sections= .info, - dwo_file->cus); + create_cus_hash_table (dwarf2_per_objfile, per_cu->cu, *dwo_file, + dwo_file->sections.info, dwo_file->cus); =20 create_debug_types_hash_table (dwarf2_per_objfile, dwo_file.get (), dwo_file->sections.types, dwo_file->tus); @@ -14700,13 +14789,14 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_= ADDR *lowpc, attr =3D dwarf2_attr (die, DW_AT_ranges, cu); if (attr !=3D NULL) { - /* DW_AT_ranges_base does not apply to DIEs from the DWO skeleton. + /* DW_AT_rnglists_base does not apply to DIEs from the DWO skeleton. We take advantage of the fact that DW_AT_ranges does not appear in DW_TAG_compile_unit of DWO files. */ - int need_ranges_base =3D die->tag !=3D DW_TAG_compile_unit; + int need_ranges_base =3D die->tag !=3D DW_TAG_compile_unit + && cu->ranges_base.has_value(); unsigned int ranges_offset =3D (DW_UNSND (attr) + (need_ranges_base - ? cu->ranges_base + ? *cu->ranges_base : 0)); =20 /* Value of the DW_AT_ranges attribute is the offset in the @@ -14871,15 +14961,15 @@ dwarf2_record_block_ranges (struct die_info *die,= struct block *block, attr =3D dwarf2_attr (die, DW_AT_ranges, cu); if (attr) { - /* DW_AT_ranges_base does not apply to DIEs from the DWO skeleton. + /* DW_AT_rnglists_base does not apply to DIEs from the DWO skeleton. We take advantage of the fact that DW_AT_ranges does not appear in DW_TAG_compile_unit of DWO files. */ - int need_ranges_base =3D die->tag !=3D DW_TAG_compile_unit; - + int need_ranges_base =3D die->tag !=3D DW_TAG_compile_unit + && cu->ranges_base.has_value(); /* The value of the DW_AT_ranges attribute is the offset of the address range list in the .debug_ranges section. */ unsigned long offset =3D (DW_UNSND (attr) - + (need_ranges_base ? cu->ranges_base : 0)); + + (need_ranges_base ? *cu->ranges_base : 0)); =20 std::vector blockvec; dwarf2_ranges_process (offset, cu, @@ -18214,10 +18304,26 @@ read_full_die_1 (const struct die_reader_specs *r= eader, attributes. */ die->num_attrs =3D abbrev->num_attrs; =20 + std::vector indexes_that_need_reprocess; for (i =3D 0; i < abbrev->num_attrs; ++i) - info_ptr =3D read_attribute (reader, &die->attrs[i], &abbrev->attrs[i], - info_ptr); + { + bool need_reprocess; + info_ptr =3D + read_attribute (reader, &die->attrs[i], &abbrev->attrs[i], + info_ptr, &need_reprocess); + if (need_reprocess) + indexes_that_need_reprocess.push_back (i); + } =20 + struct attribute *attr =3D dwarf2_attr_no_follow (die, DW_AT_str_offsets= _base); + if (attr) + cu->str_offsets_base =3D DW_UNSND (attr); + + auto maybe_addr_base =3D lookup_addr_base(cu, die, false); + if (maybe_addr_base.has_value()) + cu->addr_base =3D *maybe_addr_base; + for (int index : indexes_that_need_reprocess) + read_attribute_reprocess (reader, &die->attrs[index]); *diep =3D die; *has_children =3D abbrev->has_children; return info_ptr; @@ -18729,12 +18835,23 @@ partial_die_info::read (const struct die_reader_s= pecs *reader, int has_high_pc_attr =3D 0; int high_pc_relative =3D 0; =20 + std::vector attr_vec; + std::vector indexes_that_need_reprocess; + attr_vec.resize(abbrev.num_attrs); for (i =3D 0; i < abbrev.num_attrs; ++i) { - struct attribute attr; - - info_ptr =3D read_attribute (reader, &attr, &abbrev.attrs[i], info_p= tr); + bool need_reprocess; + info_ptr =3D read_attribute (reader, &attr_vec[i], &abbrev.attrs[i], + info_ptr, &need_reprocess); + if (need_reprocess) + indexes_that_need_reprocess.push_back (i); + } + for (int index : indexes_that_need_reprocess) + read_attribute_reprocess (reader, &attr_vec[index]); =20 + for (i =3D 0; i < abbrev.num_attrs; ++i) + { + struct attribute &attr =3D attr_vec[i]; /* Store the data if it is of an attribute we want to keep in a partial symbol table. */ switch (attr.name) @@ -18882,10 +18999,11 @@ partial_die_info::read (const struct die_reader_s= pecs *reader, /* It would be nice to reuse dwarf2_get_pc_bounds here, but that requires a full DIE, so instead we just reimplement it. */ - int need_ranges_base =3D tag !=3D DW_TAG_compile_unit; + int need_ranges_base =3D tag !=3D DW_TAG_compile_unit + && cu->ranges_base.has_value(); unsigned int ranges_offset =3D (DW_UNSND (&attr) + (need_ranges_base - ? cu->ranges_base + ? *cu->ranges_base : 0)); =20 /* Value of the DW_AT_ranges attribute is the offset in the @@ -19176,12 +19294,62 @@ partial_die_info::fixup (struct dwarf2_cu *cu) fixup_called =3D 1; } =20 +/* Process the attributes that had to be skipped in the first round. These + attributes are the ones that need str_offsets_base or addr_base attribu= tes. + They could not have been processed in the first round, because at the t= ime + the values of str_offsets_base or addr_base may not have been known. */ +void read_attribute_reprocess (const struct die_reader_specs *reader, + struct attribute *attr) +{ + struct dwarf2_cu *cu =3D reader->cu; + switch (attr->form) + { + case DW_FORM_addrx: + case DW_FORM_GNU_addr_index: + DW_ADDR (attr) =3D read_addr_index (cu, DW_UNSND (attr)); + break; + case DW_FORM_strx: + case DW_FORM_strx1: + case DW_FORM_strx2: + case DW_FORM_strx3: + case DW_FORM_strx4: + case DW_FORM_GNU_str_index: + unsigned int str_index =3D DW_UNSND (attr); + if (reader->dwo_file !=3D NULL) + { + DW_STRING (attr) =3D read_dwo_str_index (reader, str_index); + DW_STRING_IS_CANONICAL (attr) =3D 0; + DW_STRING_IS_STR_INDEX (attr) =3D false; + } + else if (cu->str_offsets_base.has_value ()) + { + DW_STRING (attr) =3D read_stub_str_index (cu, str_index); + DW_STRING_IS_CANONICAL (attr) =3D 0; + DW_STRING_IS_STR_INDEX (attr) =3D false; + } + else + { + if (attr->name !=3D DW_AT_comp_dir + && attr->name !=3D DW_AT_GNU_dwo_name + && attr->name !=3D DW_AT_dwo_name) + { + error (_("Dwarf Error: %s/%s found in non-DWO CU"), + dwarf_form_name (attr->form), + dwarf_attr_name (attr->name)); + } + DW_UNSND (attr) =3D str_index; + DW_STRING_IS_STR_INDEX (attr) =3D true; + } + } +} + /* Read an attribute value described by an attribute form. */ =20 static const gdb_byte * read_attribute_value (const struct die_reader_specs *reader, struct attribute *attr, unsigned form, - LONGEST implicit_const, const gdb_byte *info_ptr) + LONGEST implicit_const, const gdb_byte *info_ptr, + bool *need_reprocess) { struct dwarf2_cu *cu =3D reader->cu; struct dwarf2_per_objfile *dwarf2_per_objfile @@ -19192,6 +19360,7 @@ read_attribute_value (const struct die_reader_specs= *reader, struct comp_unit_head *cu_header =3D &cu->header; unsigned int bytes_read; struct dwarf_block *blk; + *need_reprocess =3D false; =20 attr->form =3D (enum dwarf_form) form; switch (form) @@ -19255,6 +19424,7 @@ read_attribute_value (const struct die_reader_specs= *reader, case DW_FORM_string: DW_STRING (attr) =3D read_direct_string (abfd, info_ptr, &bytes_read= ); DW_STRING_IS_CANONICAL (attr) =3D 0; + DW_STRING_IS_STR_INDEX (attr) =3D false; info_ptr +=3D bytes_read; break; case DW_FORM_strp: @@ -19264,6 +19434,7 @@ read_attribute_value (const struct die_reader_specs= *reader, abfd, info_ptr, cu_header, &bytes_read); DW_STRING_IS_CANONICAL (attr) =3D 0; + DW_STRING_IS_STR_INDEX (attr) =3D false; info_ptr +=3D bytes_read; break; } @@ -19288,6 +19459,7 @@ read_attribute_value (const struct die_reader_specs= *reader, DW_STRING (attr) =3D read_indirect_string_from_dwz (objfile, dwz, str_offset); DW_STRING_IS_CANONICAL (attr) =3D 0; + DW_STRING_IS_STR_INDEX (attr) =3D false; info_ptr +=3D bytes_read; } break; @@ -19324,6 +19496,7 @@ read_attribute_value (const struct die_reader_specs= *reader, info_ptr +=3D bytes_read; break; case DW_FORM_udata: + case DW_FORM_rnglistx: DW_UNSND (attr) =3D read_unsigned_leb128 (abfd, info_ptr, &bytes_rea= d); info_ptr +=3D bytes_read; break; @@ -19365,22 +19538,15 @@ read_attribute_value (const struct die_reader_spe= cs *reader, info_ptr +=3D bytes_read; } info_ptr =3D read_attribute_value (reader, attr, form, implicit_cons= t, - info_ptr); + info_ptr, need_reprocess); break; case DW_FORM_implicit_const: DW_SND (attr) =3D implicit_const; break; case DW_FORM_addrx: case DW_FORM_GNU_addr_index: - if (reader->dwo_file =3D=3D NULL) - { - /* For now flag a hard error. - Later we can turn this into a complaint. */ - error (_("Dwarf Error: %s found in non-DWO CU [in module %s]"), - dwarf_form_name (form), - bfd_get_filename (abfd)); - } - DW_ADDR (attr) =3D read_addr_index_from_leb128 (cu, info_ptr, &bytes= _read); + *need_reprocess =3D true; + DW_UNSND (attr) =3D read_unsigned_leb128 (abfd, info_ptr, &bytes_rea= d); info_ptr +=3D bytes_read; break; case DW_FORM_strx: @@ -19389,14 +19555,6 @@ read_attribute_value (const struct die_reader_spec= s *reader, case DW_FORM_strx3: case DW_FORM_strx4: case DW_FORM_GNU_str_index: - if (reader->dwo_file =3D=3D NULL) - { - /* For now flag a hard error. - Later we can turn this into a complaint if warranted. */ - error (_("Dwarf Error: %s found in non-DWO CU [in module %s]"), - dwarf_form_name (form), - bfd_get_filename (abfd)); - } { ULONGEST str_index; if (form =3D=3D DW_FORM_strx1) @@ -19424,9 +19582,9 @@ read_attribute_value (const struct die_reader_specs= *reader, str_index =3D read_unsigned_leb128 (abfd, info_ptr, &bytes_read); info_ptr +=3D bytes_read; } - DW_STRING (attr) =3D read_str_index (reader, str_index); - DW_STRING_IS_CANONICAL (attr) =3D 0; - } + *need_reprocess =3D true; + DW_UNSND (attr) =3D str_index; + } break; default: error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %= s]"), @@ -19462,11 +19620,12 @@ read_attribute_value (const struct die_reader_spe= cs *reader, static const gdb_byte * read_attribute (const struct die_reader_specs *reader, struct attribute *attr, struct attr_abbrev *abbrev, - const gdb_byte *info_ptr) + const gdb_byte *info_ptr, bool *need_reprocess) { attr->name =3D abbrev->name; return read_attribute_value (reader, attr, abbrev->form, - abbrev->implicit_const, info_ptr); + abbrev->implicit_const, info_ptr, + need_reprocess); } =20 /* Read dwarf information from a buffer. */ @@ -19893,27 +20052,30 @@ read_signed_leb128 (bfd *abfd, const gdb_byte *bu= f, } =20 /* Given index ADDR_INDEX in .debug_addr, fetch the value. - ADDR_BASE is the DW_AT_GNU_addr_base attribute or zero. + ADDR_BASE is the DW_AT_addr_base (DW_AT_GNU_addr_base) attribute or zer= o. ADDR_SIZE is the size of addresses from the CU header. */ =20 static CORE_ADDR read_addr_index_1 (struct dwarf2_per_objfile *dwarf2_per_objfile, - unsigned int addr_index, ULONGEST addr_base, int addr_size) + unsigned int addr_index, gdb::optional addr_base, + int addr_size) { struct objfile *objfile =3D dwarf2_per_objfile->objfile; bfd *abfd =3D objfile->obfd; const gdb_byte *info_ptr; + ULONGEST addr_base_or_zero =3D addr_base.has_value() ? *addr_base : 0; =20 dwarf2_read_section (objfile, &dwarf2_per_objfile->addr); if (dwarf2_per_objfile->addr.buffer =3D=3D NULL) error (_("DW_FORM_addr_index used without .debug_addr section [in modu= le %s]"), objfile_name (objfile)); - if (addr_base + addr_index * addr_size >=3D dwarf2_per_objfile->addr.siz= e) + if (addr_base_or_zero + addr_index * addr_size + >=3D dwarf2_per_objfile->addr.size) error (_("DW_FORM_addr_index pointing outside of " ".debug_addr section [in module %s]"), objfile_name (objfile)); info_ptr =3D (dwarf2_per_objfile->addr.buffer - + addr_base + addr_index * addr_size); + + addr_base_or_zero + addr_index * addr_size); if (addr_size =3D=3D 4) return bfd_get_32 (abfd, info_ptr); else @@ -19946,7 +20108,7 @@ read_addr_index_from_leb128 (struct dwarf2_cu *cu, = const gdb_byte *info_ptr, =20 struct dwarf2_read_addr_index_data { - ULONGEST addr_base; + gdb::optional addr_base; int addr_size; }; =20 @@ -19978,7 +20140,7 @@ dwarf2_read_addr_index (struct dwarf2_per_cu_data *= per_cu, { struct dwarf2_per_objfile *dwarf2_per_objfile =3D per_cu->dwarf2_per_obj= file; struct dwarf2_cu *cu =3D per_cu->cu; - ULONGEST addr_base; + gdb::optional addr_base; int addr_size; =20 /* We need addr_base and addr_size. @@ -20018,21 +20180,21 @@ dwarf2_read_addr_index (struct dwarf2_per_cu_data= *per_cu, addr_size); } =20 -/* Given a DW_FORM_GNU_str_index or DW_FORM_strx, fetch the string. - This is only used by the Fission support. */ +/* Given a DW_FORM_GNU_str_index value STR_INDEX, fetch the string. + STR_SECTION, STR_OFFSETS_SECTION can be from a Fission stub or a + DWO file. */ =20 static const char * -read_str_index (const struct die_reader_specs *reader, ULONGEST str_index) +read_str_index (struct dwarf2_cu *cu, + struct dwarf2_section_info *str_section, + struct dwarf2_section_info *str_offsets_section, + ULONGEST str_offsets_base, ULONGEST str_index) { - struct dwarf2_cu *cu =3D reader->cu; struct dwarf2_per_objfile *dwarf2_per_objfile =3D cu->per_cu->dwarf2_per_objfile; struct objfile *objfile =3D dwarf2_per_objfile->objfile; const char *objf_name =3D objfile_name (objfile); bfd *abfd =3D objfile->obfd; - struct dwarf2_section_info *str_section =3D &reader->dwo_file->sections.= str; - struct dwarf2_section_info *str_offsets_section =3D - &reader->dwo_file->sections.str_offsets; const gdb_byte *info_ptr; ULONGEST str_offset; static const char form_name[] =3D "DW_FORM_GNU_str_index or DW_FORM_strx= "; @@ -20040,18 +20202,17 @@ read_str_index (const struct die_reader_specs *re= ader, ULONGEST str_index) dwarf2_read_section (objfile, str_section); dwarf2_read_section (objfile, str_offsets_section); if (str_section->buffer =3D=3D NULL) - error (_("%s used without .debug_str.dwo section" + error (_("%s used without %s section" " in CU at offset %s [in module %s]"), - form_name, sect_offset_str (cu->header.sect_off), objf_name); + form_name, get_section_name (str_section), + sect_offset_str (cu->header.sect_off), objf_name); if (str_offsets_section->buffer =3D=3D NULL) - error (_("%s used without .debug_str_offsets.dwo section" + error (_("%s used without %s section" " in CU at offset %s [in module %s]"), - form_name, sect_offset_str (cu->header.sect_off), objf_name); - if (str_index * cu->header.offset_size >=3D str_offsets_section->size) - error (_("%s pointing outside of .debug_str_offsets.dwo" - " section in CU at offset %s [in module %s]"), - form_name, sect_offset_str (cu->header.sect_off), objf_name); + form_name, get_section_name (str_section), + sect_offset_str (cu->header.sect_off), objf_name); info_ptr =3D (str_offsets_section->buffer + + str_offsets_base + str_index * cu->header.offset_size); if (cu->header.offset_size =3D=3D 4) str_offset =3D bfd_get_32 (abfd, info_ptr); @@ -20064,6 +20225,71 @@ read_str_index (const struct die_reader_specs *rea= der, ULONGEST str_index) return (const char *) (str_section->buffer + str_offset); } =20 +/* Given a DW_FORM_GNU_str_index from a DWO file, fetch the string. */ + +static const char * +read_dwo_str_index (const struct die_reader_specs *reader, ULONGEST str_in= dex) +{ + ULONGEST str_offsets_base =3D reader->cu->header.version >=3D 5 + ? reader->cu->header.addr_size : 0; + return read_str_index (reader->cu, + &reader->dwo_file->sections.str, + &reader->dwo_file->sections.str_offsets, + str_offsets_base, str_index); +} + +/* Given a DW_FORM_GNU_str_index from a Fission stub, fetch the string. */ + +static const char * +read_stub_str_index (struct dwarf2_cu *cu, ULONGEST str_index) +{ + struct objfile *objfile =3D cu->per_cu->dwarf2_per_objfile->objfile; + const char *objf_name =3D objfile_name (objfile); + static const char form_name[] =3D "DW_FORM_GNU_str_index"; + static const char str_offsets_attr_name[] =3D "DW_AT_str_offsets"; + + if (!cu->str_offsets_base.has_value()) + error (_("%s used in Fission stub without %s" + " in CU at offset 0x%lx [in module %s]"), + form_name, str_offsets_attr_name, + (long) cu->header.offset_size, objf_name); + + return read_str_index (cu, + &cu->per_cu->dwarf2_per_objfile->str, + &cu->per_cu->dwarf2_per_objfile->str_offsets, + *cu->str_offsets_base, str_index); +} + +/* Wrapper around read_stub_str_index for attributes that *may* be using + DW_AT_GNU_str_index from a non-DWO file. */ + +static const char * +get_stub_string_attr (struct dwarf2_cu *cu, const struct attribute *attr) +{ + if (DW_STRING_IS_STR_INDEX (attr)) + return read_stub_str_index (cu, DW_UNSND (attr)); + return DW_STRING (attr); +} + +/* Fetch the value of the DW_AT_comp_dir attribute. + The result is NULL if the attribute isn't present or if the value is + empty string. If the caller needs to do something different depending on + whether the attribute is present, the caller must check. This function + should always be used to fetch this attribute as it handles + DW_AT_GNU_str_index from Fission stubs. This is important as the low + level DIE reader combines the contents of the stub with the DWO top lev= el + DIE so that the rest of the code only ever sees one DIE. */ + +static const char * +get_comp_dir_attr (struct die_info *die, struct dwarf2_cu *cu) +{ + const struct attribute *attr =3D dwarf2_attr (die, DW_AT_comp_dir, cu); + if (attr =3D=3D NULL) + return NULL; + return get_stub_string_attr (cu, attr); +} + + /* Return the length of an LEB128 number in BUF. */ =20 static int diff --git a/gdb/dwarf2read.h b/gdb/dwarf2read.h index 53fc7f4d9b..d2b06c9a4a 100644 --- a/gdb/dwarf2read.h +++ b/gdb/dwarf2read.h @@ -156,6 +156,7 @@ public: dwarf2_section_info macinfo {}; dwarf2_section_info macro {}; dwarf2_section_info str {}; + dwarf2_section_info str_offsets {}; dwarf2_section_info line_str {}; dwarf2_section_info ranges {}; dwarf2_section_info rnglists {}; diff --git a/gdb/symfile.h b/gdb/symfile.h index cb5bed9d85..fc0fa77183 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -569,6 +569,7 @@ struct dwarf2_debug_sections { struct dwarf2_section_names macinfo; struct dwarf2_section_names macro; struct dwarf2_section_names str; + struct dwarf2_section_names str_offsets; struct dwarf2_section_names line_str; struct dwarf2_section_names ranges; struct dwarf2_section_names rnglists; diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c index bc4877389b..341afd4001 100644 --- a/gdb/xcoffread.c +++ b/gdb/xcoffread.c @@ -166,6 +166,7 @@ static const struct dwarf2_debug_sections dwarf2_xcoff_= names =3D { { NULL, NULL }, { ".dwmac", NULL }, { ".dwstr", NULL }, + { NULL, NULL }, /* debug_str_offsets */ { NULL, NULL }, /* debug_line_str */ { ".dwrnges", NULL }, { NULL, NULL }, /* debug_rnglists */ --=20 2.24.0.432.g9d3f5f5b63-goog