* spu-gdb vs. stabs
@ 2006-12-14 7:18 Alan Modra
2006-12-14 17:34 ` Ulrich Weigand
0 siblings, 1 reply; 2+ messages in thread
From: Alan Modra @ 2006-12-14 7:18 UTC (permalink / raw)
To: gdb-patches; +Cc: binutils, uweigand
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
<<bfd_close>>. @var{close} either succeeds returning 0, or
fails returning -1 (setting <<bfd_error>>).
+ 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 <<bfd_error>>).
+
If <<bfd_openr_iovec>> returns <<NULL>> then an error has
occurred. Possible errors are <<bfd_error_no_memory>>,
<<bfd_error_invalid_target>> and <<bfd_error_system_call>>.
@@ -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 ("<in-memory>"), "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
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: spu-gdb vs. stabs
2006-12-14 7:18 spu-gdb vs. stabs Alan Modra
@ 2006-12-14 17:34 ` Ulrich Weigand
0 siblings, 0 replies; 2+ messages in thread
From: Ulrich Weigand @ 2006-12-14 17:34 UTC (permalink / raw)
To: Alan Modra; +Cc: gdb-patches, binutils
Alan Modra wrote:
> 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.
That sounds great, thanks!
> 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.
That's not so easy, the information gets lost during embedding
already. It would require ABI changes throughout the process ...
If we really need a proper size at some point, I think parsing
the ELF headers should suffice for that.
> gdb/
> * spu-linux-nat.c (spu_bfd_iovec_stat): New function.
> (spu_bfd_open): Adjust bfd_openr_iovec call.
This is OK, except ...
> +#ifdef INT_MAX
> + sb->st_size = INT_MAX;
> +#else
> + sb->st_size = ((unsigned) -1) >> 1;
> +#endif
... GDB's defs.h already has a fallback definition for INT_MAX,
so you can just use the macro unconditionally here.
Thanks,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-12-14 17:34 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-12-14 7:18 spu-gdb vs. stabs Alan Modra
2006-12-14 17:34 ` Ulrich Weigand
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox