diff options
author | Jim Kingdon <jkingdon@engr.sgi.com> | 1994-03-01 21:00:18 +0000 |
---|---|---|
committer | Jim Kingdon <jkingdon@engr.sgi.com> | 1994-03-01 21:00:18 +0000 |
commit | 4ad0021ebc16093209b5067aa2b8ed708c34d177 (patch) | |
tree | 78dc7893c3e2518f7765d5f0c9e484ed35233f45 /gdb/target.c | |
parent | 8b1d1557f36283b8d669eede6fcd603151d67632 (diff) | |
download | gdb-4ad0021ebc16093209b5067aa2b8ed708c34d177.zip gdb-4ad0021ebc16093209b5067aa2b8ed708c34d177.tar.gz gdb-4ad0021ebc16093209b5067aa2b8ed708c34d177.tar.bz2 |
* target.c, target.h (target_read_string): Provide error detection to
caller. Put string in malloc'd space, so caller need not impose
arbitrary limits.
* solib.c (find_solib): Update to use new interface.
* irix5-nat.c (find_solib): Read o_path from inferior
(clear_solib): Free storage for o_path.
* valprint.c (val_print_string): Add comments.
Diffstat (limited to 'gdb/target.c')
-rw-r--r-- | gdb/target.c | 406 |
1 files changed, 390 insertions, 16 deletions
diff --git a/gdb/target.c b/gdb/target.c index 62717c0..038ca0d 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1,5 +1,5 @@ /* Select target systems and architectures at runtime for GDB. - Copyright 1990, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1992, 1993, 1994 Free Software Foundation, Inc. Contributed by Cygnus Support. This file is part of GDB. @@ -28,6 +28,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" #include "symfile.h" #include "objfiles.h" +#include "wait.h" +#include <signal.h> extern int errno; @@ -434,22 +436,31 @@ pop_target () #undef MIN #define MIN(A, B) (((A) <= (B)) ? (A) : (B)) -/* target_read_string -- read a null terminated string from MEMADDR in target. - The read may also be terminated early by getting an error from target_xfer_ - memory. - LEN is the size of the buffer pointed to by MYADDR. Note that a terminating - null will only be written if there is sufficient room. The return value is - is the number of bytes (including the null) actually transferred. -*/ +/* target_read_string -- read a null terminated string, up to LEN bytes, + from MEMADDR in target. Set *ERRNOP to the errno code, or 0 if successful. + Set *STRING to a pointer to malloc'd memory containing the data; the caller + is responsible for freeing it. Return the number of bytes successfully + read. */ int -target_read_string (memaddr, myaddr, len) +target_read_string (memaddr, string, len, errnop) CORE_ADDR memaddr; - char *myaddr; + char **string; int len; + int *errnop; { int tlen, origlen, offset, i; char buf[4]; + int errcode = 0; + char *buffer; + int buffer_allocated; + char *bufptr; + unsigned int nbytes_read = 0; + + /* Small for testing. */ + buffer_allocated = 4; + buffer = xmalloc (buffer_allocated); + bufptr = buffer; origlen = len; @@ -458,20 +469,39 @@ target_read_string (memaddr, myaddr, len) tlen = MIN (len, 4 - (memaddr & 3)); offset = memaddr & 3; - if (target_xfer_memory (memaddr & ~3, buf, 4, 0)) - return origlen - len; + errcode = target_xfer_memory (memaddr & ~3, buf, 4, 0); + if (errcode != 0) + goto done; + + if (bufptr - buffer + tlen > buffer_allocated) + { + unsigned int bytes; + bytes = bufptr - buffer; + buffer_allocated *= 2; + buffer = xrealloc (buffer, buffer_allocated); + bufptr = buffer + bytes; + } for (i = 0; i < tlen; i++) { - *myaddr++ = buf[i + offset]; + *bufptr++ = buf[i + offset]; if (buf[i + offset] == '\000') - return (origlen - len) + i + 1; + { + nbytes_read += i + 1; + goto done; + } } memaddr += tlen; len -= tlen; + nbytes_read += tlen; } - return origlen; + done: + if (errnop != NULL) + *errnop = errcode; + if (string != NULL) + *string = buffer; + return nbytes_read; } /* Read LEN bytes of target memory at address MEMADDR, placing the results in @@ -658,6 +688,12 @@ target_preopen (from_tty) else error ("Program not killed."); } + + /* Calling target_kill may remove the target from the stack. But if + it doesn't (which seems like a win for UDI), remove it now. */ + + if (target_has_execution) + pop_target (); } /* Detach a target after doing deferred register stores. */ @@ -811,6 +847,8 @@ static struct { {"SIGSOUND", "Sound completed"}, {"SIGSAK", "Secure attention"}, {NULL, "Unknown signal"}, + {NULL, "Internal error: printing TARGET_SIGNAL_DEFAULT"}, + /* Last entry, used to check whether the table is the right size. */ {NULL, "TARGET_SIGNAL_MAGIC"} }; @@ -847,12 +885,348 @@ target_signal_from_name (name) questionable; seems like by now people should call it SIGABRT instead. */ - for (sig = TARGET_SIGNAL_HUP; signals[sig].name != NULL; ++sig) + /* This ugly cast brought to you by the native VAX compiler. */ + for (sig = TARGET_SIGNAL_HUP; + signals[sig].name != NULL; + sig = (enum target_signal)((int)sig + 1)) if (STREQ (name, signals[sig].name)) return sig; return TARGET_SIGNAL_UNKNOWN; } +/* The following functions are to help certain targets deal + with the signal/waitstatus stuff. They could just as well be in + a file called native-utils.c or unixwaitstatus-utils.c or whatever. */ + +/* Convert host signal to our signals. */ +enum target_signal +target_signal_from_host (hostsig) + int hostsig; +{ + /* A switch statement would make sense but would require special kludges + to deal with the cases where more than one signal has the same number. */ + + if (hostsig == 0) return TARGET_SIGNAL_0; + +#if defined (SIGHUP) + if (hostsig == SIGHUP) return TARGET_SIGNAL_HUP; +#endif +#if defined (SIGINT) + if (hostsig == SIGINT) return TARGET_SIGNAL_INT; +#endif +#if defined (SIGQUIT) + if (hostsig == SIGQUIT) return TARGET_SIGNAL_QUIT; +#endif +#if defined (SIGILL) + if (hostsig == SIGILL) return TARGET_SIGNAL_ILL; +#endif +#if defined (SIGTRAP) + if (hostsig == SIGTRAP) return TARGET_SIGNAL_TRAP; +#endif +#if defined (SIGABRT) + if (hostsig == SIGABRT) return TARGET_SIGNAL_ABRT; +#endif +#if defined (SIGEMT) + if (hostsig == SIGEMT) return TARGET_SIGNAL_EMT; +#endif +#if defined (SIGFPE) + if (hostsig == SIGFPE) return TARGET_SIGNAL_FPE; +#endif +#if defined (SIGKILL) + if (hostsig == SIGKILL) return TARGET_SIGNAL_KILL; +#endif +#if defined (SIGBUS) + if (hostsig == SIGBUS) return TARGET_SIGNAL_BUS; +#endif +#if defined (SIGSEGV) + if (hostsig == SIGSEGV) return TARGET_SIGNAL_SEGV; +#endif +#if defined (SIGSYS) + if (hostsig == SIGSYS) return TARGET_SIGNAL_SYS; +#endif +#if defined (SIGPIPE) + if (hostsig == SIGPIPE) return TARGET_SIGNAL_PIPE; +#endif +#if defined (SIGALRM) + if (hostsig == SIGALRM) return TARGET_SIGNAL_ALRM; +#endif +#if defined (SIGTERM) + if (hostsig == SIGTERM) return TARGET_SIGNAL_TERM; +#endif +#if defined (SIGUSR1) + if (hostsig == SIGUSR1) return TARGET_SIGNAL_USR1; +#endif +#if defined (SIGUSR2) + if (hostsig == SIGUSR2) return TARGET_SIGNAL_USR2; +#endif +#if defined (SIGCLD) + if (hostsig == SIGCLD) return TARGET_SIGNAL_CHLD; +#endif +#if defined (SIGCHLD) + if (hostsig == SIGCHLD) return TARGET_SIGNAL_CHLD; +#endif +#if defined (SIGPWR) + if (hostsig == SIGPWR) return TARGET_SIGNAL_PWR; +#endif +#if defined (SIGWINCH) + if (hostsig == SIGWINCH) return TARGET_SIGNAL_WINCH; +#endif +#if defined (SIGURG) + if (hostsig == SIGURG) return TARGET_SIGNAL_URG; +#endif +#if defined (SIGIO) + if (hostsig == SIGIO) return TARGET_SIGNAL_IO; +#endif +#if defined (SIGPOLL) + if (hostsig == SIGPOLL) return TARGET_SIGNAL_POLL; +#endif +#if defined (SIGSTOP) + if (hostsig == SIGSTOP) return TARGET_SIGNAL_STOP; +#endif +#if defined (SIGTSTP) + if (hostsig == SIGTSTP) return TARGET_SIGNAL_TSTP; +#endif +#if defined (SIGCONT) + if (hostsig == SIGCONT) return TARGET_SIGNAL_CONT; +#endif +#if defined (SIGTTIN) + if (hostsig == SIGTTIN) return TARGET_SIGNAL_TTIN; +#endif +#if defined (SIGTTOU) + if (hostsig == SIGTTOU) return TARGET_SIGNAL_TTOU; +#endif +#if defined (SIGVTALRM) + if (hostsig == SIGVTALRM) return TARGET_SIGNAL_VTALRM; +#endif +#if defined (SIGPROF) + if (hostsig == SIGPROF) return TARGET_SIGNAL_PROF; +#endif +#if defined (SIGXCPU) + if (hostsig == SIGXCPU) return TARGET_SIGNAL_XCPU; +#endif +#if defined (SIGXFSZ) + if (hostsig == SIGXFSZ) return TARGET_SIGNAL_XFSZ; +#endif +#if defined (SIGWIND) + if (hostsig == SIGWIND) return TARGET_SIGNAL_WIND; +#endif +#if defined (SIGPHONE) + if (hostsig == SIGPHONE) return TARGET_SIGNAL_PHONE; +#endif +#if defined (SIGLOST) + if (hostsig == SIGLOST) return TARGET_SIGNAL_LOST; +#endif +#if defined (SIGWAITING) + if (hostsig == SIGWAITING) return TARGET_SIGNAL_WAITING; +#endif +#if defined (SIGLWP) + if (hostsig == SIGLWP) return TARGET_SIGNAL_LWP; +#endif +#if defined (SIGDANGER) + if (hostsig == SIGDANGER) return TARGET_SIGNAL_DANGER; +#endif +#if defined (SIGGRANT) + if (hostsig == SIGGRANT) return TARGET_SIGNAL_GRANT; +#endif +#if defined (SIGRETRACT) + if (hostsig == SIGRETRACT) return TARGET_SIGNAL_RETRACT; +#endif +#if defined (SIGMSG) + if (hostsig == SIGMSG) return TARGET_SIGNAL_MSG; +#endif +#if defined (SIGSOUND) + if (hostsig == SIGSOUND) return TARGET_SIGNAL_SOUND; +#endif +#if defined (SIGSAK) + if (hostsig == SIGSAK) return TARGET_SIGNAL_SAK; +#endif + return TARGET_SIGNAL_UNKNOWN; +} + +int +target_signal_to_host (oursig) + enum target_signal oursig; +{ + switch (oursig) + { + case TARGET_SIGNAL_0: return 0; + +#if defined (SIGHUP) + case TARGET_SIGNAL_HUP: return SIGHUP; +#endif +#if defined (SIGINT) + case TARGET_SIGNAL_INT: return SIGINT; +#endif +#if defined (SIGQUIT) + case TARGET_SIGNAL_QUIT: return SIGQUIT; +#endif +#if defined (SIGILL) + case TARGET_SIGNAL_ILL: return SIGILL; +#endif +#if defined (SIGTRAP) + case TARGET_SIGNAL_TRAP: return SIGTRAP; +#endif +#if defined (SIGABRT) + case TARGET_SIGNAL_ABRT: return SIGABRT; +#endif +#if defined (SIGEMT) + case TARGET_SIGNAL_EMT: return SIGEMT; +#endif +#if defined (SIGFPE) + case TARGET_SIGNAL_FPE: return SIGFPE; +#endif +#if defined (SIGKILL) + case TARGET_SIGNAL_KILL: return SIGKILL; +#endif +#if defined (SIGBUS) + case TARGET_SIGNAL_BUS: return SIGBUS; +#endif +#if defined (SIGSEGV) + case TARGET_SIGNAL_SEGV: return SIGSEGV; +#endif +#if defined (SIGSYS) + case TARGET_SIGNAL_SYS: return SIGSYS; +#endif +#if defined (SIGPIPE) + case TARGET_SIGNAL_PIPE: return SIGPIPE; +#endif +#if defined (SIGALRM) + case TARGET_SIGNAL_ALRM: return SIGALRM; +#endif +#if defined (SIGTERM) + case TARGET_SIGNAL_TERM: return SIGTERM; +#endif +#if defined (SIGUSR1) + case TARGET_SIGNAL_USR1: return SIGUSR1; +#endif +#if defined (SIGUSR2) + case TARGET_SIGNAL_USR2: return SIGUSR2; +#endif +#if defined (SIGCHLD) || defined (SIGCLD) + case TARGET_SIGNAL_CHLD: +#if defined (SIGCHLD) + return SIGCHLD; +#else + return SIGCLD; +#endif +#endif /* SIGCLD or SIGCHLD */ +#if defined (SIGPWR) + case TARGET_SIGNAL_PWR: return SIGPWR; +#endif +#if defined (SIGWINCH) + case TARGET_SIGNAL_WINCH: return SIGWINCH; +#endif +#if defined (SIGURG) + case TARGET_SIGNAL_URG: return SIGURG; +#endif +#if defined (SIGIO) + case TARGET_SIGNAL_IO: return SIGIO; +#endif +#if defined (SIGPOLL) + case TARGET_SIGNAL_POLL: return SIGPOLL; +#endif +#if defined (SIGSTOP) + case TARGET_SIGNAL_STOP: return SIGSTOP; +#endif +#if defined (SIGTSTP) + case TARGET_SIGNAL_TSTP: return SIGTSTP; +#endif +#if defined (SIGCONT) + case TARGET_SIGNAL_CONT: return SIGCONT; +#endif +#if defined (SIGTTIN) + case TARGET_SIGNAL_TTIN: return SIGTTIN; +#endif +#if defined (SIGTTOU) + case TARGET_SIGNAL_TTOU: return SIGTTOU; +#endif +#if defined (SIGVTALRM) + case TARGET_SIGNAL_VTALRM: return SIGVTALRM; +#endif +#if defined (SIGPROF) + case TARGET_SIGNAL_PROF: return SIGPROF; +#endif +#if defined (SIGXCPU) + case TARGET_SIGNAL_XCPU: return SIGXCPU; +#endif +#if defined (SIGXFSZ) + case TARGET_SIGNAL_XFSZ: return SIGXFSZ; +#endif +#if defined (SIGWIND) + case TARGET_SIGNAL_WIND: return SIGWIND; +#endif +#if defined (SIGPHONE) + case TARGET_SIGNAL_PHONE: return SIGPHONE; +#endif +#if defined (SIGLOST) + case TARGET_SIGNAL_LOST: return SIGLOST; +#endif +#if defined (SIGWAITING) + case TARGET_SIGNAL_WAITING: return SIGWAITING; +#endif +#if defined (SIGLWP) + case TARGET_SIGNAL_LWP: return SIGLWP; +#endif +#if defined (SIGDANGER) + case TARGET_SIGNAL_DANGER: return SIGDANGER; +#endif +#if defined (SIGGRANT) + case TARGET_SIGNAL_GRANT: return SIGGRANT; +#endif +#if defined (SIGRETRACT) + case TARGET_SIGNAL_RETRACT: return SIGRETRACT; +#endif +#if defined (SIGMSG) + case TARGET_SIGNAL_MSG: return SIGMSG; +#endif +#if defined (SIGSOUND) + case TARGET_SIGNAL_SOUND: return SIGSOUND; +#endif +#if defined (SIGSAK) + case TARGET_SIGNAL_SAK: return SIGSAK; +#endif + default: + /* The user might be trying to do "signal SIGSAK" where this system + doesn't have SIGSAK. */ + warning ("Signal %s does not exist on this system.\n", + target_signal_to_name (oursig)); + return 0; + } +} + +/* Helper function for child_wait and the Lynx derivatives of child_wait. + HOSTSTATUS is the waitstatus from wait() or the equivalent; store our + translation of that in OURSTATUS. */ +void +store_waitstatus (ourstatus, hoststatus) + struct target_waitstatus *ourstatus; + int hoststatus; +{ +#ifdef CHILD_SPECIAL_WAITSTATUS + /* CHILD_SPECIAL_WAITSTATUS should return nonzero and set *OURSTATUS + if it wants to deal with hoststatus. */ + if (CHILD_SPECIAL_WAITSTATUS (ourstatus, hoststatus)) + return; +#endif + + if (WIFEXITED (hoststatus)) + { + ourstatus->kind = TARGET_WAITKIND_EXITED; + ourstatus->value.integer = WEXITSTATUS (hoststatus); + } + else if (!WIFSTOPPED (hoststatus)) + { + ourstatus->kind = TARGET_WAITKIND_SIGNALLED; + ourstatus->value.sig = target_signal_from_host (WTERMSIG (hoststatus)); + } + else + { + ourstatus->kind = TARGET_WAITKIND_STOPPED; + ourstatus->value.sig = target_signal_from_host (WSTOPSIG (hoststatus)); + } +} + + /* Convert a normal process ID to a string. Returns the string in a static buffer. */ |