aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/linux-low.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2009-07-31 15:25:22 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2009-07-31 15:25:22 +0000
commitefcbbd1428e455c9ca59a590a91e4db200b3813c (patch)
tree7565c0101e30d632a24d9e59157649e0cb938d59 /gdb/gdbserver/linux-low.c
parentf4d9badee6725f50cb4ebc607fad078a7da64584 (diff)
downloadgdb-efcbbd1428e455c9ca59a590a91e4db200b3813c.zip
gdb-efcbbd1428e455c9ca59a590a91e4db200b3813c.tar.gz
gdb-efcbbd1428e455c9ca59a590a91e4db200b3813c.tar.bz2
ChangeLog:
* linux-nat.c: Include <sys/vfs.h>. (SPUFS_MAGIC): Define. (spu_enumerate_spu_ids): New function. (linux_proc_xfer_spu): New function. (linux_xfer_partial): Handle TARGET_OBJECT_SPU. (iterate_over_spus): New function. (struct linux_spu_corefile_data): New data type. (linux_spu_corefile_callback): New function. (linux_spu_make_corefile_notes): New function. (linux_nat_make_corefile_notes): Call it. * corelow.c (struct spuid_list): New data type. (add_to_spuid_list): New function. (core_xfer_partial): Handle TARGET_OBJECT_SPU. gdbserver/ChangeLog: * linux-low.c: Include <sys/stat.h> and <sys/vfs.h>. (SPUFS_MAGIC): Define. (spu_enumerate_spu_ids): New function. (linux_qxfer_spu): New function. (linux_target_ops): Install linux_qxfer_spu.
Diffstat (limited to 'gdb/gdbserver/linux-low.c')
-rw-r--r--gdb/gdbserver/linux-low.c102
1 files changed, 101 insertions, 1 deletions
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 5edc473..a88f4d1 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -40,6 +40,12 @@
#include <pwd.h>
#include <sys/types.h>
#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+
+#ifndef SPUFS_MAGIC
+#define SPUFS_MAGIC 0x23c9b64e
+#endif
#ifndef PTRACE_GETSIGINFO
# define PTRACE_GETSIGINFO 0x4202
@@ -3034,6 +3040,100 @@ linux_supports_multi_process (void)
return 1;
}
+
+/* Enumerate spufs IDs for process PID. */
+static int
+spu_enumerate_spu_ids (long pid, unsigned char *buf, CORE_ADDR offset, int len)
+{
+ int pos = 0;
+ int written = 0;
+ char path[128];
+ DIR *dir;
+ struct dirent *entry;
+
+ sprintf (path, "/proc/%ld/fd", pid);
+ dir = opendir (path);
+ if (!dir)
+ return -1;
+
+ rewinddir (dir);
+ while ((entry = readdir (dir)) != NULL)
+ {
+ struct stat st;
+ struct statfs stfs;
+ int fd;
+
+ fd = atoi (entry->d_name);
+ if (!fd)
+ continue;
+
+ sprintf (path, "/proc/%ld/fd/%d", pid, fd);
+ if (stat (path, &st) != 0)
+ continue;
+ if (!S_ISDIR (st.st_mode))
+ continue;
+
+ if (statfs (path, &stfs) != 0)
+ continue;
+ if (stfs.f_type != SPUFS_MAGIC)
+ continue;
+
+ if (pos >= offset && pos + 4 <= offset + len)
+ {
+ *(unsigned int *)(buf + pos - offset) = fd;
+ written += 4;
+ }
+ pos += 4;
+ }
+
+ closedir (dir);
+ return written;
+}
+
+/* Implements the to_xfer_partial interface for the TARGET_OBJECT_SPU
+ object type, using the /proc file system. */
+static int
+linux_qxfer_spu (const char *annex, unsigned char *readbuf,
+ unsigned const char *writebuf,
+ CORE_ADDR offset, int len)
+{
+ long pid = lwpid_of (get_thread_lwp (current_inferior));
+ char buf[128];
+ int fd = 0;
+ int ret = 0;
+
+ if (!writebuf && !readbuf)
+ return -1;
+
+ if (!*annex)
+ {
+ if (!readbuf)
+ return -1;
+ else
+ return spu_enumerate_spu_ids (pid, readbuf, offset, len);
+ }
+
+ sprintf (buf, "/proc/%ld/fd/%s", pid, annex);
+ fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
+ if (fd <= 0)
+ return -1;
+
+ if (offset != 0
+ && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
+ {
+ close (fd);
+ return 0;
+ }
+
+ if (writebuf)
+ ret = write (fd, writebuf, (size_t) len);
+ else
+ ret = read (fd, readbuf, (size_t) len);
+
+ close (fd);
+ return ret;
+}
+
static struct target_ops linux_target_ops = {
linux_create_inferior,
linux_attach,
@@ -3064,7 +3164,7 @@ static struct target_ops linux_target_ops = {
#else
NULL,
#endif
- NULL,
+ linux_qxfer_spu,
hostio_last_error_from_errno,
linux_qxfer_osdata,
linux_xfer_siginfo,