From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21981 invoked by alias); 3 Jan 2003 19:07:41 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 21972 invoked from network); 3 Jan 2003 19:07:37 -0000 Received: from unknown (HELO takamaka.act-europe.fr) (80.13.79.136) by 209.249.29.67 with SMTP; 3 Jan 2003 19:07:37 -0000 Received: by takamaka.act-europe.fr (Postfix, from userid 507) id 90524D34AE; Fri, 3 Jan 2003 23:07:22 +0400 (RET) Date: Fri, 03 Jan 2003 19:07:00 -0000 From: Joel Brobecker To: gdb-patches@sources.redhat.com Subject: [RFA] Fix a "pc ... in psymtab but not in symtab" internal error warning Message-ID: <20030103190722.GL693@gnat.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="qjNfmADvan18RZcF" Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2003-01/txt/msg00074.txt.bz2 --qjNfmADvan18RZcF Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 3614 Hello, After fixing the problem in mdebugread.c (see one of my recent patches), GDB was no longer crashing, but some internal errors later appeared. Something like this: warning: (Internal error: pc 0x3ff800203a8 in read in psymtab, but not in symtab.) This would happen when trying to do a backtrace, for intance. These warnings are really annoying, as they have a tendency to flood the regular output... I found that the address was a valid PC address for a function inside one of the system libraries (eg libc or libpthread, for instance). What happened is that GDB was doing a symtab lookup for this address and did not find any. It then did a psymtab lookup, and found one. But then GDB was surprised to find out that the psymtab was already read in, and hence generated the warning. See find_pc_sect_symtab in symtab.c: | ALL_SYMTABS (objfile, s) | { | if (BLOCK_START (b) <= pc && BLOCK_END (b) > pc && [...]) | { | [...] | best_s = s; | } | } | | if (best_s != NULL) | return best_s; | | ps = find_pc_sect_psymtab (pc, section); | if (ps) | { | if (ps->readin) | warning ("Internal error: [...]"); | s = PSYMTAB_TO_SYMTAB (ps); | } | | return s; What really striked me when I started debugging this is that the psymtab found by find_pc_sect_psymtab was completely incorrect. At second thought, it should not have found any psymtab, since the symbol in question did not come with any debugging info besides the minimal symbol table. So I looked at the textlow and texthigh values for the psymtab, and was started by the texthigh value: 0xfffffffffffffffe, or written differently: -2. A "maintenance print symbols" and "maintenance print psymbols" confirmed that many symtabs had a suspisciouly high texthigh value. These dumps also revealed that these entries contained procedures with empty names and and address of 0xfffffffffffffffe. Debugging a bit furter, I indeed found stProc symbol records whose value are -2. I then looked up the Compaq documentation for the ECOFF format, and it says p171 that (stProc, scInfo) entries represent "a procedure without code, or a function prototype, or a function pointer". In that case, the value field is respectively either -1, -2, or a non-negative value. I read a bit more about stProc and stStaticProc symbol records. According to this documentation, only a very small subset of the (storage type, storage class) couple is legal: - stProc can only be associated with scNil, scText, scUndefined, and scInfo. - stStaticProc can only be associated with scText, scInit, and scFini. It also says that only (stProc, scText) entries are "real" procedures (all combinations of (stStaticProc, sc*) are "real" procedures). I therefore made some modifications in mdebugread.c to ignore all stProc entries when the storage class was not scText. This fixed the warnings, and did not introduce any regressions. But there is one flaw in my testing that I have to admit: we don't have a C++ compiler on our Tru64 machine... I still suggest this fix for inclusion in our sources, although I would understand that it be rejected for lack of testing. I checked the output of the "maint print symbols" and "maint print psymbols" commands, and did not find any 0xff[...]fe addresses anymore. 2003-01-03 J. Brobecker * mdebugread.c (parse_symbol): Skip stProc entries which storage class is not scText. These do not define "real" procedures. (parse_partial_symbols): Likewise. Ahem, ok to commit? -- Joel --qjNfmADvan18RZcF Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mdebugread.c.diff" Content-length: 3828 Index: mdebugread.c =================================================================== RCS file: /cvs/src/src/gdb/mdebugread.c,v retrieving revision 1.35 diff -c -3 -p -r1.35 mdebugread.c *** mdebugread.c 3 Jan 2003 15:34:59 -0000 1.35 --- mdebugread.c 3 Jan 2003 19:05:32 -0000 *************** parse_symbol (SYMR *sh, union aux_ext *a *** 751,756 **** --- 751,783 ---- case stProc: /* Procedure, usually goes into global block */ case stStaticProc: /* Static procedure, goes into current block */ + /* Make sure this is a "real" procedure. Otherwise, skip it. */ + if (sh->st == stProc && sh->sc != scText) + { + char *ext_tsym = ext_sh; + int keep_counting = 1; + SYMR tsym; + + while (keep_counting) + { + ext_tsym += external_sym_size; + (*swap_sym_in) (cur_bfd, ext_tsym, &tsym); + count++; + switch (tsym.st) + { + case stParam: + break; + case stEnd: + keep_counting = 0; + break; + default: + complaint (&symfile_complaints, + "unknown symbol type 0x%x", sh->st); + break; + } + } + break; + } s = new_symbol (name); SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; SYMBOL_CLASS (s) = LOC_BLOCK; *************** parse_partial_symbols (struct objfile *o *** 3323,3328 **** --- 3350,3383 ---- /* FALLTHROUGH */ case stProc: + /* Ignore all parameter symbol records. */ + if (sh.index >= hdr->iauxMax) + { + /* Should not happen, but does when cross-compiling + with the MIPS compiler. FIXME -- pull later. */ + index_complaint (name); + new_sdx = cur_sdx + 1; /* Don't skip at all */ + } + else + new_sdx = AUX_GET_ISYM (fh->fBigendian, + (debug_info->external_aux + + fh->iauxBase + + sh.index)); + + if (new_sdx <= cur_sdx) + { + /* This should not happen either... FIXME. */ + complaint (&symfile_complaints, + "bad proc end in aux found from symbol %s", + name); + new_sdx = cur_sdx + 1; /* Don't skip backward */ + } + + /* Make sure that this stProc entry represents a "real" + procedure. If not, ignore it. */ + if (sh.st == stProc && sh.sc != scText) + goto skip; + /* Usually there is a local and a global stProc symbol for a function. This means that the function name has already been entered into the mimimal symbol table *************** parse_partial_symbols (struct objfile *o *** 3345,3373 **** &objfile->static_psymbols, 0, sh.value, psymtab_language, objfile); - /* Skip over procedure to next one. */ - if (sh.index >= hdr->iauxMax) - { - /* Should not happen, but does when cross-compiling - with the MIPS compiler. FIXME -- pull later. */ - index_complaint (name); - new_sdx = cur_sdx + 1; /* Don't skip at all */ - } - else - new_sdx = AUX_GET_ISYM (fh->fBigendian, - (debug_info->external_aux - + fh->iauxBase - + sh.index)); procaddr = sh.value; - - if (new_sdx <= cur_sdx) - { - /* This should not happen either... FIXME. */ - complaint (&symfile_complaints, - "bad proc end in aux found from symbol %s", - name); - new_sdx = cur_sdx + 1; /* Don't skip backward */ - } cur_sdx = new_sdx; (*swap_sym_in) (cur_bfd, --- 3400,3406 ---- --qjNfmADvan18RZcF--