From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pg1-x52c.google.com (mail-pg1-x52c.google.com [IPv6:2607:f8b0:4864:20::52c]) by sourceware.org (Postfix) with ESMTPS id D761F3858D1E for ; Wed, 13 Mar 2024 02:09:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D761F3858D1E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D761F3858D1E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::52c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710295809; cv=none; b=Z/RFkwQ1jvMwVvW86sZiuGuctQI9mzdr7a4l5qjVFDBPmNvmBwnq+TRGN0iHHxIOuK41Huc5dJhR/CT+jPjfseM0JzX75ELvUsiAwzigpicsRwLmsvEPnPu/BDKNvMqNMm9RkXt/ItcSFyPlDYGWlIA/vJ4teujKX4PTayDRKTU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710295809; c=relaxed/simple; bh=LG7+XWx02Hf6y+oU6+p3OYSDmMmiLzdpckz1iKCG4hc=; h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To; b=elpyYTb9Ts1I+pyVGqQNnnxY1EillISB5e/oF1C7v7NIqkDLvHncxEcRH5u2xjyKn0c/2flh6t1QgEPdO1sVaNrS4aY07TeV5RymkHokZ+4YQjzQFYhYWDk1gwb5QPLNi1/HzIWk5zvyQJAmCkkBXAYcgrhDcZLtXdpq0wNdi6k= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pg1-x52c.google.com with SMTP id 41be03b00d2f7-5bdbe2de25fso5115433a12.3 for ; Tue, 12 Mar 2024 19:09:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710295795; x=1710900595; darn=sourceware.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=MoKy9c17qpUG/yKfdW++kyhpLOgZZg6DsbsBc5rIzuI=; b=gicZI2MjS64Q3b8qNgY97YF3l8+wOKkRVnet59InSTDrQ2LL9U15oB/X08gJrIsVfL XtzJ34ECFz4kXE+kDKReYoxE+fFQ9xeo7gRyNsRdk68pZTz3TpjqqA0EiZetANbHALbJ KO9aBX6moYyiMKJFADehxU0NbcMWv46qixKwdplXuty+4M8XaKw8L0RGUMRHGUjvq+xZ sQgAmt/OSO8be1cmqvRa82j1YPJtZ5hi65qRpIZZSX4+Ese09QbKBXYNj1+r2nxIUzVW 3dBYtWYO7trRTSOyfAZelg6JrSQuXbQNAthbcZh0rli7mrNbPmkW7EfPX6tvQ+D4Jyzg 6X4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710295795; x=1710900595; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=MoKy9c17qpUG/yKfdW++kyhpLOgZZg6DsbsBc5rIzuI=; b=eQtI22m3cSuFObGHVkX3OjQ1394ZVmFg9P694rJiD0PUeNhb3H1PRtmo18rIDKupb5 JaLDvsUeGFF3dqeZd1pD0kCETrQu0JSa+EwkCsmhJZE3fK/q1XyaKmLXC11Hzm4k3U9/ 2/bAiiOmgnMPY/yvcTlvS18usUKl2IaHcVaAB6J/ak2Ju0pWQsUDujs9RWpkG0K4crkp HHRfR4t8t2F50U6ONJIPlAW4F042nwfWPkmPDSS5XvcELV62bY6gLUsbAQ15AoiuSBQj a4ZO8a+7gJX14vi8NOBd9gFMp11Ar2oafPiFkhYGhBxzJoUVIlPYPlrsWRLM0kukdqaS KprA== X-Gm-Message-State: AOJu0YxjLbNfzFKAWxqtHTiUPovcrUpDaqhfrvUBAX3k5wmH6u6m9Y6T 7OEN/gKgRUjitxmh4K3rrfWawyOa8MAGXtrR9Ovlo21xc+eFX3OolbbY6FlX9NOS73UNgd1nMWf sBNshhXWNOVIUwZe7Uy7ACJB3V7uJgF5Z X-Google-Smtp-Source: AGHT+IHcnegIbmmZ7f9SU449/14w97SwlOqQIqmOtPHDegOGnnJ4pGKCfRQtsDfs0SyqCWUFgrJbIXp/15htiU4670s= X-Received: by 2002:a05:6a20:549c:b0:1a3:1574:8a16 with SMTP id i28-20020a056a20549c00b001a315748a16mr10170318pzk.48.1710295794796; Tue, 12 Mar 2024 19:09:54 -0700 (PDT) MIME-Version: 1.0 References: <20240216024523.227437-3-zeck654321@gmail.com> In-Reply-To: <20240216024523.227437-3-zeck654321@gmail.com> From: Zeck S Date: Tue, 12 Mar 2024 21:09:43 -0500 Message-ID: Subject: Re: [RFC][PATCH?] fixed some segfaults and bugs in mdebug support To: gdb-patches@sourceware.org Cc: Andrew Burgess , tom@tromey.com Content-Type: multipart/alternative; boundary="0000000000004f4eaf0613814503" X-Spam-Status: No, score=-9.5 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,GIT_PATCH_0,HTML_MESSAGE,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: --0000000000004f4eaf0613814503 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Just checking to see if there is still interest in taking this patch. I could split it up somehow or remove parts of it if I need to. On Thu, Feb 15, 2024 at 8:48=E2=80=AFPM Zeck S wrote: > Tried to send this a week ago, but I see somehow send email did not thread > it correctly. > Trying again, I think it was because the subject line was messed up. > > Addressed comments, adapted some core tests, fixed more bugs. > In addition to the modified tests, I specifically also got > gdb.base/relocate.exp working to sort out some problems. > > As always, glad to address feedback, and thanks for the patience. > > I reverted some of my code around parse_lines addresses. > The Procedure Descriptor Record format is weird. > The File Descriptor Record has the final correct address > of the LOWEST PDR, only. This is used as a base address > for a kind of janky fixup/relocation system. > I suspect originally the PDR addresses were directly useful in simpler > formats. > > Based on comments in bfd ecofflink and documentation about something > similar in > "MIPS Mdebug Debugging Information" by David Anderson > that describes HDRR offsets as offsets from the beginning of the a.out > as a "design mistake" I think some compilers > set the PDR address to a location in an object file. > > This means there's basically a garbage offset added to all the PDRs. > So all PDRs have their addresses subtracted from the lowest to kind > treat it as 0, and then the lowest PDRs REAL correct address > is used from the FDR, as an offset. > > IDO actually always outputs the lowest PDR's address as 0 > so subtracting it out does nothing, but hurts nothing. > > I can find no real documentation about this. > > I did find precedent for what my reverted code was doing in > section 5.3.4.1 of ""Tru64 UNIX Object File and Symbol Table Format > Specification" > but after I figured out what the original code was doing I > reverted those changes to distrub the code less. > > --- > gdb/mdebugread.c | 230 ++++-- > gdb/testsuite/boards/qemu-user.exp | 267 +++++++ > gdb/testsuite/gdb.mdebug/README | 67 ++ > gdb/testsuite/gdb.mdebug/break.c | 92 +++ > gdb/testsuite/gdb.mdebug/break.exp | 921 ++++++++++++++++++++++ > gdb/testsuite/gdb.mdebug/break1.c | 59 ++ > gdb/testsuite/gdb.mdebug/info-types-c.exp | 67 ++ > gdb/testsuite/gdb.mdebug/info-types.c | 116 +++ > 8 files changed, 1770 insertions(+), 49 deletions(-) > create mode 100644 gdb/testsuite/boards/qemu-user.exp > create mode 100644 gdb/testsuite/gdb.mdebug/README > create mode 100644 gdb/testsuite/gdb.mdebug/break.c > create mode 100644 gdb/testsuite/gdb.mdebug/break.exp > create mode 100644 gdb/testsuite/gdb.mdebug/break1.c > create mode 100644 gdb/testsuite/gdb.mdebug/info-types-c.exp > create mode 100644 gdb/testsuite/gdb.mdebug/info-types.c > > diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c > index cd6638224e7..0118507a8f3 100644 > --- a/gdb/mdebugread.c > +++ b/gdb/mdebugread.c > @@ -237,7 +237,7 @@ static struct type *new_type (char *); > enum block_type { FUNCTION_BLOCK, NON_FUNCTION_BLOCK }; > > static struct block *new_block (struct objfile *objfile, > - enum block_type, enum language); > + enum block_type, enum language, bool > is_global); > > static struct compunit_symtab *new_symtab (const char *, int, struct > objfile *); > > @@ -246,7 +246,7 @@ static struct linetable *new_linetable (int); > static struct blockvector *new_bvect (int); > > static struct type *parse_type (int, union aux_ext *, unsigned int, int = *, > - int, const char *); > + int, const char *, bool); > > static struct symbol *mylookup_symbol (const char *, const struct block = *, > domain_enum, enum address_class); > @@ -572,7 +572,7 @@ add_data_symbol (SYMR *sh, union aux_ext *ax, int > bigend, > || sh->sc =3D=3D scNil || sh->index =3D=3D indexNil) > s->set_type (builtin_type (objfile)->nodebug_data_symbol); > else > - s->set_type (parse_type (cur_fd, ax, sh->index, 0, bigend, name)); > + s->set_type (parse_type (cur_fd, ax, sh->index, 0, bigend, name, > false)); > /* Value of a data symbol is its memory address. */ > } > > @@ -624,8 +624,17 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char > *ext_sh, int bigend, > break; > } > > - if (section_index !=3D -1) > - sh->value +=3D section_offsets[section_index]; > + if (section_index !=3D -1) { > + int offset =3D section_offsets[section_index]; > + if ((bfd_get_file_flags (objfile->obfd.get ()) & (EXEC_P | DYNAMIC)) > =3D=3D 0) > + { > + /* This is attempting to detect .o files. > + Their sections are relocated in symfile.c > default_symfile_offsets > + but section_offsets are set to 0 there and the offset is put > in the vma. */ > + offset +=3D > objfile->sections_start[section_index].the_bfd_section->vma; > + } > + sh->value +=3D offset; > + } > > switch (sh->st) > { > @@ -705,7 +714,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char > *ext_sh, int bigend, > break; > } > s->set_value_longest (svalue); > - s->set_type (parse_type (cur_fd, ax, sh->index, 0, bigend, name)); > + s->set_type (parse_type (cur_fd, ax, sh->index, 0, bigend, name, > false)); > add_symbol (s, top_stack->cur_st, top_stack->cur_block); > break; > > @@ -761,7 +770,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char > *ext_sh, int bigend, > t =3D builtin_type (objfile)->builtin_int; > else > { > - t =3D parse_type (cur_fd, ax, sh->index + 1, 0, bigend, name); > + t =3D parse_type (cur_fd, ax, sh->index + 1, 0, bigend, name, > false); > if (strcmp (name, "malloc") =3D=3D 0 > && t->code () =3D=3D TYPE_CODE_VOID) > { > @@ -805,7 +814,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char > *ext_sh, int bigend, > s->type ()->set_is_prototyped (true); > > /* Create and enter a new lexical context. */ > - b =3D new_block (objfile, FUNCTION_BLOCK, s->language ()); > + b =3D new_block (objfile, FUNCTION_BLOCK, s->language (), false); > s->set_value_block (b); > b->set_function (s); > b->set_start (sh->value); > @@ -1135,7 +1144,13 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char > *ext_sh, int bigend, > } > > top_stack->blocktype =3D stBlock; > - b =3D new_block (objfile, NON_FUNCTION_BLOCK, psymtab_language); > + > + /* Using psymtab_langauge fixes commit 76fc0f62138e. > + This file does not use buildsym-lecacy. > + start_compunit_symtab () is never called. > + get_current_subfile () will crash because > + buildsym_compunit has never been initialized. */ > + b =3D new_block (objfile, NON_FUNCTION_BLOCK, psymtab_language, > false); > b->set_start (sh->value + top_stack->procadr); > b->set_superblock (top_stack->cur_block); > top_stack->cur_block =3D b; > @@ -1247,7 +1262,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char > *ext_sh, int bigend, > f->set_loc_bitpos (sh->value); > bitsize =3D 0; > f->set_type (parse_type (cur_fd, ax, sh->index, &bitsize, bigend, > - name)); > + name, false)); > f->set_bitsize (bitsize); > } > break; > @@ -1269,7 +1284,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char > *ext_sh, int bigend, > pend =3D is_pending_symbol (cur_fdr, ext_sh); > if (pend =3D=3D NULL) > { > - t =3D parse_type (cur_fd, ax, sh->index, NULL, bigend, name); > + t =3D parse_type (cur_fd, ax, sh->index, NULL, bigend, name, tr= ue); > add_pending (cur_fdr, ext_sh, t); > } > else > @@ -1382,7 +1397,7 @@ basic_type (int bt, struct objfile *objfile) > if (map_bt[bt]) > return map_bt[bt]; > > - type_allocator alloc (objfile, get_current_subfile ()->language); > + type_allocator alloc (objfile, psymtab_language); > > switch (bt) > { > @@ -1514,7 +1529,7 @@ basic_type (int bt, struct objfile *objfile) > > static struct type * > parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, > - int bigend, const char *sym_name) > + int bigend, const char *sym_name, bool is_stTypedef) > { > TIR t[1]; > struct type *tp =3D 0; > @@ -1571,7 +1586,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int > aux_index, int *bs, > } > } > > - type_allocator alloc (mdebugread_objfile, get_current_subfile > ()->language); > + type_allocator alloc (mdebugread_objfile, psymtab_language); > > /* Move on to next aux. */ > ax++; > @@ -1628,7 +1643,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int > aux_index, int *bs, > xref_fh =3D get_rfd (fd, rf); > xref_fd =3D xref_fh - debug_info->fdr; > tp =3D parse_type (xref_fd, debug_info->external_aux + > xref_fh->iauxBase, > - rn->index, NULL, xref_fh->fBigendian, sym_name); > + rn->index, NULL, xref_fh->fBigendian, sym_name, false= ); > } > > /* All these types really point to some (common) MIPS type > @@ -1785,6 +1800,13 @@ parse_type (int fd, union aux_ext *ax, unsigned int > aux_index, int *bs, > if (t->continued) > complaint (_("illegal TIR continued for %s"), sym_name); > > + if (is_stTypedef) > + { > + struct type *wrap =3D alloc.new_type (TYPE_CODE_TYPEDEF, 0, > sym_name); > + wrap->set_target_type(tp); > + tp =3D wrap; > + } > + > return tp; > } > > @@ -1839,7 +1861,7 @@ upgrade_type (int fd, struct type **tpp, int tq, > union aux_ext *ax, int bigend, > > indx =3D parse_type (fh - debug_info->fdr, > debug_info->external_aux + fh->iauxBase, > - id, NULL, bigend, sym_name); > + id, NULL, bigend, sym_name, false); > > /* The bounds type should be an integer type, but might be anything > else due to corrupt aux entries. */ > @@ -2155,7 +2177,7 @@ parse_external (EXTR *es, int bigend, const > section_offsets §ion_offsets, > > static void > parse_lines (FDR *fh, PDR *pr, struct linetable *lt, int maxlines, > - CORE_ADDR lowest_pdr_addr) > + CORE_ADDR textlow, CORE_ADDR lowest_pdr_addr) > { > unsigned char *base; > int j, k; > @@ -2169,7 +2191,6 @@ parse_lines (FDR *fh, PDR *pr, struct linetable *lt, > int maxlines, > for (j =3D 0; j < fh->cpd; j++, pr++) > { > CORE_ADDR l; > - CORE_ADDR adr; > unsigned char *halt; > > /* No code for this one. */ > @@ -2186,9 +2207,15 @@ parse_lines (FDR *fh, PDR *pr, struct linetable > *lt, int maxlines, > halt =3D base + fh->cbLine; > base +=3D pr->cbLineOffset; > > - adr =3D pr->adr - lowest_pdr_addr; > - > - l =3D adr >> 2; /* in words */ > + /* textlow is the FDR->adr, for the file containing these PDRs. > + FDR->adr is the absolute address of the lowest PDR. > + PDR->adr's themselves, are relative offsets. > + The PDR->adr's may start at 0, or they could have an offset > + based on the PDRs position in an object file. > + This is why the lowest PDR address is subtracted > + from all other PDRs addresses, to subtract out the potential > offset. > + See bfd/ecofflink.c comments. */ > + l =3D (textlow + pr->adr - lowest_pdr_addr) >> 2; /* in > words */ > for (lineno =3D pr->lnLow; base < halt;) > { > count =3D *base & 0x0f; > @@ -3047,28 +3074,49 @@ parse_partial_symbols (minimal_symbol_reader > &reader, > index into the namestring which indicates the > debugging type symbol. */ > > + int section; > + bfd_vma address; > + > switch (p[1]) > { > case 'S': > + section =3D SECT_OFF_DATA (objfile); > + address =3D sh.value; > + if ((bfd_get_file_flags (objfile->obfd.get ()) & > (EXEC_P | DYNAMIC)) =3D=3D 0) > + { > + /* This is attempting to detect .o files. > + Their sections are relocated in symfile.c > default_symfile_offsets > + but section_offsets are set to 0 there and > the offset is put in the vma. */ > + address +=3D > objfile->sections_start[section].the_bfd_section->vma; > + } > pst->add_psymbol (gdb::string_view (namestring, > p - > namestring), > true, VAR_DOMAIN, LOC_STATIC, > - SECT_OFF_DATA (objfile), > + section, > psymbol_placement::STATIC, > - unrelocated_addr (sh.value), > + unrelocated_addr (address), > psymtab_language, > partial_symtabs, objfile); > continue; > case 'G': > + section =3D SECT_OFF_DATA (objfile); > + address =3D sh.value; > + if ((bfd_get_file_flags (objfile->obfd.get ()) & > (EXEC_P | DYNAMIC)) =3D=3D 0) > + { > + /* This is attempting to detect .o files. > + Their sections are relocated in symfile.c > default_symfile_offsets > + but section_offsets are set to 0 there and the > offset is put in the vma. */ > + address +=3D > objfile->sections_start[section].the_bfd_section->vma; > + } > /* The addresses in these entries are reported > to be wrong. See the code that reads 'G's > for symtabs. */ > pst->add_psymbol (gdb::string_view (namestring, > p - > namestring), > true, VAR_DOMAIN, LOC_STATIC, > - SECT_OFF_DATA (objfile), > + section, > psymbol_placement::GLOBAL, > - unrelocated_addr (sh.value), > + unrelocated_addr (address), > psymtab_language, > partial_symtabs, objfile); > continue; > @@ -3215,12 +3263,21 @@ parse_partial_symbols (minimal_symbol_reader > &reader, > function_outside_compilation_unit_complaint > (copy.c_str ()); > } > + section =3D SECT_OFF_TEXT (objfile); > + address =3D sh.value; > + if ((bfd_get_file_flags (objfile->obfd.get ()) & > (EXEC_P | DYNAMIC)) =3D=3D 0) > + { > + /* This is attempting to detect .o files. > + Their sections are relocated in symfile.c > default_symfile_offsets > + but section_offsets are set to 0 there and > the offset is put in the vma. */ > + address +=3D > objfile->sections_start[section].the_bfd_section->vma; > + } > pst->add_psymbol (gdb::string_view (namestring, > p - > namestring), > true, VAR_DOMAIN, LOC_BLOCK, > - SECT_OFF_TEXT (objfile), > + section, > psymbol_placement::STATIC, > - unrelocated_addr (sh.value), > + unrelocated_addr (address), > psymtab_language, > partial_symtabs, objfile); > continue; > @@ -3236,12 +3293,21 @@ parse_partial_symbols (minimal_symbol_reader > &reader, > function_outside_compilation_unit_complaint > (copy.c_str ()); > } > + section =3D SECT_OFF_TEXT (objfile); > + address =3D sh.value; > + if ((bfd_get_file_flags (objfile->obfd.get ()) & > (EXEC_P | DYNAMIC)) =3D=3D 0) > + { > + /* This is attempting to detect .o files. > + Their sections are relocated in symfile.c > default_symfile_offsets > + but section_offsets are set to 0 there and > the offset is put in the vma. */ > + address +=3D > objfile->sections_start[section].the_bfd_section->vma; > + } > pst->add_psymbol (gdb::string_view (namestring, > p - > namestring), > true, VAR_DOMAIN, LOC_BLOCK, > - SECT_OFF_TEXT (objfile), > + section, > psymbol_placement::GLOBAL, > - unrelocated_addr (sh.value), > + unrelocated_addr (address), > psymtab_language, > partial_symtabs, objfile); > continue; > @@ -3419,6 +3485,9 @@ parse_partial_symbols (minimal_symbol_reader &reade= r, > break; > } > > + bfd_vma address; > + /* some symbols don't use the above section */ > + int section_override; > switch (sh.st) > { > unrelocated_addr high; > @@ -3426,9 +3495,18 @@ parse_partial_symbols (minimal_symbol_reader > &reader, > int new_sdx; > > case stStaticProc: > - reader.record_with_info (sym_name, minsym_value, > + section_override =3D SECT_OFF_TEXT (objfile); > + address =3D (bfd_vma)minsym_value; > + if ((bfd_get_file_flags (objfile->obfd.get ()) & > (EXEC_P | DYNAMIC)) =3D=3D 0) > + { > + /* This is attempting to detect .o files. > + Their sections are relocated in symfile.c > default_symfile_offsets > + but section_offsets are set to 0 there and > the offset is put in the vma. */ > + address +=3D > objfile->sections_start[section_override].the_bfd_section->vma; > + } > + reader.record_with_info (sym_name, > (unrelocated_addr)address, > mst_file_text, > - SECT_OFF_TEXT (objfile)); > + section_override); > > /* FALLTHROUGH */ > > @@ -3476,12 +3554,21 @@ parse_partial_symbols (minimal_symbol_reader > &reader, > still able to find the PROGRAM name via the partial > symbol table, and the MAIN__ symbol via the minimal > symbol table. */ > + > + address =3D sh.value; > + if ((bfd_get_file_flags (objfile->obfd.get ()) & (EXEC_P > | DYNAMIC)) =3D=3D 0) > + { > + /* This is attempting to detect .o files. > + Their sections are relocated in symfile.c > default_symfile_offsets > + but section_offsets are set to 0 there and the > offset is put in the vma. */ > + address +=3D > objfile->sections_start[section].the_bfd_section->vma; > + } > if (sh.st =3D=3D stProc) > pst->add_psymbol (sym_name, true, > VAR_DOMAIN, LOC_BLOCK, > section, > psymbol_placement::GLOBAL, > - unrelocated_addr (sh.value), > + unrelocated_addr (address), > psymtab_language, > partial_symtabs, objfile); > else > @@ -3489,7 +3576,7 @@ parse_partial_symbols (minimal_symbol_reader &reade= r, > VAR_DOMAIN, LOC_BLOCK, > section, > psymbol_placement::STATIC, > - unrelocated_addr (sh.value), > + unrelocated_addr (address), > psymtab_language, > partial_symtabs, objfile); > > @@ -3517,13 +3604,36 @@ parse_partial_symbols (minimal_symbol_reader > &reader, > > case stStatic: /* Variable */ > if (SC_IS_DATA (sh.sc)) > - reader.record_with_info (sym_name, minsym_value, > + { > + section_override =3D SECT_OFF_DATA (objfile); > + address =3D 0; > + if ((bfd_get_file_flags (objfile->obfd.get ()) & > (EXEC_P | DYNAMIC)) =3D=3D 0) > + { > + /* This is attempting to detect .o files. > + Their sections are relocated in symfile.c > default_symfile_offsets > + but section_offsets are set to 0 there and > the offset is put in the vma. */ > + address +=3D > objfile->sections_start[section_override].the_bfd_section->vma; > + } > + reader.record_with_info (sym_name, > (unrelocated_addr)(((bfd_vma)minsym_value + address)), > mst_file_data, > - SECT_OFF_DATA (objfile)); > + section_override); > + } > else > - reader.record_with_info (sym_name, minsym_value, > + { > + section_override =3D SECT_OFF_BSS (objfile); > + address =3D 0; > + if ((bfd_get_file_flags (objfile->obfd.get ()) & > (EXEC_P | DYNAMIC)) =3D=3D 0) > + { > + /* This is attempting to detect .o files. > + Their sections are relocated in symfile.c > default_symfile_offsets > + but section_offsets are set to 0 there and > the offset is put in the vma. */ > + address +=3D > objfile->sections_start[section_override].the_bfd_section->vma; > + } > + reader.record_with_info (sym_name, > (unrelocated_addr)(((bfd_vma)minsym_value + address)), > mst_file_bss, > - SECT_OFF_BSS (objfile)); > + section_override); > + } > + > theclass =3D LOC_STATIC; > break; > > @@ -3596,11 +3706,19 @@ parse_partial_symbols (minimal_symbol_reader > &reader, > cur_sdx++; > continue; > } > + address =3D sh.value; > + if ((bfd_get_file_flags (objfile->obfd.get ()) & > (EXEC_P | DYNAMIC)) =3D=3D 0) > + { > + /* This is attempting to detect .o files. > + Their sections are relocated in symfile.c > default_symfile_offsets > + but section_offsets are set to 0 there and > the offset is put in the vma. */ > + address +=3D > objfile->sections_start[section].the_bfd_section->vma; > + } > /* Use this gdb symbol. */ > pst->add_psymbol (sym_name, true, > VAR_DOMAIN, theclass, section, > psymbol_placement::STATIC, > - unrelocated_addr (sh.value), > + unrelocated_addr (address), > psymtab_language, > partial_symtabs, objfile); > skip: > @@ -3676,12 +3794,20 @@ parse_partial_symbols (minimal_symbol_reader > &reader, > theclass =3D LOC_STATIC; > break; > } > + bfd_vma address =3D svalue; > char *sym_name =3D debug_info->ssext + psh->iss; > + if ((bfd_get_file_flags (objfile->obfd.get ()) & > (EXEC_P | DYNAMIC)) =3D=3D 0) > + { > + /* This is attempting to detect .o files. > + Their sections are relocated in symfile.c > default_symfile_offsets > + but section_offsets are set to 0 there and > the offset is put in the vma. */ > + address +=3D > objfile->sections_start[section].the_bfd_section->vma; > + } > pst->add_psymbol (sym_name, true, > VAR_DOMAIN, theclass, > section, > psymbol_placement::GLOBAL, > - unrelocated_addr (svalue), > + unrelocated_addr (address), > psymtab_language, > partial_symtabs, objfile); > } > @@ -4163,7 +4289,7 @@ mdebug_expand_psymtab (legacy_psymtab *pst, struct > objfile *objfile) > } > > parse_lines (fh, pr_block.data (), lines, maxlines, > - lowest_pdr_addr); > + (CORE_ADDR) pst->unrelocated_text_low (), > lowest_pdr_addr); > if (lines->nitems < fh->cline) > lines =3D shrink_linetable (lines); > > @@ -4291,7 +4417,7 @@ cross_ref (int fd, union aux_ext *ax, struct type > **tpp, > rf =3D rn->rfd; > } > > - type_allocator alloc (mdebugread_objfile, get_current_subfile > ()->language); > + type_allocator alloc (mdebugread_objfile, psymtab_language); > > /* mips cc uses a rf of -1 for opaque struct definitions. > Set TYPE_STUB for these types so that check_typedef will > @@ -4412,7 +4538,8 @@ cross_ref (int fd, union aux_ext *ax, struct type > **tpp, > sh.index, > NULL, > fh->fBigendian, > - debug_info->ss + fh->issBase + sh.iss); > + debug_info->ss + fh->issBase + sh.iss, > + sh.st =3D=3D stTypedef); > add_pending (fh, esh, *tpp); > break; > > @@ -4438,7 +4565,8 @@ cross_ref (int fd, union aux_ext *ax, struct type > **tpp, > sh.index, > NULL, > fh->fBigendian, > - debug_info->ss + fh->issBase + sh.iss); > + debug_info->ss + fh->issBase + sh.iss, > + true); > } > else > { > @@ -4542,6 +4670,8 @@ add_line (struct linetable *lt, int lineno, > CORE_ADDR adr, int last) > return lineno; > > lt->item[lt->nitems].line =3D lineno; > + lt->item[lt->nitems].is_stmt =3D 1; > + lt->item[lt->nitems].prologue_end =3D 1; > lt->item[lt->nitems++].set_unrelocated_pc (unrelocated_addr (adr << 2)= ); > return lineno; > } > @@ -4634,9 +4764,10 @@ new_symtab (const char *name, int maxlines, struct > objfile *objfile) > > /* All symtabs must have at least two blocks. */ > bv =3D new_bvect (2); > - bv->set_block (GLOBAL_BLOCK, new_block (objfile, NON_FUNCTION_BLOCK, > lang)); > - bv->set_block (STATIC_BLOCK, new_block (objfile, NON_FUNCTION_BLOCK, > lang)); > + bv->set_block (GLOBAL_BLOCK, new_block (objfile, NON_FUNCTION_BLOCK, > lang, true)); > + bv->set_block (STATIC_BLOCK, new_block (objfile, NON_FUNCTION_BLOCK, > lang, false)); > bv->static_block ()->set_superblock (bv->global_block ()); > + bv->global_block ()->set_compunit_symtab(cust); > cust->set_blockvector (bv); > > cust->set_debugformat ("ECOFF"); > @@ -4723,9 +4854,11 @@ new_bvect (int nblocks) > > static struct block * > new_block (struct objfile *objfile, enum block_type type, > - enum language language) > + enum language language, bool is_global) > { > - struct block *retval =3D new (&objfile->objfile_obstack) block; > + struct block *retval =3D (is_global > + ? new (&objfile->objfile_obstack) global_block > + : new (&objfile->objfile_obstack) block); > > if (type =3D=3D FUNCTION_BLOCK) > retval->set_multidict (mdict_create_linear_expandable (language)); > @@ -4754,8 +4887,7 @@ new_type (char *name) > { > struct type *t; > > - t =3D type_allocator (mdebugread_objfile, > - get_current_subfile ()->language).new_type (); > + t =3D type_allocator (mdebugread_objfile, psymtab_language).new_type (= ); > t->set_name (name); > INIT_CPLUS_SPECIFIC (t); > return t; > diff --git a/gdb/testsuite/boards/qemu-user.exp > b/gdb/testsuite/boards/qemu-user.exp > new file mode 100644 > index 00000000000..8a48ab7f6d4 > --- /dev/null > +++ b/gdb/testsuite/boards/qemu-user.exp > @@ -0,0 +1,267 @@ > +# Copyright 2020-2023 Free Software Foundation, Inc. > + > +# 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 . > + > +# NOTICE: > +# QEMU user mode gdbstub has multithreading problems > +# https://gitlab.com/qemu-project/qemu/-/issues/1671 > +# run with --ignore gdb.threads/access-mem-running-thread-exit.exp > +# since this test in particular seems to hang. Could be related. > + > +# This technique is from native-extended-gdbserver.exp > +# We must load this explicitly here, and rename the procedures we want > +# to override. If we didn't do this, given that mi-support.exp is > +# loaded later in the test files, the procedures loaded then would > +# override our definitions. > +load_lib mi-support.exp > + > +set qemu "" > +set qemu_arch "" > +set qemu_user_spawn_id "" > +set qemu_user_last_load_file "" > +set port "2345" > + > +# add sections for other architectures > +# as needed > +case "$target_triplet" in { > + { "mips" } { > + set qemu "qemu-mips" > + set qemu_arch "mips" > + } > + default { > + puts "No target hardware for $target_triplet" > + } > +} > + > +# QEMU supports some of extended-remote, but not the run command > +# which causes problems for the test suite > +set_board_info gdb_protocol "remote" > +set_board_info use_gdb_stub 1 > +set_board_info gdb,do_reload_on_run 1 > +set_board_info exit_is_reliable 1 > +# static link so we do not need to configure an QEMU LD prefix and insta= ll > +# libraries for the target architecture > +set_board_info ldflags "-static" > + > +# technique from simavr.exp > +# > +# Load executable into GDB > +# > +proc gdb_load { arg } { > + global gdb_prompt > + global verbose > + global spawn_id > + global qemu > + global qemu_user_last_load_file > + global qemu_user_spawn_id > + global port > + > + # keep track of last loaded file > + # to simulate run restart like behavior > + if { $arg =3D=3D "" } { > + set arg $qemu_user_last_load_file > + if { $arg =3D=3D "" } { > + global last_loaded_file > + # this fallback is needed > + # for tests like gdb.base/break-unload-file.exp > + set arg $last_loaded_file > + } > + } else { > + set qemu_user_last_load_file $arg > + } > + > + if { $arg !=3D "" } { > + if {[gdb_file_cmd $arg]} then { return -1 } > + } > + > + # Close any previous qemu user instance. > + if { $qemu_user_spawn_id !=3D "" } { > + verbose -log "qemu user: closing previous spawn id > $qemu_user_spawn_id" > + if [catch { close -i $qemu_user_spawn_id } !=3D 0] { > + warning "qemu user: failed to close connection to > previous qemu user instance" > + } > + > + # some tests get QEMU > + # into a state where the process doesn't want to die > + # so -nowait to not hang the entire test run > + wait -nowait -i $qemu_user_spawn_id > + set qemu_user_spawn_id "" > + } > + > + # technique from gdbserver-support.exp > + # Loop till we find a free port. > + # This is to cope with qemu sometimes getting > + # into a bad state and not closing. > + # Do a pkill -f qemu-mips -9 after running tests > + # to remove stragglers > + while 1 { > + # Run QEMU user > + set cmd "spawn -noecho $qemu -g $port $arg" > + verbose -log "Spawning qemu user: $cmd" > + eval $cmd > + set qemu_user_spawn_id $spawn_id > + > + # without inferior_spawn_id > + # tests such as gdb.base/a2-run.exp > + # can't look at the right process output > + global inferior_spawn_id > + set inferior_spawn_id $spawn_id > + > + expect { > + -i $qemu_user_spawn_id > + -timeout 1 > + -re ".*qemu: could not open gdbserver on.*" { > + verbose -log "Port $port is already in > use." > + if [catch { close -i $qemu_user_spawn_id } > !=3D 0] { > + warning "qemu user: failed to > close connection to previous qemu user instance" > + } > + # Bump the port number to avoid the > conflict. > + wait -i $qemu_user_spawn_id > + incr port > + continue > + } > + } > + break > + } > + > + # arch needs set because some tests > + # take actions that need arch to be correct > + # immediately, before file command loads the binary > + # for example gdb.base/break-unload-file.exp > + global qemu_arch > + send_gdb "set arch $qemu_arch\n" > + > + # Connect to qemu user. > + send_gdb "target remote :$port\n" > + gdb_expect { > + # qemu user mode gdb stub does not support non stop mode > + # this is so tests that attempt it die quickly > + -re ".*Non-stop mode requested, but remote does not > support non-stop.*" { > + error "qemu user does not support non-stop" > + } > + # cannot have multiple targets connected > + # some tests end up causing this to be attempted in > gdb.multi > + -re ".*Already connected to a remote target. > Disconnect?.*" { > + send_gdb "y\n" > + gdb_expect { > + -re ".*$gdb_prompt $" { > + error "connected to new target > while connected to existing" > + } > + } > + } > + -re ".*$gdb_prompt $" { > + if $verbose>1 then { > + send_user "Connected to QEMU target\n" > + } > + } > + -re "Remote debugging using .*$gdb_prompt $" { > + verbose "Set target to remote for QEMU" > + } > + timeout { > + verbose -log "qemu-user: unable to connect to qemu > user, closing qemu user spawn id" > + close -i $qemu_user_spawn_id > + verbose -log "qemu-user: unable to connect to qemu > user, waiting for qemu user process exit" > + wait -i $qemu_user_spawn_id > + set qemu_user_spawn_id "" > + error "unable to connect to qemu user stub" > + } > + } > + > + return 0 > +} > + > +# technique from native-extended-gdbserver.exp > +# for overriding mi-support.exp procs > +if { [info procs original_mi_gdb_load] =3D=3D "" } { > + rename mi_gdb_load original_gdbserver_mi_gdb_load > +} > + > +# same ideas as gdb_load, but adapted for mi > +proc mi_gdb_load { arg } { > + global gdb_prompt > + global verbose > + global spawn_id > + global qemu > + global qemu_user_last_load_file > + global qemu_user_spawn_id > + global port > + > + if { $arg =3D=3D "" } { > + set arg $qemu_user_last_load_file > + if { $arg =3D=3D "" } { > + global last_loaded_file > + set arg $last_loaded_file > + } > + } else { > + set qemu_user_last_load_file $arg > + } > + > + if { $arg !=3D "" } { > + if {[mi_gdb_file_cmd $arg]} then { return -1 } > + } > + > + #Close any previous qemu user instance. > + if { $qemu_user_spawn_id !=3D "" } { > + verbose -log "qemu user: closing previous spawn id > $qemu_user_spawn_id" > + if [catch { close -i $qemu_user_spawn_id } !=3D 0] { > + warning "qemu user: failed to close previous qemu > user instance" > + } > + > + # some tests get QEMU/its gdb stub > + # into a state where the process doesn't want to die > + # so -nowait to not hang the entire test run > + wait -nowait -i $qemu_user_spawn_id > + set qemu_user_spawn_id "" > + } > + > + # technique from gdbserver-support.exp > + # Loop till we find a free port. > + while 1 { > + # Run QEMU user > + set cmd "spawn -noecho $qemu -g $port $arg" > + verbose -log "Spawning qemu user: $cmd" > + eval $cmd > + set qemu_user_spawn_id $spawn_id > + > + # without inferior_spawn_id > + # tests such as gdb.base/a2-run.exp > + # can't look at the right process output > + global inferior_spawn_id > + set inferior_spawn_id $spawn_id > + > + expect { > + -i $qemu_user_spawn_id > + -timeout 1 > + -re ".*qemu: could not open gdbserver on.*" { > + verbose -log "Port $port is already in > use." > + if [catch { close -i $qemu_user_spawn_id } > !=3D 0] { > + warning "qemu user: failed to > close connection to previous qemu user instance" > + } > + # Bump the port number to avoid the > conflict. > + wait -i $qemu_user_spawn_id > + incr port > + continue > + } > + } > + break > + } > + > + return 0 > +} > + > +# technique from stdio-gdb-server-base.exp > +proc mi_gdb_target_load { } { > + global port > + return [mi_gdb_target_cmd "remote" ":$port"] > +} > diff --git a/gdb/testsuite/gdb.mdebug/README > b/gdb/testsuite/gdb.mdebug/README > new file mode 100644 > index 00000000000..f749d3e1cbc > --- /dev/null > +++ b/gdb/testsuite/gdb.mdebug/README > @@ -0,0 +1,67 @@ > +These tests are adapted for dealing with the limitations of old compilers > and the mdebug format. > + > +Execute the mdebug tests with something like: > +runtest gdb.mdebug/info-types-c.exp CC_FOR_TARGET=3Didowrapper MDEBUG=3D1 > --target mips --target_board qemu-user > + > +The CC_FOR_TARGET is probably going to be a wrapper script > +for an old compiler running in an emulator. > +Example at the end of this readme. > +Put it somewhere in your PATH. > +Do not give the path to the script as CC_FOR_TARGET, that does not work. > + > +The qemu-user board will run mips programs in qemu user mode > +and connect gdb to QEMU's gdb stub. > + > +mdebug does not record line numbers for type definitions. > +This is why the info types tests are modified > + > +mdebug output can be odd in how line mappings deal with the start of > functions. > +This is why the break tests are modified. > + > +Most compilers outputting mdebug data are so old they cannot deal with > C99 features. > +This makes parsing standard library headers for modern implementations a > problem. > +Also, even past that, the headers may eventually lead to compiler > specific code > +in things like stddef.h that may not be appriopriate for your old > compiler. > +This is why break.c has some modified standard function signatures at the > beginning. > + > +A few of the break tests *sometimes* fail still. > +Several memory initialization bugs were fixed but whatever is causing th= at > +is very inconsistent. Or it could be some issue with the exp file. > + > +The best documentation on mdebug are these documents: > + > +"Tru64 UNIX Object File and Symbol Table Format Specification" > +Sections 5, 9, and 10 > +Note, the word "mdebug" is never used, but it is that format > +carried through from DEC to Compaq. > + > +"MIPS Mdebug Debugging Information" by David Anderson > + > +A wrapper script like this was used to create .o files with IDO running > in an emulator. > +The final link commands are run with regular linux gcc. > + > +#!/bin/sh > + > +echo "$@" >> theargs > + > +for arg do > + if [ "$arg" =3D "-static" ] > + then > + link=3D1 > + fi > +done > + > +if [ "$link" =3D 1 ] > +then > + mips-unknown-linux-gnu-gcc "$@" -fno-exceptions > +else > +for arg do > + shift > + [ "$arg" =3D "-fdiagnostics-color=3Dnever" ] && continue > + [ "$arg" =3D "-g" ] && continue > + set -- "$@" "$arg" > +done > + > +/home/someuser/qemu-irix/build/irix-linux-user/qemu-irix -L > /home/someuser/ido/ido7.1_compiler > /home/someuser/ido/ido7.1_compiler/usr/bin/cc -Xcpluscomm -nostdlib > -nostdinc -mips2 > +-g2 "$@" 2>/dev/null > +fi > diff --git a/gdb/testsuite/gdb.mdebug/break.c > b/gdb/testsuite/gdb.mdebug/break.c > new file mode 100644 > index 00000000000..d0b26998c77 > --- /dev/null > +++ b/gdb/testsuite/gdb.mdebug/break.c > @@ -0,0 +1,92 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 1992-2023 Free Software Foundation, Inc. > + > + 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 . > */ > + > +int printf (const char *__format, ...); > +int fprintf (void *__stream, const char *__format, ...); > +int atoi(const char *_Str); > +void *malloc(int size); > + > +extern void * stderr; > + > +extern int marker1 (void); > +extern int marker2 (int a); > +extern void marker3 (char *a, char *b); > +extern void marker4 (long d); > + > +/* We're used by a test that requires malloc, so make sure it is in > + the executable. */ > +void *need_malloc () > +{ > + return malloc (1); > +} > + > +/* > + * This simple classical example of recursion is useful for > + * testing stack backtraces and such. > + */ > + > +int factorial(int); > + > +int > +main (int argc, char **argv, char **envp) > +{ /* set breakpoint 6 here */ > + if (argc =3D=3D 12345) { /* an unlikely value < 2^16, in case uninite= d */ > + fprintf (stderr, "usage: factorial \n"); > + return 1; > + } > + printf ("%d\n", factorial (atoi ("6"))); /* set breakpoint 1 here */ > + /* set breakpoint 12 here */ > + marker1 (); /* set breakpoint 11 here */ > + marker2 (43); /* set breakpoint 20 here */ > + marker3 ("stack", "trace"); /* set breakpoint 21 here */ > + marker4 (177601976L); > + /* We're used by a test that requires malloc, so make sure it is > + in the executable. */ > + (void)malloc (1); > + > + argc =3D (argc =3D=3D 12345); /* This is silly, but we can step off = of it > */ /* set breakpoint 2 here */ > + return argc; /* set breakpoint 10 here */ > +} /* set breakpoint 10a here */ > + > +int factorial (int value) > +{ /* set breakpoint 7 here */ > + if (value > 1) { /* set breakpoint 7a here */ > + value *=3D factorial (value - 1); > + } > + return (value); /* set breakpoint 19 here */ > +} > + > +int multi_line_if_conditional (int a, int b, int c) > +{ /* set breakpoint 3 here */ > + if (a > + && b > + && c) > + return 0; > + else > + return 1; > +} > + > +int multi_line_while_conditional (int a, int b, int c) > +{ /* set breakpoint 4 here */ > + while (a > + && b > + && c) > + { > + a--, b--, c--; > + } > + return 0; > +} > diff --git a/gdb/testsuite/gdb.mdebug/break.exp > b/gdb/testsuite/gdb.mdebug/break.exp > new file mode 100644 > index 00000000000..cb74c1b0081 > --- /dev/null > +++ b/gdb/testsuite/gdb.mdebug/break.exp > @@ -0,0 +1,921 @@ > +# Copyright 1988-2023 Free Software Foundation, Inc. > + > +# 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 was written by Rob Savoye. (rob@cygnus.com) > + > +if { [build_executable "failed to prepare" "break" {break.c break1.c} > {debug nowarnings}] } { > + return -1 > +} > +set srcfile break.c > +set srcfile1 break1.c > + > +set bp_location1 [gdb_get_line_number "set breakpoint 1 here"] > +set bp_location2 [gdb_get_line_number "set breakpoint 2 here"] > +set bp_location3 [gdb_get_line_number "set breakpoint 3 here"] > +set bp_location4 [gdb_get_line_number "set breakpoint 4 here"] > +set bp_location6 [gdb_get_line_number "set breakpoint 6 here"] > +set bp_location7 [gdb_get_line_number "set breakpoint 7 here"] > +set bp_location8 [gdb_get_line_number "set breakpoint 8 here" $srcfile1] > +set bp_location11 [gdb_get_line_number "set breakpoint 11 here"] > + > +set main_line $bp_location6 > + > +# In C++ mode, we see a full prototype; in C mode, we only see the > +# function name, with no parameter info. > +proc func {name} { > + return "${name}(?:\(\[^\r\n\]*\))?" > +} > + > +# test simple breakpoint setting commands > + > +proc_with_prefix test_break {} { > + clean_restart break > + > + # Test deleting all breakpoints when there are none installed, > + # GDB should not prompt for confirmation. > + # Note that lib/gdb.exp provides a "delete_breakpoints" proc > + # for general use elsewhere. > + send_gdb "delete breakpoints\n" > + gdb_expect { > + -re "Delete all breakpoints.*$" { > + send_gdb "y\n" > + gdb_expect { > + -re "$::gdb_prompt $" { > + fail "delete all breakpoints when none (unexpected > prompt)" > + } > + timeout { fail "delete all breakpoints when none > (timeout after unexpected prompt)" } > + } > + } > + -re ".*$::gdb_prompt $" { pass "delete all breakpoints when > none" } > + timeout { fail "delete all breakpoints when none > (timeout)" } > + } > + > + # test break at function > + gdb_test "break -q main" \ > + "Breakpoint.*at.* file .*$::srcfile, line.*" \ > + "breakpoint function" > + > + # test break at quoted function > + gdb_test "break \"marker2\"" \ > + "Breakpoint.*at.* file .*$::srcfile1, line.*" \ > + "breakpoint quoted function" > + > + # test break at function in file > + gdb_test "break $::srcfile:factorial" \ > + "Breakpoint.*at.* file .*$::srcfile, line.*" \ > + "breakpoint function in file" > + > + # test break at line number > + # > + # Note that the default source file is the last one whose source text > + # was printed. For native debugging, before we've executed the > + # program, this is the file containing main, but for remote debuggin= g, > + # it's wherever the processor was stopped when we connected to the > + # board. So, to be sure, we do a list command. > + gdb_test "list -q main" \ > + ".*main \\(int argc, char \\*\\*argv, char \\*\\*envp\\).*" \ > + "use `list' to establish default source file" > + > + gdb_test "break $::bp_location1" \ > + "Breakpoint.*at.* file .*$::srcfile, line $::bp_location1\\." \ > + "breakpoint line number" > + > + # test duplicate breakpoint > + gdb_test "break $::bp_location1" \ > + "Note: breakpoint \[0-9\]+ also set at pc.*Breakpoint \[0-9\]+ > at.* file .*$::srcfile, line $::bp_location1\\." \ > + "breakpoint duplicate" > + > + # test break at line number in file > + gdb_test "break $::srcfile:$::bp_location2" \ > + "Breakpoint.*at.* file .*$::srcfile, line $::bp_location2\\." \ > + "breakpoint line number in file" > + > + # Test putting a break at the start of a multi-line if conditional. > + # Verify the breakpoint was put at the start of the conditional. > + gdb_test "break multi_line_if_conditional" \ > + "Breakpoint.*at.* file .*$::srcfile, line $::bp_location3\\." \ > + "breakpoint at start of multi line if conditional" > + > + gdb_test "break multi_line_while_conditional" \ > + "Breakpoint.*at.* file .*$::srcfile, line $::bp_location4\\." \ > + "breakpoint at start of multi line while conditional" > + > + gdb_test "info break" \ > + [multi_line "Num Type\[ \]+Disp Enb Address\[ \]+What.*" \ > + "$::decimal\[\t \]+breakpoint keep y.* in [func > main] at .*$::srcfile:$::main_line.*" \ > + "$::decimal\[\t \]+breakpoint keep y.* in [func > marker2] at .*$::srcfile1:$::bp_location8.*" \ > + "$::decimal\[\t \]+breakpoint keep y.* in [func > factorial] at .*$::srcfile:$::bp_location7.*" \ > + "$::decimal\[\t \]+breakpoint keep y.* in [func > main] at .*$::srcfile:$::bp_location1.*" \ > + "$::decimal\[\t \]+breakpoint keep y.* in [func > main] at .*$::srcfile:$::bp_location1.*" \ > + "$::decimal\[\t \]+breakpoint keep y.* in [func > main] at .*$::srcfile:$::bp_location2.*" \ > + "$::decimal\[\t \]+breakpoint keep y.* in [func > multi_line_if_conditional] at .*$::srcfile:$::bp_location3.*" \ > + "$::decimal\[\t \]+breakpoint keep y.* in [func > multi_line_while_conditional] at .*$::srcfile:$::bp_location4"] \ > + "breakpoint info" > + > + # > + # Test info breakpoint with arguments > + # > + > + set see1 0 > + set see2 0 > + set see3 0 > + set see4 0 > + set see5 0 > + set see6 0 > + > + gdb_test_multiple "info break 2 4 6" "info break 2 4 6" { > + -re "1\[\t \]+breakpoint *keep y\[^\r\n\]*:$::main_line\[^\r\n\]*" > { > + set see1 1 > + exp_continue > + } > + -re "2\[\t \]+breakpoint *keep y\[^\r\n\]* in [func marker2] at > \[^\r\n\]*" { > + set see2 1 > + exp_continue > + } > + -re "3\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location7\[^\r\n\]*" { > + set see3 1 > + exp_continue > + } > + -re "4\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location1\[^\r\n\]*" { > + set see4 1 > + exp_continue > + } > + -re "5\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location1\[^\r\n\]*" { > + set see5 1 > + exp_continue > + } > + -re "6\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location2\[^\r\n\]*" { > + set see6 1 > + exp_continue > + } > + -re ".*$::gdb_prompt $" { > + if {!$see1 && $see2 && !$see3 && $see4 && !$see5 && $see6} { > + pass "info break 2 4 6" > + } else { > + fail "info break 2 4 6" > + } > + } > + } > + > + set see1 0 > + set see2 0 > + set see3 0 > + set see4 0 > + set see5 0 > + set see6 0 > + > + gdb_test_multiple "info break 3-5" "info break 3-5" { > + -re "1\[\t \]+breakpoint *keep y.* in [func main] at > .*:$::main_line\[^\r\n\]*" { > + set see1 1 > + exp_continue > + } > + -re "2\[\t \]+breakpoint *keep y\[^\r\n\]* in [func marker2] at > \[^\r\n\]*" { > + set see2 1 > + exp_continue > + } > + -re "3\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location7\[^\r\n\]*" { > + set see3 1 > + exp_continue > + } > + -re "4\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location1\[^\r\n\]*" { > + set see4 1 > + exp_continue > + } > + -re "5\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location1\[^\r\n\]*" { > + set see5 1 > + exp_continue > + } > + -re "6\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location2\[^\r\n\]*" { > + set see6 1 > + exp_continue > + } > + -re ".*$::gdb_prompt $" { > + if {!$see1 && !$see2 && $see3 && $see4 && $see5 && !$see6} { > + pass "info break 3-5" > + } else { > + fail "info break 3-5" > + } > + } > + } > + > + # > + # Test disable/enable with arguments > + # > + > + # Test with value history > + > + with_test_prefix "with value history" { > + gdb_test "print 1" > + gdb_test "print 2" > + gdb_test "print 3" > + gdb_test "print 4" > + gdb_test "print 5" > + gdb_test "print 6" > + > + # $2 is 2 and $$ is 5 > + gdb_test_no_output "disable \$2 \$\$" "disable using history > values" > + > + set see1 0 > + set see2 0 > + set see3 0 > + set see4 0 > + set see5 0 > + set see6 0 > + > + gdb_test_multiple "info break" "check disable with history values" > { > + -re "1\[\t \]+breakpoint *keep y.* in [func main] at > .*:$::main_line\[^\r\n\]*" { > + set see1 1 > + exp_continue > + } > + -re "2\[\t \]+breakpoint *keep n\[^\r\n\]* in [func marker2] > at \[^\r\n\]*" { > + set see2 1 > + exp_continue > + } > + -re "3\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location7\[^\r\n\]*" { > + set see3 1 > + exp_continue > + } > + -re "4\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location1\[^\r\n\]*" { > + set see4 1 > + exp_continue > + } > + -re "5\[\t \]+breakpoint *keep > n\[^\r\n\]*$::bp_location1\[^\r\n\]*" { > + set see5 1 > + exp_continue > + } > + -re "6\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location2\[^\r\n\]*" { > + set see6 1 > + exp_continue > + } > + -re ".*$::gdb_prompt $" { > + if {$see1 && $see2 && $see3 && $see4 && $see5 && $see6} { > + pass "check disable with history values" > + } else { > + fail "check disable with history values" > + } > + } > + } > + } > + > + with_test_prefix "with convenience vars" { > + gdb_test "enable" > + gdb_test "set \$foo =3D 3" > + gdb_test "set \$bar =3D 6" > + gdb_test_no_output "disable \$foo \$bar" "disable with convenience > values" > + > + set see1 0 > + set see2 0 > + set see3 0 > + set see4 0 > + set see5 0 > + set see6 0 > + > + gdb_test_multiple "info break" "check disable with convenience > values" { > + -re "1\[\t \]+breakpoint *keep y.* in [func main] at > .*:$::main_line\[^\r\n\]*" { > + set see1 1 > + exp_continue > + } > + -re "2\[\t \]+breakpoint *keep y\[^\r\n\]* in [func marker2] > at \[^\r\n\]*" { > + set see2 1 > + exp_continue > + } > + -re "3\[\t \]+breakpoint *keep > n\[^\r\n\]*$::bp_location7\[^\r\n\]*" { > + set see3 1 > + exp_continue > + } > + -re "4\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location1\[^\r\n\]*" { > + set see4 1 > + exp_continue > + } > + -re "5\[\t \]+breakpoint *keep > y\[^\r\n\]*$::bp_location1\[^\r\n\]*" { > + set see5 1 > + exp_continue > + } > + -re "6\[\t \]+breakpoint *keep > n\[^\r\n\]*$::bp_location2\[^\r\n\]*" { > + set see6 1 > + exp_continue > + } > + -re ".*$::gdb_prompt $" { > + if {$see1 && $see2 && $see3 && $see4 && $see5 && $see6} { > + pass "check disable with convenience values" > + } else { > + fail "check disable with convenience values" > + } > + } > + } > + } > + > + # test with bad values > + > + with_test_prefix "bad values" { > + gdb_test "enable" > + gdb_test "disable 10" "No breakpoint number 10." \ > + "disable non-existent breakpoint 10" > + > + gdb_test_no_output "set \$baz =3D 1.234" > + gdb_test "disable \$baz" \ > + "Convenience variable must have integer value.*" \ > + "disable with non-integer convenience var" > + gdb_test "disable \$grbx" \ > + "Convenience variable must have integer value.*" \ > + "disable with non-existent convenience var" > + gdb_test "disable \$10" \ > + "History has not yet reached .10." \ > + "disable with non-existent history value" > + gdb_test "disable \$1foo" \ > + "Convenience variable must have integer value.*" \ > + "disable with badly formed history value" > + } > + > + # FIXME: The rest of this test doesn't work with anything that can't > + # handle arguments. > + # Huh? There doesn't *appear* to be anything that passes arguments > + # below. > + > + # > + # run until the breakpoint at main is hit. For non-stubs-using > targets. > + # > + gdb_run_cmd > + gdb_test "" \ > + "Breakpoint \[0-9\]+,.*main .*argc.*argv.* at > .*$::srcfile:$::bp_location6.*$::bp_location6\[\t \]+\{.*" \ > + "run until function breakpoint" > + > + # Test the 'list' commands sets current file for the 'break LINENO' > command. > + set bp_marker1 [gdb_get_line_number "set breakpoint 15 here" > $::srcfile1] > + gdb_test "list marker1" ".*" > + gdb_test "break $bp_marker1" "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: > file .*$::srcfile1, line ${bp_marker1}\\." \ > + "break lineno" > + gdb_test_no_output {delete $bpnum} > + > + # > + # run until the breakpoint at a line number > + # > + gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, main > \\(argc=3D.*, argv=3D.*, envp=3D.*\\) at > .*$::srcfile:$::bp_location1.*$::bp_location1\[\t \]+printf.*factorial.*"= \ > + "run until breakpoint set at a line number" > + > + # > + # Run until the breakpoint set in a function in a file > + # > + set bp_location7a [gdb_get_line_number "set breakpoint 7a here"] > + send_gdb "del 3\n" > + send_gdb "del 7\n" > + gdb_test "break $bp_location7a" \ > + "Breakpoint.*at.* file .*$::srcfile, line $bp_location7a\\." \ > + "setting breakpoint at 7a" > + > + for {set i 6} {$i >=3D 1} {incr i -1} { > + gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, > factorial \\(value=3D$i\\) at .*$::srcfile:$bp_location7a.*$bp_location7a= \[\t > \]+.*if .value > 1. \{.*" \ > + "run until file:function($i) breakpoint" > + } > + > + send_gdb "break $::bp_location3\n" > + > + send_gdb "break $::bp_location7\n" > + > + send_gdb "del 2\n" > + > + # > + # run until the file:function breakpoint at a line number in a file > + # > + gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, main > \\(argc=3D.*, argv=3D.*, envp=3D.*\\) at > .*$::srcfile:$::bp_location2.*$::bp_location2\[\t \]+argc =3D \\(argc =3D= =3D > 12345\\);.*" \ > + "run until file:linenum breakpoint" > + > + # Test break at offset +1 > + set bp_location10 [gdb_get_line_number "set breakpoint 10 here"] > + > + gdb_test "break +1" \ > + "Breakpoint.*at.* file .*$::srcfile, line $bp_location10\\." \ > + "breakpoint offset +1" > + > + # Check to see if breakpoint is hit when stepped onto > + > + gdb_test "step" \ > + ".*Breakpoint \[0-9\]+, main \\(argc=3D.*, argv=3D.*, envp=3D.*\\= ) at > .*$::srcfile:$bp_location10.*$bp_location10\[\t \]+return argc;.*breakpoi= nt > 10 here.*" \ > + "step onto breakpoint" > +} > + > +test_break > + > +proc_with_prefix test_tbreak {} { > + clean_restart break > + > + # test temporary breakpoint at function > + gdb_test "tbreak -q main" "Temporary breakpoint.*at.* file > .*$::srcfile, line.*" "temporary breakpoint function" > + > + # test break at function in file > + gdb_test "tbreak $::srcfile:factorial" "Temporary breakpoint.*at.* > file .*$::srcfile, line.*" \ > + "Temporary breakpoint function in file" > + > + # test break at line number > + gdb_test "tbreak $::bp_location1" \ > + "Temporary breakpoint.*at.* file .*$::srcfile, line > $::bp_location1.*" \ > + "temporary breakpoint line number #1" > + > + gdb_test "tbreak $::bp_location6" "Temporary breakpoint.*at.* file > .*$::srcfile, line $::bp_location6.*" "temporary breakpoint line number #= 2" > + > + # test break at line number in file > + gdb_test "tbreak $::srcfile:$::bp_location2" \ > + "Temporary breakpoint.*at.* file .*$::srcfile, line > $::bp_location2.*" \ > + "temporary breakpoint line number in file #1" > + > + gdb_test "tbreak $::srcfile:$::bp_location11" "Temporary > breakpoint.*at.* file .*$::srcfile, line $::bp_location11.*" "Temporary > breakpoint line number in file #2" > + > + # check to see what breakpoints are set (temporary this time) > + gdb_test "info break" \ > + [multi_line "Num Type.*Disp Enb Address.*What.*" \ > + "$::decimal\[\t \]+breakpoint del.*y.*in [func > main] at .*$::srcfile:$::main_line.*" \ > + "$::decimal\[\t \]+breakpoint del.*y.*in [func > factorial] at .*$::srcfile:$::bp_location7.*" \ > + "$::decimal\[\t \]+breakpoint del.*y.*in [func > main] at .*$::srcfile:$::bp_location1.*" \ > + "$::decimal\[\t \]+breakpoint del.*y.*in [func > main] at .*$::srcfile:$::bp_location6.*" \ > + "$::decimal\[\t \]+breakpoint del.*y.*in [func > main] at .*$::srcfile:$::bp_location2.*" \ > + "$::decimal\[\t \]+breakpoint del.*y.*in [func > main] at .*$::srcfile:$::bp_location11.*"] \ > + "Temporary breakpoint info" > +} > + > +test_tbreak > + > +# Verify that GDB responds gracefully when asked to set a breakpoint > +# on a nonexistent source line. > + > +proc_with_prefix test_break_nonexistent_line {} { > + clean_restart break > + > + if {![runto_main]} { > + return > + } > + > + gdb_test_no_output "set breakpoint pending off" > + gdb_test "break 999" \ > + "No line 999 in the current file." \ > + "break on non-existent source line" > +} > + > +test_break_nonexistent_line > + > +proc_with_prefix test_break_default {} { > + clean_restart break > + > + if {![runto_main]} { > + return > + } > + > + # Run to the desired default location. If not positioned here, the > + # tests below don't work. > + # > + gdb_test "until $::bp_location1" "main .* at .*:$::bp_location1.*" \ > + "until bp_location1" > + > + # Verify that GDB allows one to just say "break", which is treated > + # as the "default" breakpoint. Note that GDB gets cute when printing > + # the informational message about other breakpoints at the same > + # location. We'll hit that bird with this stone too. > + # > + gdb_test "break" "Breakpoint \[0-9\]*.*" \ > + "break on default location, 1st time" > + > + gdb_test "break" \ > + "Note: breakpoint \[0-9\]* also set at .*Breakpoint \[0-9\]*.*" \ > + "break on default location, 2nd time" > + > + gdb_test "break" \ > + "Note: breakpoints \[0-9\]* and \[0-9\]* also set at .*Breakpoint > \[0-9\]*.*" \ > + "break on default location, 3rd time" > + > + gdb_test "break" \ > + "Note: breakpoints \[0-9\]*, \[0-9\]* and \[0-9\]* also set at > .*Breakpoint \[0-9\]*.*" \ > + "break on default location, 4th time" > + > + # Check setting a breakpoint at the default location with a condition > attached. > + gdb_test "break if (1)" \ > + "Note: breakpoints \[0-9\]*, \[0-9\]*, \[0-9\]* and \[0-9\]* also > set at .*Breakpoint \[0-9\]*.*" \ > + "break on the default location, 5th time, but with a condition" > +} > + > +test_break_default > + > +# Verify that a "silent" breakpoint can be set, and that GDB is indeed > +# "silent" about its triggering. > + > +proc_with_prefix test_break_silent_and_more {} { > + clean_restart break > + > + if {![runto_main]} { > + return > + } > + > + gdb_test_multiple "break $::bp_location1" \ > + "set to-be-silent break bp_location1" { > + -re "Breakpoint (\[0-9\]*) at .*, line > $::bp_location1.*$::gdb_prompt $" { > + set bpno $expect_out(1,string) > + pass "set to-be-silent break bp_location1" > + } > + } > + > + gdb_test "commands $bpno\nsilent\nend" ">end" "set silent break > bp_location1" > + > + gdb_test "info break $bpno" \ > + "\[0-9\]*\[ \t\]*breakpoint.*:$::bp_location1\r\n\[ \t\]*silent.*" > \ > + "info silent break bp_location1" > + > + gdb_test "continue" "Continuing." \ > + "hit silent break bp_location1" > + > + gdb_test "bt" "#0 main .* at .*:$::bp_location1.*" \ > + "stopped for silent break bp_location1" > + > + # Verify the $_hit_bpnum convenience variable is set to the silent > hit bpno. > + gdb_test "printf \"%d\\n\", \$_hit_bpnum" "$bpno" \ > + "Silent breakpoint hit \$_hit_bpnum is silent $bpno" > + > + # Verify that GDB can at least parse a breakpoint with the > + # "thread" keyword. (We won't attempt to test here that a > + # thread-specific breakpoint really triggers appropriately. > + # The gdb.threads subdirectory contains tests for that.) > + # > + set bp_location12 [gdb_get_line_number "set breakpoint 12 here"] > + gdb_test "break $bp_location12 thread 999" "Unknown thread 999.*" \ > + "thread-specific breakpoint on non-existent thread disallowed" > + > + gdb_test "break $bp_location12 thread foo" \ > + "Invalid thread ID: foo" \ > + "thread-specific breakpoint on bogus thread ID disallowed" > + > + # Verify that GDB responds gracefully to a breakpoint command with > + # trailing garbage. > + # > + gdb_test "break $bp_location12 foo" \ > + "malformed linespec error: unexpected string, \"foo\".*" \ > + "breakpoint with trailing garbage disallowed" > + > + # Verify that GDB responds gracefully to a "clear" command that has > + # no matching breakpoint. (First, get us off the current source lin= e, > + # which we know has a breakpoint.) > + # > + gdb_test "next" "marker1.*" "step over breakpoint" > + > + gdb_test "clear 81" "No breakpoint at 81.*" \ > + "clear line has no breakpoint disallowed" > + > + gdb_test "clear" "No breakpoint at this line.*" \ > + "clear current line has no breakpoint disallowed" > + > + # Verify that we can set and clear multiple breakpoints. > + # > + # We don't test that it deletes the correct breakpoints. We do at > + # least test that it deletes more than one breakpoint. > + # > + gdb_test "break marker3" "Breakpoint.*at.*" "break marker3 #1" > + gdb_test "break marker3" "Breakpoint.*at.*" "break marker3 #2" > + gdb_test "clear marker3" {Deleted breakpoints [0-9]+ [0-9]+.*} > +} > + > +test_break_silent_and_more > + > +# Verify that a breakpoint can be set via a convenience variable. > + > +proc_with_prefix test_break_line_convenience_var {} { > + clean_restart break > + > + if { ![runto_main] } { > + return > + } > + > + gdb_test_no_output "set \$foo=3D$::bp_location11" \ > + "set convenience variable \$foo to bp_location11" > + > + gdb_test "break \$foo" \ > + "Breakpoint (\[0-9\]*) at .*, line $::bp_location11.*" > + > + # Verify that GDB responds gracefully to an attempt to set a > + # breakpoint via a convenience variable whose type is not integer. > + > + gdb_test_no_output "set \$foo=3D81.5" \ > + "set convenience variable \$foo to 81.5" > + > + gdb_test "break \$foo" \ > + "Convenience variables used in line specs must have integer > values.*" \ > + "non-integer convenience variable disallowed" > +} > + > +test_break_line_convenience_var > + > +# Verify that we can set and trigger a breakpoint in a user-called > function. > + > +proc_with_prefix test_break_user_call {} { > + clean_restart break > + > + if { ![runto_main] } { > + return > + } > + > + gdb_test "break marker2" \ > + "Breakpoint (\[0-9\]*) at .*, line $::bp_location8.*" \ > + "set breakpoint on to-be-called function" > + > + gdb_test "print marker2(99)" \ > + "The program being debugged stopped while in a function called > from GDB.\r\nEvaluation of the expression containing the function\r\n.[fu= nc > marker2]. will be abandoned.\r\nWhen the function is done executing, GDB > will silently stop.*" \ > + "hit breakpoint on called function" > + > + # As long as we're stopped (breakpointed) in a called function, > + # verify that we can successfully backtrace & such from here. > + gdb_test "bt" \ > + "#0\[ \t\]*($::hex in )?marker2.*:$::bp_location8\r\n#1\[ > \t\]*.*" \ > + "backtrace while in called function" > + > + # Return from the called function. For remote targets, it's > important to do > + # this before runto_main, which otherwise may silently stop on the > dummy > + # breakpoint inserted by GDB at the program's entry point. > + # > + gdb_test_multiple "finish" "finish from called function" { > + -re "Run till exit from .*marker2.* at > .*$::bp_location8\r\n.*function called from gdb.*$::gdb_prompt $" { > + pass "finish from called function" > + } > + -re "Run till exit from .*marker2.* at > .*$::bp_location8\r\n.*Value returned.*$::gdb_prompt $" { > + pass "finish from called function" > + } > + } > +} > + > +test_break_user_call > + > +# Verify that GDB responds gracefully to a "finish" command with > +# arguments. > + > +proc_with_prefix test_finish_arguments {} { > + clean_restart break > + > + if {![runto_main]} { > + return > + } > + > + send_gdb "finish 123\n" > + gdb_expect { > + -re "The \"finish\" command does not take any > arguments.\r\n$::gdb_prompt $"\ > + {pass "finish with arguments disallowed"} > + -re "$::gdb_prompt $"\ > + {fail "finish with arguments disallowed"} > + timeout {fail "(timeout) finish with arguments disallowed"} > + } > + > + # Verify that GDB responds gracefully to a request to "finish" from > + # the outermost frame. On a stub that never exits, this will just > + # run to the stubs routine, so we don't get this error... Thus the > + # second condition. > + # > + > + gdb_test_multiple "finish" "finish from outermost frame disallowed" { > + -re "\"finish\" not meaningful in the outermost > frame.\r\n$::gdb_prompt $" { > + pass "finish from outermost frame disallowed" > + } > + -re "Run till exit from.*\r\n$::gdb_prompt $" { > + pass "finish from outermost frame disallowed" > + } > + } > +} > + > +test_finish_arguments > + > +#******** > + > + > +# > +# Test "next" over recursive function call. > +# > + > +proc_with_prefix test_next_with_recursion {} { > + global gdb_prompt > + global decimal > + global binfile > + > + gdb_test "kill" "" "kill program" "Kill the program being debugged.*y > or n. $" "y" > + delete_breakpoints > + > + set bp_location7a [gdb_get_line_number "set breakpoint 7a here"] > + gdb_test "break $bp_location7a" \ > + "Breakpoint.*at.* file .*$::srcfile, line $bp_location7a\\." \ > + "setting breakpoint at 7a" > + > + # Run until we call factorial with 6 > + > + gdb_run_cmd > + gdb_test "" "Break.* factorial .value=3D6. .*" "run to factorial(6)" > + > + # Continue until we call factorial recursively with 5. > + > + gdb_test "continue" \ > + "Continuing.*Break.* factorial .value=3D5. .*" \ > + "continue to factorial(5)" > + > + # Do a backtrace just to confirm how many levels deep we are. > + > + gdb_test "backtrace" \ > + "#0\[ \t\]+ factorial .value=3D5..*" \ > + "backtrace from factorial(5)" > + > + # Now a "next" should position us at the recursive call, which > + # we will be performing with 4. > + > + gdb_test "next" \ > + ".* factorial .value - 1.;.*" \ > + "next to recursive call" > + > + # Disable the breakpoint at the entry to factorial by deleting them > all. > + # The "next" should run until we return to the next line from this > + # recursive call to factorial with 4. > + # Buggy versions of gdb will stop instead at the innermost frame on > + # the line where we are trying to "next" to. > + > + delete_breakpoints > + > + if [istarget "mips*tx39-*"] { > + set timeout 60 > + } > + # We used to set timeout here for all other targets as well. This > + # is almost certainly wrong. The proper timeout depends on the > + # target system in use, and how we communicate with it, so there > + # is no single value appropriate for all targets. The timeout > + # should be established by the Dejagnu config file(s) for the > + # board, and respected by the test suite. > + # > + # For example, if I'm running GDB over an SSH tunnel talking to a > + # portmaster in California talking to an ancient 68k board running > + # a crummy ROM monitor (a situation I can only wish were > + # hypothetical), then I need a large timeout. But that's not the > + # kind of knowledge that belongs in this file. > + > + gdb_test next "\[0-9\]*\[\t \]+return \\(value\\);.*" \ > + "next over recursive call" > + > + # OK, we should be back in the same stack frame we started from. > + # Do a backtrace just to confirm. > + > + gdb_test "backtrace" \ > + "#0\[ \t\]+ factorial .value=3D120.*\r\n#1\[ \t\]+ \[0-9a-fx\= ]+ > in factorial .value=3D6..*" \ > + "backtrace from factorial(5.1)" > + > + if { ![target_info exists gdb,noresults] } { > + gdb_continue_to_end "recursive next test" > + } > +} > + > +test_next_with_recursion > + > + > +#******** > + > +# build a new file with optimization enabled so that we can try > breakpoints > +# on targets with optimized prologues > + > +if { [build_executable "failed to prepare" "breako2" {break.c break1.c} > {debug nowarnings optimize=3D-O2}] } { > + return -1 > +} > + > +proc_with_prefix test_break_optimized_prologue {} { > + clean_restart breako2 > + > + # test break at function > + gdb_test "break -q main" \ > + "Breakpoint.*at.* file .*, line.*" \ > + "breakpoint function, optimized file" > + > + # test break at function > + gdb_test "break marker4" \ > + "Breakpoint.*at.* file .*$::srcfile1, line.*" \ > + "breakpoint small function, optimized file" > + > + # run until the breakpoint at main is hit. For non-stubs-using > targets. > + gdb_run_cmd > + > + set test "run until function breakpoint, optimized file" > + gdb_test_multiple "" $test { > + -re "Breakpoint \[0-9\]+,.*main .*argc.*argv.* at > .*$::srcfile:$::bp_location6.*$::bp_location6\[\t \]+\{ if .argc.* > \{.*$::gdb_prompt $" { > + pass $test > + } > + -re "Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$::gdb_prompt > $" { > + pass "$test (code motion)" > + } > + } > + > + # run until the breakpoint at a small function > + # > + # Add a second pass pattern. The behavior differs here between stabs > + # and dwarf for one-line functions. Stabs preserves two line symbols > + # (one before the prologue and one after) with the same line number, > + # but dwarf regards these as duplicates and discards one of them. > + # Therefore the address after the prologue (where the breakpoint is) > + # has no exactly matching line symbol, and GDB reports the breakpoint > + # as if it were in the middle of a line rather than at the beginning. > + > + set bp_location14 [gdb_get_line_number "set breakpoint 14 here" > $::srcfile1] > + > + gdb_test_multiple "continue" \ > + "run until breakpoint set at small function, optimized file" { > + -re "Breakpoint $::decimal, marker4 \\(d=3D(d@entry=3D)?17760= 1976\\) > at .*$::srcfile1:$bp_location14\[\r\n\]+$bp_location14\[\t \]+void > marker4.*" { > + pass "run until breakpoint set at small function, > optimized file (line bp_location14)" > + } > + -re "Breakpoint $::decimal, factorial \\(.*\\) > .*\{\r\n$::gdb_prompt" { > + # GCC 4.3 emits bad line number information - see > gcc/36748. > + if { [test_compiler_info "gcc-4-3-*"] } { > + setup_xfail *-*-* > + } > + fail "run until breakpoint set at small function, > optimized file" > + } > + } > +} > + > +test_break_optimized_prologue > + > +# test that 'rbreak' on a symbol that may be from a shared library doesn= 't > +# cause a "Junk at end of arguments." error. > +# > +# On x86 GNU/Linux, this test will choke on e.g. __libc_start_main@plt. > +# > +# Note that this test won't necessarily choke on all targets even if > +# all the rbreak issue is present. rbreak needs to match and set a > +# breakpoint on a symbol causes 'break' to choke. > + > +proc_with_prefix test_rbreak_shlib {} { > + clean_restart breako2 > + > + gdb_test_no_output "set breakpoint pending on" "rbreak junk pending > setup" > + > + # We expect at least one breakpoint to be set when we "rbreak main". > + gdb_test "rbreak main" \ > + ".*Breakpoint.*at.* file .*$::srcfile, line.*" > + > + # Run to a breakpoint. Fail if we see "Junk at end of arguments". > + gdb_run_cmd > + > + gdb_test_multiple "" "rbreak junk" { > + -re -wrap "Junk at end of arguments.*" { > + fail $gdb_test_name > + } > + -re -wrap ".*Breakpoint \[0-9\]+,.*" { > + pass $gdb_test_name > + } > + } > +} > + > +test_rbreak_shlib > + > +# Test break via convenience variable with file name > + > +proc_with_prefix test_break_file_line_convenience_var {} { > + clean_restart breako2 > + > + set line [gdb_get_line_number "set breakpoint 1 here"] > + gdb_test_no_output "set \$l =3D $line" > + > + set line_actual "-1" > + set test "break $::srcfile:\$l" > + gdb_test_multiple "$test" $test { > + -re "Breakpoint $::decimal at $::hex: file .*break\\.c, line > ($::decimal)\\.\r\n$::gdb_prompt $" { > + # Save the actual line number on which the breakpoint was > + # actually set. On some systems (Eg: Ubuntu 16.04 with GCC > + # version 5.4.0), that line gets completely inlined, including > + # the call to printf, and so we end up inserting the breakpoi= nt > + # on one of the following lines instead. > + set line_actual $expect_out(1,string) > + pass $test > + } > + } > + > + gdb_test_no_output "set \$foo=3D81.5" \ > + "set convenience variable \$foo to 81.5" > + gdb_test "break $::srcfile:\$foo" \ > + "Convenience variables used in line specs must have integer > values.*" \ > + "non-integer convenience variable disallowed" > +} > + > +test_break_file_line_convenience_var > + > +# Test that commands can be cleared without error. > + > +proc_with_prefix test_break_commands_clear {} { > + clean_restart breako2 > + > + set line [gdb_get_line_number "set breakpoint 1 here"] > + gdb_breakpoint $line > + > + gdb_test "commands\nprint 232323\nend" ">end" "set some breakpoint > commands" > + gdb_test "commands\nend" ">end" "clear breakpoint commands" > + > + # We verify that the commands were cleared by ensuring that the last > + # breakpoint's location ends the output -- if there were commands, > + # they would have been printed after the location. > + gdb_test "info break" "$::srcfile:$::decimal" "verify that they were > cleared" > +} > + > +test_break_commands_clear > diff --git a/gdb/testsuite/gdb.mdebug/break1.c > b/gdb/testsuite/gdb.mdebug/break1.c > new file mode 100644 > index 00000000000..5382ec06fa9 > --- /dev/null > +++ b/gdb/testsuite/gdb.mdebug/break1.c > @@ -0,0 +1,59 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 1992-2023 Free Software Foundation, Inc. > + > + 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 . > */ > + > +/* The code for this file was extracted from the gdb testsuite > + testcase "break.c". */ > + > +/* A structure we use for field name completion tests. */ > +struct some_struct > +{ > + int a_field; > + int b_field; > + union { int z_field; }; > +}; > + > +struct some_struct values[50]; > + > +/* Some definitions for tag completion. */ > +enum some_enum { VALUE }; > + > +enum some_enum some_enum_global; > + > +union some_union > +{ > + int f1; > + double f2; > +}; > + > +union some_union some_union_global; > + > +/* A variable with a name "similar" to the above struct, to test that > + tag completion works ok. */ > +int some_variable; > + > +/* The following functions do nothing useful. They are included > + simply as places to try setting breakpoints at. They are > + explicitly "one-line functions" to verify that this case works > + (some versions of gcc have or have had problems with this). > + > + These functions are in a separate source file to prevent an > + optimizing compiler from inlining them and optimizing them away. */ > + > +int marker1 (void) { return (0); } /* set breakpoint 15 here */ > +int marker2 (int a) { return (1); } /* set breakpoint 8 here */ > +void marker3 (char *a, char *b) {} /* set breakpoint 17 here */ > +void marker4 (long d) { values[0].a_field =3D d; } /* set breakpoi= nt > 14 here */ > diff --git a/gdb/testsuite/gdb.mdebug/info-types-c.exp > b/gdb/testsuite/gdb.mdebug/info-types-c.exp > new file mode 100644 > index 00000000000..d8c3abeade0 > --- /dev/null > +++ b/gdb/testsuite/gdb.mdebug/info-types-c.exp > @@ -0,0 +1,67 @@ > +# Copyright 2019-2023 Free Software Foundation, Inc. > +# > +# 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 . > + > +require {info exists MDEBUG} > + > +global testfile > +global srcfile > +global binfile > +global subdir > +global srcdir > +global compile_flags > + > +standard_testfile info-types.c > + > +if {[prepare_for_testing "failed to prepare" \ > + "${testfile}" $srcfile "debug c"]} { > +return -1 > +} > + > +gdb_test_no_output "set auto-solib-add off" > + > +if ![runto_main] then { > +return 0 > +} > + > +set file_re "File .*[string_to_regexp $srcfile]:"\ > + > +set output_lines \ > + [list \ > + "^All defined types:" \ > + ".*" \ > + $file_re \ > + "\[\t \]+typedef enum {\\.\\.\\.} anon_enum_t;" \ > + "\[\t \]+typedef struct {\\.\\.\\.} anon_struct_t;" \ > + "\[\t \]+typedef union {\\.\\.\\.} anon_union_t;" \ > + "\[\t \]+typedef struct baz_t baz;" \ > + "\[\t \]+typedef struct baz_t \\* baz_ptr;" \ > + "\[\t \]+typedef struct baz_t baz_t;" \ > + "\[\t \]+enum enum_t;" \ > + "\[\t \]+typedef enum enum_t my_enum_t;" \ > + "\[\t \]+typedef float my_float_t;" \ > + "\[\t \]+typedef int my_int_t;" \ > + "\[\t \]+typedef enum {\\.\\.\\.} nested_anon_enum_t;" \ > + "\[\t \]+typedef struct {\\.\\.\\.} nested_anon_struct_t;" \ > + "\[\t \]+typedef union {\\.\\.\\.} nested_anon_union_t;" \ > + "\[\t \]+typedef struct baz_t nested_baz;" \ > + "\[\t \]+typedef struct baz_t nested_baz_t;" \ > + "\[\t \]+typedef enum enum_t nested_enum_t;" \ > + "\[\t \]+typedef float nested_float_t;" \ > + "\[\t \]+typedef int nested_int_t;" \ > + "\[\t \]+typedef union union_t nested_union_t;" \ > + "\[\t \]+union union_t;" \ > + "($|\r\n.*)"] > + > +gdb_test_lines "info types" "" [multi_line {*}$output_lines] > diff --git a/gdb/testsuite/gdb.mdebug/info-types.c > b/gdb/testsuite/gdb.mdebug/info-types.c > new file mode 100644 > index 00000000000..15a74b3016a > --- /dev/null > +++ b/gdb/testsuite/gdb.mdebug/info-types.c > @@ -0,0 +1,116 @@ > +/* Copyright 2019-2023 Free Software Foundation, Inc. > + > + 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 . > */ > + > +typedef int my_int_t; > +typedef float my_float_t; > +typedef my_int_t nested_int_t; > +typedef my_float_t nested_float_t; > + > +struct baz_t > +{ > + float f; > + double d; > +}; > + > +typedef struct baz_t baz_t; > +typedef struct baz_t baz; > +typedef baz_t nested_baz_t; > +typedef baz nested_baz; > +typedef struct baz_t *baz_ptr; > + > +enum enum_t > +{ > + AA, BB, CC > +}; > + > +typedef enum enum_t my_enum_t; > +typedef my_enum_t nested_enum_t; > + > +typedef struct > +{ > + double d; > + float f; > +} anon_struct_t; > + > +typedef anon_struct_t nested_anon_struct_t; > + > +typedef enum > +{ > + DD, EE, FF > +} anon_enum_t; > + > +typedef anon_enum_t nested_anon_enum_t; > + > +union union_t > +{ > + int i; > + float f; > +}; > + > +typedef union union_t nested_union_t; > + > +typedef union > +{ > + int i; > + double d; > +} anon_union_t; > + > +typedef anon_union_t nested_anon_union_t; > + > +volatile int var_a; > +volatile float var_b; > +volatile my_int_t var_c; > +volatile my_float_t var_d; > +volatile nested_int_t var_e; > +volatile nested_float_t var_f; > +volatile struct baz_t var_g; > +volatile baz_t var_h; > +volatile baz var_i; > +volatile nested_baz_t var_j; > +volatile nested_baz var_k; > +volatile baz_ptr var_l; > +volatile enum enum_t var_m; > +volatile my_enum_t var_n; > +volatile nested_enum_t var_o; > +volatile anon_struct_t var_p; > +volatile nested_anon_struct_t var_q; > +volatile anon_enum_t var_r; > +volatile nested_anon_enum_t var_s; > +volatile union union_t var_t; > +volatile nested_union_t var_u; > +volatile anon_union_t var_v; > +volatile nested_anon_union_t var_w; > + > +#ifdef __cplusplus > + > +class CL > +{ > + int a; > +}; > + > +typedef CL my_cl; > +typedef CL *my_ptr; > + > +volatile CL var_cpp_a; > +volatile my_cl var_cpp_b; > +volatile my_ptr var_cpp_c; > + > +#endif /* __cplusplus */ > + > +int > +main () > +{ > + return 0; > +} > -- > 2.41.0 > > --0000000000004f4eaf0613814503--