From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19297 invoked by alias); 14 Dec 2006 07:18:57 -0000 Received: (qmail 19276 invoked by uid 22791); 14 Dec 2006 07:18:55 -0000 X-Spam-Check-By: sourceware.org Received: from omta01sl.mx.bigpond.com (HELO omta01sl.mx.bigpond.com) (144.140.92.153) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 14 Dec 2006 07:18:44 +0000 Received: from oaamta01sl.mx.bigpond.com ([60.226.252.218]) by omta01sl.mx.bigpond.com with ESMTP id <20061214071840.VZUV1340.omta01sl.mx.bigpond.com@oaamta01sl.mx.bigpond.com>; Thu, 14 Dec 2006 07:18:40 +0000 Received: from bubble.grove.modra.org ([60.226.252.218]) by oaamta01sl.mx.bigpond.com with ESMTP id <20061214071840.DGZZ5409.oaamta01sl.mx.bigpond.com@bubble.grove.modra.org>; Thu, 14 Dec 2006 07:18:40 +0000 Received: by bubble.grove.modra.org (Postfix, from userid 500) id C226222D757; Thu, 14 Dec 2006 17:48:39 +1030 (CST) Date: Thu, 14 Dec 2006 07:18:00 -0000 From: Alan Modra To: gdb-patches@sourceware.org Cc: binutils@sourceware.org, uweigand@de.ibm.com Subject: spu-gdb vs. stabs Message-ID: <20061214071839.GD6013@bubble.grove.modra.org> Mail-Followup-To: gdb-patches@sourceware.org, binutils@sourceware.org, uweigand@de.ibm.com Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.9i Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2006-12/txt/msg00190.txt.bz2 The iovec support that Andrew added to BFD a couple of years ago doesn't allow the user to provide a stat function. This doesn't matter in most cases, but someone ran into "ridiculous string table size" errors a while ago when trying to debug an embedded spu binary that used stabs. The problem is that gdb/dbxread.c uses bfd_get_size to validate string table accesses, and bfd_get_size uses the underlying iovec->stat function which returns a zero struct stat. There are a number of ways to fix this. One is to modify dbxread.c to accept a zero return from bfd_get_size. Another is to make the default iovec stat function return INT_MAX in st_size to effectively circumvent the dbxread.c checks. I chose to extend bfd_openr_iovec to accept a user "stat" function so that the actual size can be provided, but then cowardly decided to just return a size of INT_MAX in the spu implementation for stat. See the comment. If the kernel /proc file used to find the address of a spu embedded binary also returned the size then we could easily provide a better stat function. Are the gdb bits OK to apply? bfd/ * opncls.c (bfd_openr_iovec): Add "stat" parameter. (struct opncls): Add "stat" field. (opncls_bstat): Call vec->stat. * bfd-in2.h: Regenerate. * elf32-spu.c (spu_elf_open_builtin_lib): Adjust. gdb/ * spu-linux-nat.c (spu_bfd_iovec_stat): New function. (spu_bfd_open): Adjust bfd_openr_iovec call. Index: bfd/opncls.c =================================================================== RCS file: /cvs/src/src/bfd/opncls.c,v retrieving revision 1.44 diff -u -p -r1.44 opncls.c --- bfd/opncls.c 1 Jun 2006 03:45:58 -0000 1.44 +++ bfd/opncls.c 14 Dec 2006 01:44:42 -0000 @@ -384,7 +384,10 @@ SYNOPSIS file_ptr nbytes, file_ptr offset), int (*close) (struct bfd *nbfd, - void *stream)); + void *stream), + int (*stat) (struct bfd *abfd, + void *stream, + struct stat *sb)); DESCRIPTION @@ -411,6 +414,10 @@ DESCRIPTION <>. @var{close} either succeeds returning 0, or fails returning -1 (setting <>). + Calls @var{stat} to fill in a stat structure for bfd_stat, + bfd_get_size, and bfd_get_mtime calls. @var{stat} returns 0 + on success, or returns -1 on failure (setting <>). + If <> returns <> then an error has occurred. Possible errors are <>, <> and <>. @@ -423,6 +430,7 @@ struct opncls file_ptr (*pread) (struct bfd *abfd, void *stream, void *buf, file_ptr nbytes, file_ptr offset); int (*close) (struct bfd *abfd, void *stream); + int (*stat) (struct bfd *abfd, void *stream, struct stat *sb); file_ptr where; }; @@ -485,10 +493,15 @@ opncls_bflush (struct bfd *abfd ATTRIBUT } static int -opncls_bstat (struct bfd *abfd ATTRIBUTE_UNUSED, struct stat *sb) +opncls_bstat (struct bfd *abfd, struct stat *sb) { + struct opncls *vec = abfd->iostream; + memset (sb, 0, sizeof (*sb)); - return 0; + if (vec->stat == NULL) + return 0; + + return (vec->stat) (abfd, vec->stream, sb); } static const struct bfd_iovec opncls_iovec = { @@ -507,7 +520,10 @@ bfd_openr_iovec (const char *filename, c file_ptr nbytes, file_ptr offset), int (*close) (struct bfd *nbfd, - void *stream)) + void *stream), + int (*stat) (struct bfd *abfd, + void *stream, + struct stat *sb)) { bfd *nbfd; const bfd_target *target_vec; @@ -539,6 +555,7 @@ bfd_openr_iovec (const char *filename, c vec->stream = stream; vec->pread = pread; vec->close = close; + vec->stat = stat; nbfd->iovec = &opncls_iovec; nbfd->iostream = vec; Index: bfd/elf32-spu.c =================================================================== RCS file: /cvs/src/src/bfd/elf32-spu.c,v retrieving revision 1.1 diff -u -p -r1.1 elf32-spu.c --- bfd/elf32-spu.c 25 Oct 2006 06:49:20 -0000 1.1 +++ bfd/elf32-spu.c 14 Dec 2006 01:44:35 -0000 @@ -1090,6 +1090,7 @@ spu_elf_open_builtin_lib (bfd **ovl_bfd, ovl_mgr_open, (void *) stream, ovl_mgr_pread, + NULL, NULL); return *ovl_bfd != NULL; } Index: gdb/spu-linux-nat.c =================================================================== RCS file: /cvs/src/src/gdb/spu-linux-nat.c,v retrieving revision 1.1 diff -u -p -r1.1 spu-linux-nat.c --- gdb/spu-linux-nat.c 22 Nov 2006 13:49:53 -0000 1.1 +++ gdb/spu-linux-nat.c 14 Dec 2006 01:45:05 -0000 @@ -281,6 +281,22 @@ spu_bfd_iovec_pread (struct bfd *abfd, v return nbytes; } +static int +spu_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb) +{ + /* We don't have an easy way of finding the size of embedded spu + images. We could parse the in-memory ELF header and section + table to find the extent of the last section but that seems + pointless when the size is needed only for checks of other + parsed values in dbxread.c. */ +#ifdef INT_MAX + sb->st_size = INT_MAX; +#else + sb->st_size = ((unsigned) -1) >> 1; +#endif + return 0; +} + static bfd * spu_bfd_open (CORE_ADDR addr) { @@ -291,7 +307,8 @@ spu_bfd_open (CORE_ADDR addr) nbfd = bfd_openr_iovec (xstrdup (""), "elf32-spu", spu_bfd_iovec_open, open_closure, - spu_bfd_iovec_pread, spu_bfd_iovec_close); + spu_bfd_iovec_pread, spu_bfd_iovec_close, + spu_bfd_iovec_stat); if (!nbfd) return NULL; -- Alan Modra IBM OzLabs - Linux Technology Centre