From patchwork Tue Oct 13 16:01:12 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksandar Ristovski X-Patchwork-Id: 9088 Received: (qmail 41363 invoked by alias); 13 Oct 2015 16:01:38 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 41279 invoked by uid 89); 13 Oct 2015 16:01:37 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.5 required=5.0 tests=AWL, BAYES_05, RCVD_IN_DNSWL_LOW, SPF_SOFTFAIL, UNWANTED_LANGUAGE_BODY autolearn=no version=3.3.2 X-HELO: smtp-a02.blackberry.com Received: from smtp-a02.blackberry.com (HELO smtp-a02.blackberry.com) (208.65.78.91) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 13 Oct 2015 16:01:26 +0000 Received: from mhs102cnc.rim.net ([10.65.141.76]) by mhs215cnc-app.rim.net with ESMTP; 13 Oct 2015 12:01:17 -0400 Received: from unknown (HELO qnxws9580.ott.qnx.com) ([10.65.140.254]) by mhs102cnc.rim.net with ESMTP; 13 Oct 2015 16:01:16 +0000 From: Aleksandar Ristovski To: gdb-patches@sourceware.org Cc: Aleksandar Ristovski Subject: [PATCH 2/4] [nto] Fixes for nto procfs. Date: Tue, 13 Oct 2015 12:01:12 -0400 Message-Id: <1444752074-878-3-git-send-email-aristovski@qnx.com> In-Reply-To: <1444752074-878-1-git-send-email-aristovski@qnx.com> References: <1444752074-878-1-git-send-email-aristovski@qnx.com> ChangeLog: * nto-procfs.c (sys/auxv.h): Include. (nto_procfs_path): Rename to... (nodestr): ... this, and change type. (nto_node): Use new variable and logic accordingly. (procfs_open_1): Use new variable name. Use local buffer to construct procfs path. (procfs_pidlist): Use NODESTR to construct procfs path. (procfs_files_info): Use NODESTR to output meaningful text. (procfs_pid_to_exec_file): New target function. (do_attach): Construct procfs using NODESTR. (procfs_xfer_partial): Logic for reading TARGET_OBJECT_AUXV. (init_procfs_targets): Wire procfs_pid_to_exec_file. * nto-tdep.c (symfile.h): Include. (nto_read_auxv_from_initial_stack): New function. * nto-tdep.h (nto_read_auxv_from_initial_stack): New function declaration. --- gdb/ChangeLog | 19 +++++++++ gdb/nto-procfs.c | 119 +++++++++++++++++++++++++++++++++++++++++++++---------- gdb/nto-tdep.c | 87 ++++++++++++++++++++++++++++++++++++++++ gdb/nto-tdep.h | 4 ++ 4 files changed, 209 insertions(+), 20 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3bd7d7d..04c9f0a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,22 @@ +<2015-2> Aleksandar Ristovski + + * nto-procfs.c (sys/auxv.h): Include. + (nto_procfs_path): Rename to... + (nodestr): ... this, and change type. + (nto_node): Use new variable and logic accordingly. + (procfs_open_1): Use new variable name. Use local buffer to construct + procfs path. + (procfs_pidlist): Use NODESTR to construct procfs path. + (procfs_files_info): Use NODESTR to output meaningful text. + (procfs_pid_to_exec_file): New target function. + (do_attach): Construct procfs using NODESTR. + (procfs_xfer_partial): Logic for reading TARGET_OBJECT_AUXV. + (init_procfs_targets): Wire procfs_pid_to_exec_file. + * nto-tdep.c (symfile.h): Include. + (nto_read_auxv_from_initial_stack): New function. + * nto-tdep.h (nto_read_auxv_from_initial_stack): New function + declaration. + <2015-1> Aleksandar Ristovski * nto-procfs.c (common/filestuff.h): Include. diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c index d659f79..a4b5ce8 100644 --- a/gdb/nto-procfs.c +++ b/gdb/nto-procfs.c @@ -30,6 +30,8 @@ #include #include #include +#include + #include "gdbcore.h" #include "inferior.h" #include "target.h" @@ -73,7 +75,7 @@ static int procfs_stopped_by_watchpoint (struct target_ops *ops); referenced elsewhere. 'nto_procfs_node' is a flag used to say whether we are local, or we should get the current node descriptor for the remote QNX node. */ -static char nto_procfs_path[PATH_MAX] = { "/proc" }; +static char *nodestr; static unsigned nto_procfs_node = ND_LOCAL_NODE; /* Return the current QNX Node, or error out. This is a simple @@ -85,10 +87,11 @@ nto_node (void) { unsigned node; - if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0) + if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0 + || nodestr == NULL) return ND_LOCAL_NODE; - node = netmgr_strtond (nto_procfs_path, 0); + node = netmgr_strtond (nodestr, 0); if (node == -1) error (_("Lost the QNX node. Debug session probably over.")); @@ -108,12 +111,12 @@ procfs_is_nto_target (bfd *abfd) static void procfs_open_1 (struct target_ops *ops, const char *arg, int from_tty) { - char *nodestr; char *endstr; char buffer[50]; int fd, total_size; procfs_sysinfo *sysinfo; struct cleanup *cleanups; + char nto_procfs_path[PATH_MAX]; /* Offer to kill previous inferiors before opening this target. */ target_preopen (from_tty); @@ -123,6 +126,9 @@ procfs_open_1 (struct target_ops *ops, const char *arg, int from_tty) /* Set the default node used for spawning to this one, and only override it if there is a valid arg. */ + xfree (nodestr); + nodestr = NULL; + nto_procfs_node = ND_LOCAL_NODE; nodestr = arg ? xstrdup (arg) : NULL; @@ -151,8 +157,6 @@ procfs_open_1 (struct target_ops *ops, const char *arg, int from_tty) } snprintf (nto_procfs_path, PATH_MAX - 1, "%s%s", nodestr ? nodestr : "", "/proc"); - if (nodestr) - xfree (nodestr); fd = open (nto_procfs_path, O_RDONLY); if (fd == -1) @@ -359,7 +363,7 @@ procfs_pidlist (char *args, int from_tty) { DIR *dp = NULL; struct dirent *dirp = NULL; - char buf[512]; + char buf[PATH_MAX]; procfs_info *pidinfo = NULL; procfs_debuginfo *info = NULL; procfs_status *status = NULL; @@ -367,12 +371,16 @@ procfs_pidlist (char *args, int from_tty) pid_t pid; char name[512]; struct cleanup *cleanups; + char procfs_dir[PATH_MAX]; - dp = opendir (nto_procfs_path); + snprintf (procfs_dir, sizeof (procfs_dir), "%s%s", nodestr ? nodestr : "", + "/proc"); + + dp = opendir (procfs_dir); if (dp == NULL) { fprintf_unfiltered (gdb_stderr, "failed to opendir \"%s\" - %d (%s)", - nto_procfs_path, errno, safe_strerror (errno)); + procfs_dir, errno, safe_strerror (errno)); return; } @@ -395,7 +403,8 @@ procfs_pidlist (char *args, int from_tty) do_cleanups (cleanups); return; } - snprintf (buf, 511, "%s/%s/as", nto_procfs_path, dirp->d_name); + snprintf (buf, sizeof (buf), "%s%s/%s/as", nodestr ? nodestr : "", + "/proc", dirp->d_name); pid = atoi (dirp->d_name); } while (pid == 0); @@ -406,8 +415,7 @@ procfs_pidlist (char *args, int from_tty) { fprintf_unfiltered (gdb_stderr, "failed to open %s - %d (%s)\n", buf, errno, safe_strerror (errno)); - do_cleanups (cleanups); - return; + continue; } inner_cleanup = make_cleanup_close (fd); @@ -431,11 +439,16 @@ procfs_pidlist (char *args, int from_tty) status = (procfs_status *) buf; for (status->tid = 1; status->tid <= num_threads; status->tid++) { - if (devctl (fd, DCMD_PROC_TIDSTATUS, status, sizeof (buf), 0) != EOK - && status->tid != 0) - break; - if (status->tid != 0) - printf_filtered ("%s - %d/%d\n", name, pid, status->tid); + const int err + = devctl (fd, DCMD_PROC_TIDSTATUS, status, sizeof (buf), 0); + printf_filtered ("%s - %d", name, pid); + if (err == EOK && status->tid != 0) + printf_filtered ("/%d\n", status->tid); + else + { + printf_filtered ("\n"); + break; + } } do_cleanups (inner_cleanup); @@ -599,9 +612,40 @@ procfs_files_info (struct target_ops *ignore) printf_unfiltered ("\tUsing the running image of %s %s via %s.\n", inf->attach_flag ? "attached" : "child", - target_pid_to_str (inferior_ptid), nto_procfs_path); + target_pid_to_str (inferior_ptid), + nodestr ? nodestr : "local node"); +} + +/* Read executable file name for the given PID. */ + +static char * +procfs_pid_to_exec_file (struct target_ops *ops, const int pid) +{ + int proc_fd; + static char proc_path[PATH_MAX]; + ssize_t rd; + + /* Read exe file name. */ + snprintf (proc_path, sizeof (proc_path), "%s/proc/%d/exefile", + nodestr ? nodestr : "", pid); + proc_fd = open (proc_path, O_RDONLY); + if (proc_fd == -1) + return NULL; + + rd = read (proc_fd, proc_path, sizeof (proc_path) - 1); + close (proc_fd); + if (rd <= 0) + { + proc_path[0] = '\0'; + return NULL; + } + else + proc_path[rd] = '\0'; + + return proc_path; } + /* Attach to process PID, then initialize for debugging it. */ static void procfs_attach (struct target_ops *ops, const char *args, int from_tty) @@ -653,8 +697,8 @@ do_attach (ptid_t ptid) struct sigevent event; char path[PATH_MAX]; - snprintf (path, PATH_MAX - 1, "%s/%d/as", nto_procfs_path, - ptid_get_pid (ptid)); + snprintf (path, PATH_MAX - 1, "%s%s/%d/as", nodestr ? nodestr : "", + "/proc", ptid_get_pid (ptid)); ctl_fd = open (path, O_RDWR); if (ctl_fd == -1) error (_("Couldn't open proc file %s, error %d (%s)"), path, errno, @@ -872,6 +916,40 @@ procfs_xfer_partial (struct target_ops *ops, enum target_object object, { case TARGET_OBJECT_MEMORY: return procfs_xfer_memory (readbuf, writebuf, offset, len, xfered_len); + case TARGET_OBJECT_AUXV: + if (readbuf != NULL) + { + int err; + CORE_ADDR initial_stack; + debug_process_t procinfo; + /* For 32-bit architecture, size of auxv_t is 8 bytes. */ + const unsigned int sizeof_auxv_t = sizeof (auxv_t); + const unsigned int sizeof_tempbuf = 20 * sizeof_auxv_t; + int tempread; + gdb_byte *const tempbuf = alloca (sizeof_tempbuf); + + if (!tempbuf) + return TARGET_XFER_E_IO; + + err = devctl (ctl_fd, DCMD_PROC_INFO, &procinfo, + sizeof procinfo, 0); + if (err != EOK) + return TARGET_XFER_E_IO; + + /* Similar as in the case of a core file, we read auxv from + initial_stack. */ + initial_stack = procinfo.initial_stack; + + /* procfs is always 'self-hosted', no byte-order manipulation. */ + tempread = nto_read_auxv_from_initial_stack (initial_stack, tempbuf, + sizeof_tempbuf, + sizeof (auxv_t)); + tempread = min (tempread, len) - offset; + memcpy (readbuf, tempbuf + offset, tempread); + *xfered_len = tempread; + return tempread ? TARGET_XFER_OK : TARGET_XFER_EOF; + } + /* Fallthru */ default: return ops->beneath->to_xfer_partial (ops->beneath, object, annex, readbuf, writebuf, offset, len, @@ -1444,6 +1522,7 @@ init_procfs_targets (void) t->to_interrupt = procfs_interrupt; t->to_have_continuable_watchpoint = 1; t->to_extra_thread_info = nto_extra_thread_info; + t->to_pid_to_exec_file = procfs_pid_to_exec_file; nto_native_ops = t; diff --git a/gdb/nto-tdep.c b/gdb/nto-tdep.c index 81ee7fb..63094e8 100644 --- a/gdb/nto-tdep.c +++ b/gdb/nto-tdep.c @@ -31,6 +31,7 @@ #include "solib-svr4.h" #include "gdbcore.h" #include "objfiles.h" +#include "symfile.h" #ifdef __CYGWIN__ #include @@ -394,3 +395,89 @@ nto_initialize_signals (void) signal_pass_update (SIGPHOTON, 1); #endif } + + +/* Read AUXV from initial_stack. */ +LONGEST +nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack, gdb_byte *readbuf, + LONGEST len, size_t sizeof_auxv_t) +{ + gdb_byte targ32[4]; /* For 32 bit target values. */ + gdb_byte targ64[8]; /* For 64 bit target values. */ + CORE_ADDR data_ofs = 0; + ULONGEST anint; + LONGEST len_read = 0; + gdb_byte *buff; + enum bfd_endian byte_order; + int ptr_size; + + if (sizeof_auxv_t == 16) + ptr_size = 8; + else + ptr_size = 4; + + /* Skip over argc, argv and envp... Comment from ldd.c: + + The startup frame is set-up so that we have: + auxv + NULL + ... + envp2 + envp1 <----- void *frame + (argc + 2) * sizeof(char *) + NULL + ... + argv2 + argv1 + argc <------ void * frame + + On entry to ldd, frame gives the address of argc on the stack. */ + /* Read argc. 4 bytes on both 64 and 32 bit arches and luckily little + * endian. So we just read first 4 bytes. */ + if (target_read_memory (initial_stack + data_ofs, targ32, 4) != 0) + return 0; + + byte_order = gdbarch_byte_order (target_gdbarch ()); + + anint = extract_unsigned_integer (targ32, sizeof (targ32), byte_order); + + /* Size of pointer is assumed to be 4 bytes (32 bit arch.) */ + data_ofs += (anint + 2) * ptr_size; /* + 2 comes from argc itself and + NULL terminating pointer in + argv. */ + + /* Now loop over env table: */ + anint = 0; + while (target_read_memory (initial_stack + data_ofs, targ64, ptr_size) + == 0) + { + if (extract_unsigned_integer (targ64, ptr_size, byte_order) == 0) + anint = 1; /* Keep looping until non-null entry is found. */ + else if (anint) + break; + data_ofs += ptr_size; + } + initial_stack += data_ofs; + + memset (readbuf, 0, len); + buff = readbuf; + while (len_read <= len-sizeof_auxv_t) + { + if (target_read_memory (initial_stack + len_read, buff, sizeof_auxv_t) + == 0) + { + /* Both 32 and 64 bit structures have int as the first field. */ + const ULONGEST a_type + = extract_unsigned_integer (buff, sizeof (targ32), byte_order); + + if (a_type == AT_NULL) + break; + buff += sizeof_auxv_t; + len_read += sizeof_auxv_t; + } + else + break; + } + return len_read; +} + + diff --git a/gdb/nto-tdep.h b/gdb/nto-tdep.h index bd85d2a..7089a12 100644 --- a/gdb/nto-tdep.h +++ b/gdb/nto-tdep.h @@ -168,4 +168,8 @@ int nto_in_dynsym_resolve_code (CORE_ADDR pc); char *nto_extra_thread_info (struct target_ops *self, struct thread_info *); +LONGEST nto_read_auxv_from_initial_stack (CORE_ADDR inital_stack, + gdb_byte *readbuf, + LONGEST len, size_t sizeof_auxv_t); + #endif