From 16d72e1e9b8dc9cff2f54b8d6ed15f00895f9501 Mon Sep 17 00:00:00 2001 From: jkh Date: Fri, 30 Dec 1994 23:27:33 +0000 Subject: [PATCH] Hurrah! Let the champagne flow, the olive oil barrel be opened and the wild, slippery orgy commence! Gary Jennejohn, too studly for his own good, has finally come through with the new, improved gdb 4.13. This gdb features: o kgdb support - if this works (and I urge folks to test it), we can finally purge the old and hateful version of kgdb from our source tree. o attach/detach support. See comments in README.FreeBSD for more details. o Well, it's newer. Our previous version was 4.11. Comments and flames to gj, of course! :-) Thanks, Gary. Much appreciated. The previous state of gdb/kgdb has been a thorn in all of our sides for some time.. Submitted by: gj --- gnu/usr.bin/binutils/gdb/Makefile | 31 +- gnu/usr.bin/binutils/gdb/gdb.1 | 2 +- gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c | 375 +- gnu/usr.bin/binutils/gdb/i386/nm.h | 56 + gnu/usr.bin/binutils/gdb/i386/tm.h | 2 +- gnu/usr.bin/binutils/gdb/i386/version.c | 6 +- gnu/usr.bin/binutils/gdb/i386/xm.h | 4 - gnu/usr.bin/gdb/README.FreeBSD | 33 +- gnu/usr.bin/gdb/VERSION | 2 +- gnu/usr.bin/gdb/bfd/Makefile | 17 +- gnu/usr.bin/gdb/bfd/README.FreeBSD | 7 +- gnu/usr.bin/gdb/bfd/VERSION | 2 +- gnu/usr.bin/gdb/bfd/aout-target.h | 296 +- gnu/usr.bin/gdb/bfd/aout32.c | 2 +- gnu/usr.bin/gdb/bfd/aoutx.h | 4780 ++++++++++++++----- gnu/usr.bin/gdb/bfd/archive.c | 1894 ++++---- gnu/usr.bin/gdb/bfd/archures.c | 196 +- gnu/usr.bin/gdb/bfd/bfd.c | 548 ++- gnu/usr.bin/gdb/bfd/bfd.h | 1234 +++-- gnu/usr.bin/gdb/bfd/cache.c | 368 +- gnu/usr.bin/gdb/bfd/coffgen.c | 872 ++-- gnu/usr.bin/gdb/bfd/core.c | 28 +- gnu/usr.bin/gdb/bfd/cpu-i386.c | 3 +- gnu/usr.bin/gdb/bfd/ctor.c | 63 +- gnu/usr.bin/gdb/bfd/ecoff.c | 3961 +++++++++------ gnu/usr.bin/gdb/bfd/elf.c | 225 +- gnu/usr.bin/gdb/bfd/format.c | 170 +- gnu/usr.bin/gdb/bfd/freebsd386.c | 1 + gnu/usr.bin/gdb/bfd/init.c | 27 +- gnu/usr.bin/gdb/bfd/libaout.h | 259 +- gnu/usr.bin/gdb/bfd/libbfd.c | 500 +- gnu/usr.bin/gdb/bfd/libbfd.h | 313 +- gnu/usr.bin/gdb/bfd/libcoff.h | 81 +- gnu/usr.bin/gdb/bfd/libecoff.h | 302 +- gnu/usr.bin/gdb/bfd/libelf.h | 462 +- gnu/usr.bin/gdb/bfd/opncls.c | 206 +- gnu/usr.bin/gdb/bfd/reloc.c | 1222 +++-- gnu/usr.bin/gdb/bfd/section.c | 590 ++- gnu/usr.bin/gdb/bfd/srec.c | 1248 ++--- gnu/usr.bin/gdb/bfd/stab-syms.c | 35 +- gnu/usr.bin/gdb/bfd/syms.c | 236 +- gnu/usr.bin/gdb/bfd/sysdep.h | 3 +- gnu/usr.bin/gdb/bfd/targets.c | 599 ++- gnu/usr.bin/gdb/bfd/trad-core.c | 142 +- gnu/usr.bin/gdb/gdb/Makefile | 31 +- gnu/usr.bin/gdb/gdb/ansidecl.h | 2 + gnu/usr.bin/gdb/gdb/aout/aout64.h | 94 +- gnu/usr.bin/gdb/gdb/aout/ar.h | 10 +- gnu/usr.bin/gdb/gdb/aout/stab.def | 8 +- gnu/usr.bin/gdb/gdb/blockframe.c | 53 +- gnu/usr.bin/gdb/gdb/breakpoint.c | 1343 ++++-- gnu/usr.bin/gdb/gdb/breakpoint.h | 71 +- gnu/usr.bin/gdb/gdb/buildsym.c | 20 +- gnu/usr.bin/gdb/gdb/c-lang.c | 50 +- gnu/usr.bin/gdb/gdb/c-lang.h | 11 +- gnu/usr.bin/gdb/gdb/c-typeprint.c | 58 +- gnu/usr.bin/gdb/gdb/c-valprint.c | 149 +- gnu/usr.bin/gdb/gdb/ch-lang.c | 42 +- gnu/usr.bin/gdb/gdb/ch-lang.h | 17 +- gnu/usr.bin/gdb/gdb/ch-typeprint.c | 130 +- gnu/usr.bin/gdb/gdb/ch-valprint.c | 289 +- gnu/usr.bin/gdb/gdb/coff/ecoff.h | 235 +- gnu/usr.bin/gdb/gdb/coff/internal.h | 18 +- gnu/usr.bin/gdb/gdb/coff/sym.h | 6 +- gnu/usr.bin/gdb/gdb/coff/symconst.h | 3 +- gnu/usr.bin/gdb/gdb/coffread.c | 222 +- gnu/usr.bin/gdb/gdb/command.c | 93 +- gnu/usr.bin/gdb/gdb/command.h | 17 +- gnu/usr.bin/gdb/gdb/complaints.c | 2 +- gnu/usr.bin/gdb/gdb/core.c | 62 +- gnu/usr.bin/gdb/gdb/coredep.c | 15 +- gnu/usr.bin/gdb/gdb/corelow.c | 29 +- gnu/usr.bin/gdb/gdb/cp-valprint.c | 112 +- gnu/usr.bin/gdb/gdb/dbxread.c | 586 ++- gnu/usr.bin/gdb/gdb/defs.h | 323 +- gnu/usr.bin/gdb/gdb/demangle.c | 35 +- gnu/usr.bin/gdb/gdb/demangle.h | 3 + gnu/usr.bin/gdb/gdb/dis-asm.h | 11 +- gnu/usr.bin/gdb/gdb/dis-buf.c | 3 +- gnu/usr.bin/gdb/gdb/dwarfread.c | 34 +- gnu/usr.bin/gdb/gdb/elf/common.h | 45 +- gnu/usr.bin/gdb/gdb/elf/internal.h | 49 +- gnu/usr.bin/gdb/gdb/elfread.c | 198 +- gnu/usr.bin/gdb/gdb/environ.c | 30 +- gnu/usr.bin/gdb/gdb/eval.c | 91 +- gnu/usr.bin/gdb/gdb/exec.c | 77 +- gnu/usr.bin/gdb/gdb/expprint.c | 35 +- gnu/usr.bin/gdb/gdb/expression.h | 7 +- gnu/usr.bin/gdb/gdb/findvar.c | 385 +- gnu/usr.bin/gdb/gdb/fork-child.c | 102 +- gnu/usr.bin/gdb/gdb/frame.h | 4 +- gnu/usr.bin/gdb/gdb/freebsd-nat.c | 375 +- gnu/usr.bin/gdb/gdb/gdb.1 | 2 +- gnu/usr.bin/gdb/gdb/gdbcore.h | 16 +- gnu/usr.bin/gdb/gdb/gdbtypes.c | 325 +- gnu/usr.bin/gdb/gdb/gdbtypes.h | 93 +- gnu/usr.bin/gdb/gdb/i386-dis.c | 23 +- gnu/usr.bin/gdb/gdb/i386-pinsn.c | 2 +- gnu/usr.bin/gdb/gdb/i386-tdep.c | 113 +- gnu/usr.bin/gdb/gdb/infcmd.c | 223 +- gnu/usr.bin/gdb/gdb/inferior.h | 45 +- gnu/usr.bin/gdb/gdb/inflow.c | 117 +- gnu/usr.bin/gdb/gdb/infptrace.c | 102 +- gnu/usr.bin/gdb/gdb/infrun.c | 797 ++-- gnu/usr.bin/gdb/gdb/inftarg.c | 122 +- gnu/usr.bin/gdb/gdb/init.c | 81 +- gnu/usr.bin/gdb/gdb/language.c | 161 +- gnu/usr.bin/gdb/gdb/language.h | 26 +- gnu/usr.bin/gdb/gdb/m2-lang.c | 32 +- gnu/usr.bin/gdb/gdb/m2-lang.h | 4 +- gnu/usr.bin/gdb/gdb/m2-typeprint.c | 4 +- gnu/usr.bin/gdb/gdb/m2-valprint.c | 4 +- gnu/usr.bin/gdb/gdb/main.c | 2394 +--------- gnu/usr.bin/gdb/gdb/maint.c | 52 +- gnu/usr.bin/gdb/gdb/minsyms.c | 151 +- gnu/usr.bin/gdb/gdb/mipsread.c | 3854 ++------------- gnu/usr.bin/gdb/gdb/nlmread.c | 70 +- gnu/usr.bin/gdb/gdb/nm.h | 56 + gnu/usr.bin/gdb/gdb/objfiles.c | 251 +- gnu/usr.bin/gdb/gdb/objfiles.h | 50 +- gnu/usr.bin/gdb/gdb/obstack.h | 149 +- gnu/usr.bin/gdb/gdb/parse.c | 71 +- gnu/usr.bin/gdb/gdb/parser-defs.h | 62 +- gnu/usr.bin/gdb/gdb/partial-stab.h | 187 +- gnu/usr.bin/gdb/gdb/printcmd.c | 458 +- gnu/usr.bin/gdb/gdb/regex.c | 109 +- gnu/usr.bin/gdb/gdb/regex.h | 2 + gnu/usr.bin/gdb/gdb/remote-utils.c | 139 +- gnu/usr.bin/gdb/gdb/remote-utils.h | 9 +- gnu/usr.bin/gdb/gdb/remote.c | 786 +-- gnu/usr.bin/gdb/gdb/ser-unix.c | 179 +- gnu/usr.bin/gdb/gdb/serial.c | 16 +- gnu/usr.bin/gdb/gdb/serial.h | 9 +- gnu/usr.bin/gdb/gdb/source.c | 203 +- gnu/usr.bin/gdb/gdb/stabsread.c | 684 ++- gnu/usr.bin/gdb/gdb/stabsread.h | 40 +- gnu/usr.bin/gdb/gdb/stack.c | 257 +- gnu/usr.bin/gdb/gdb/symfile.c | 333 +- gnu/usr.bin/gdb/gdb/symfile.h | 52 +- gnu/usr.bin/gdb/gdb/symmisc.c | 335 +- gnu/usr.bin/gdb/gdb/symtab.c | 522 +- gnu/usr.bin/gdb/gdb/symtab.h | 136 +- gnu/usr.bin/gdb/gdb/target.c | 577 ++- gnu/usr.bin/gdb/gdb/target.h | 206 +- gnu/usr.bin/gdb/gdb/terminal.h | 2 - gnu/usr.bin/gdb/gdb/thread.c | 131 +- gnu/usr.bin/gdb/gdb/tm-i386v.h | 25 +- gnu/usr.bin/gdb/gdb/tm.h | 2 +- gnu/usr.bin/gdb/gdb/typeprint.c | 18 +- gnu/usr.bin/gdb/gdb/typeprint.h | 2 +- gnu/usr.bin/gdb/gdb/utils.c | 437 +- gnu/usr.bin/gdb/gdb/valarith.c | 211 +- gnu/usr.bin/gdb/gdb/valops.c | 381 +- gnu/usr.bin/gdb/gdb/valprint.c | 276 +- gnu/usr.bin/gdb/gdb/valprint.h | 10 +- gnu/usr.bin/gdb/gdb/value.h | 296 +- gnu/usr.bin/gdb/gdb/values.c | 334 +- gnu/usr.bin/gdb/gdb/version.c | 6 +- gnu/usr.bin/gdb/gdb/xm.h | 4 - gnu/usr.bin/gdb/libiberty/Makefile | 2 +- gnu/usr.bin/gdb/libiberty/README.FreeBSD | 7 +- gnu/usr.bin/gdb/libiberty/argv.c | 12 + gnu/usr.bin/gdb/libiberty/basename.c | 3 + gnu/usr.bin/gdb/libiberty/concat.c | 65 +- gnu/usr.bin/gdb/libiberty/cplus-dem.c | 415 +- gnu/usr.bin/gdb/libiberty/fdmatch.c | 2 + gnu/usr.bin/gdb/libiberty/getopt.c | 205 +- gnu/usr.bin/gdb/libiberty/getopt1.c | 7 + gnu/usr.bin/gdb/libiberty/obstack.c | 43 +- gnu/usr.bin/gdb/libiberty/spaces.c | 8 +- gnu/usr.bin/gdb/libiberty/strerror.c | 290 +- gnu/usr.bin/gdb/libiberty/strsignal.c | 149 +- gnu/usr.bin/gdb/libiberty/xmalloc.c | 47 +- gnu/usr.bin/gdb/mmalloc/README.FreeBSD | 7 +- gnu/usr.bin/gdb/mmalloc/mmtrace.c | 12 +- 175 files changed, 26350 insertions(+), 18738 deletions(-) diff --git a/gnu/usr.bin/binutils/gdb/Makefile b/gnu/usr.bin/binutils/gdb/Makefile index 70f0e0c0de74..3e481ce39964 100644 --- a/gnu/usr.bin/binutils/gdb/Makefile +++ b/gnu/usr.bin/binutils/gdb/Makefile @@ -1,19 +1,23 @@ PROG = gdb BINDIR= /usr/bin CLEANFILES+= y.tab.h c-exp.tab.c ch-exp.tab.c m2-exp.tab.c -SRCS = main.c blockframe.c breakpoint.c findvar.c stack.c thread.c \ - source.c values.c eval.c valops.c valarith.c valprint.c printcmd.c \ - symtab.c symfile.c symmisc.c infcmd.c infrun.c command.c utils.c \ - expprint.c environ.c gdbtypes.c copying.c i386-tdep.c i386-pinsn.c \ - freebsd-solib.c ser-unix.c exec.c fork-child.c infptrace.c inftarg.c \ - corelow.c coredep.c freebsd-nat.c remote.c dcache.c remote-utils.c \ - mem-break.c target.c putenv.c parse.c language.c buildsym.c \ - objfiles.c minsyms.c maint.c demangle.c dbxread.c coffread.c \ - elfread.c dwarfread.c mipsread.c stabsread.c core.c c-lang.c \ - ch-lang.c m2-lang.c complaints.c typeprint.c c-typeprint.c \ - ch-typeprint.c m2-typeprint.c c-valprint.c cp-valprint.c ch-valprint.c \ - m2-valprint.c nlmread.c serial.c inflow.c regex.c init.c \ - c-exp.tab.c ch-exp.tab.c m2-exp.tab.c version.c i386-dis.c dis-buf.c +SRCS = annotate.c blockframe.c breakpoint.c buildsym.c c-lang.c \ + c-typeprint.c c-valprint.c ch-lang.c ch-typeprint.c \ + ch-valprint.c coffread.c command.c complaints.c copying.c core.c \ + coredep.c corelow.c cp-valprint.c \ + dcache.c dbxread.c demangle.c disassemble.c dis-buf.c dwarfread.c \ + elfread.c environ.c eval.c exec.c expprint.c \ + findvar.c fork-child.c freebsd-nat.c gdbtypes.c i386-dis.c \ + i386-pinsn.c i386-tdep.c infcmd.c inflow.c infptrace.c \ + infrun.c inftarg.c init.c kcorelow.c language.c \ + m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \ + mem-break.c minsyms.c objfiles.c parse.c \ + printcmd.c regex.c remote.c remote-utils.c solib.c source.c \ + stabsread.c stack.c symfile.c symmisc.c \ + symtab.c target.c thread.c top.c \ + typeprint.c utils.c valarith.c valops.c \ + valprint.c values.c version.c serial.c ser-unix.c mdebugread.c\ + c-exp.tab.c ch-exp.tab.c m2-exp.tab.c c-exp.tab.c: $(.CURDIR)/c-exp.y yacc -d -p c_ $(.CURDIR)/c-exp.y @@ -40,7 +44,6 @@ m2-exp.tab.c: $(.CURDIR)/m2-exp.y mv m2-exp.new ./m2-exp.tab.c - CFLAGS+= -I$(.CURDIR)/. -I${DESTDIR}/usr/include/readline -I$(.CURDIR)/../bfd DPADD+= ${LIBREADLINE} ${LIBTERMCAP} LDADD+= -lreadline -ltermcap diff --git a/gnu/usr.bin/binutils/gdb/gdb.1 b/gnu/usr.bin/binutils/gdb/gdb.1 index ccb216ee88f7..ee14f7073451 100644 --- a/gnu/usr.bin/binutils/gdb/gdb.1 +++ b/gnu/usr.bin/binutils/gdb/gdb.1 @@ -1,6 +1,6 @@ .\" Copyright (c) 1991 Free Software Foundation .\" See section COPYING for conditions for redistribution -.\" $Id: gdb.1,v 1.1.1.1 1993/10/30 21:59:13 jkh Exp $ +.\" $Id: gdb.1,v 1.1 1994/01/28 12:39:43 pk Exp $ .TH gdb 1 "4nov1991" "GNU Tools" "GNU Tools" .SH NAME gdb \- The GNU Debugger diff --git a/gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c b/gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c index deb68ebb9453..ba742a359c7e 100644 --- a/gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c +++ b/gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c @@ -15,10 +15,20 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: freebsd-nat.c,v 1.3 1994/05/18 12:43:13 pk Exp $ +*/ + +#include +#include +#include +#include +#include +#include +#include #include "defs.h" -#include /* this table must line up with REGISTER_NAMES in tm-i386.h */ /* symbols like 'tEAX' come from */ @@ -28,14 +38,7 @@ static int tregmap[] = tESP, tEBP, tESI, tEDI, tEIP, tEFLAGS, tCS, tSS }; -#ifdef sEAX -static int sregmap[] = -{ - sEAX, sECX, sEDX, sEBX, - sESP, sEBP, sESI, sEDI, - sEIP, sEFLAGS, sCS, sSS -}; -#endif + /* blockend is the value of u.u_ar0, and points to the place where ES is stored. */ @@ -44,45 +47,14 @@ i386_register_u_addr (blockend, regnum) int blockend; int regnum; { - /* The following condition is a kludge to get at the proper register map - depending upon the state of pcb_flag. - The proper condition would be - if (u.u_pcb.pcb_flag & FM_TRAP) - but that would require a ptrace call here and wouldn't work - for corefiles. */ - -#ifdef sEAX - if (blockend < 0x1fcc) return (blockend + 4 * tregmap[regnum]); - else - return (blockend + 4 * sregmap[regnum]); -#else - return (blockend + 4 * tregmap[regnum]); -#endif } -#ifdef FLOAT_INFO -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#define curpcb Xcurpcb /* XXX avoid leaking declaration from pcb.h */ -#include -#undef curpcb -#include -#include -#include #define fpstate save87 #define U_FPSTATE(u) u.u_pcb.pcb_savefpu +static void i387_to_double (from, to) char *from; char *to; @@ -113,6 +85,7 @@ i387_to_double (from, to) asm ("popl %eax"); /* flush saved copy */ } +static void double_to_i387 (from, to) char *from; char *to; @@ -209,7 +182,7 @@ print_387_status_word (status) printf ("top %d\n", (status >> 11) & 7); } -static +static void print_387_status (status, ep) unsigned short status; struct env387 *ep; @@ -271,6 +244,7 @@ print_387_status (status, ep) } } +void i386_float_info () { struct user u; /* just for address computations */ @@ -320,4 +294,319 @@ i386_float_info () print_387_status (0, (struct env387 *)buf); } +void +clear_regs() +{ + return; +} + +#ifdef KERNEL_DEBUG +#include +#include +#include +#include + +#include +#include + +#include +#include + +#define KERNOFF ((unsigned)KERNBASE) +#define INKERNEL(x) ((x) >= KERNOFF) + +static CORE_ADDR sbr; +static CORE_ADDR curpcb; +static CORE_ADDR kstack; +static int found_pcb; +static int devmem; +static int kfd; +static struct pcb pcb; +int read_pcb (int, CORE_ADDR); +static CORE_ADDR kvtophys (int, CORE_ADDR); +static physrd(int, u_int, char*, int); + +extern CORE_ADDR ksym_lookup(const char *); + +/* substitutes for the stuff in libkvm which doesn't work */ +/* most of this was taken from the old kgdb */ + +/* we don't need all this stuff, but the call should look the same */ +kvm_open (efile, cfile, sfile, perm, errout) +char *efile; +char *cfile; +void *sfile; +int perm; +int errout; +{ + struct stat stb; + CORE_ADDR addr; + int cfd; + + if ((cfd = open(cfile, perm, 0)) < 0) + return (cfd); + + fstat(cfd, &stb); + if ((stb.st_mode & S_IFMT) == S_IFCHR && stb.st_rdev == makedev(2, 0)) { + devmem = 1; + kfd = open ("/dev/kmem", perm, 0); + } + + physrd(cfd, ksym_lookup("IdlePTD") - KERNOFF, (char*)&sbr, sizeof sbr); + printf("IdlePTD %x\n", sbr); + curpcb = ksym_lookup("curpcb") - KERNOFF; + physrd(cfd, curpcb, (char*)&curpcb, sizeof curpcb); + kstack = ksym_lookup("kstack"); + + found_pcb = 1; /* for vtophys */ + if (!devmem) + read_pcb(cfd, ksym_lookup("dumppcb") - KERNOFF); + else + read_pcb(cfd, kvtophys(cfd, kstack)); + + return (cfd); +} + +kvm_close (fd) +{ + return (close (fd)); +} + +kvm_write(core_kd, memaddr, myaddr, len) +CORE_ADDR memaddr; +char *myaddr; +{ + int cc; + + if (devmem) { + if (kfd > 0) { + /* + * Just like kvm_read, only we write. + */ + errno = 0; + if (lseek(kfd, (off_t)memaddr, 0) < 0 && errno != 0) { + error("kvm_write:invalid address (%x)", memaddr); + return (0); + } + cc = write(kfd, myaddr, len); + if (cc < 0) { + error("kvm_write:write failed"); + return (0); + } else if (cc < len) + error("kvm_write:short write"); + return (cc); + } else + return (0); + } else { + printf("kvm_write not implemented for dead kernels\n"); + return (0); + } + /* NOTREACHED */ +} + +kvm_read(core_kd, memaddr, myaddr, len) +CORE_ADDR memaddr; +char *myaddr; +{ + return (kernel_core_file_hook (core_kd, memaddr, myaddr, len)); +} + +kvm_uread(core_kd, p, memaddr, myaddr, len) +register struct proc *p; +CORE_ADDR memaddr; +char *myaddr; +{ + register char *cp; + char procfile[MAXPATHLEN]; + ssize_t amount; + int fd; + + if (devmem) { + cp = myaddr; + + sprintf(procfile, "/proc/%d/mem", p->p_pid); + fd = open(procfile, O_RDONLY, 0); + + if (fd < 0) { + error("cannot open %s", procfile); + close(fd); + return (0); + } + + while (len > 0) { + if (lseek(fd, memaddr, 0) == -1 && errno != 0) { + error("invalid address (%x) in %s", + memaddr, procfile); + break; + } + amount = read(fd, cp, len); + if (amount < 0) { + error("error reading %s", procfile); + break; + } + cp += amount; + memaddr += amount; + len -= amount; + } + + close(fd); + return (ssize_t)(cp - myaddr); + } else { + return (kernel_core_file_hook (core_kd, memaddr, myaddr, len)); + } +} + +static +physrd(cfd, addr, dat, len) +u_int addr; +char *dat; +{ + if (lseek(cfd, (off_t)addr, L_SET) == -1) + return (-1); + return (read(cfd, dat, len)); +} + +static CORE_ADDR +kvtophys (fd, addr) +CORE_ADDR addr; +{ + CORE_ADDR v; + struct pte pte; + static CORE_ADDR PTD = -1; + CORE_ADDR current_ptd; + + /*if (devmem && kfd > 0) + return (addr); + /* + * If we're looking at the kernel stack, + * munge the address to refer to the user space mapping instead; + * that way we get the requested process's kstack, not the running one. + */ + if (addr >= kstack && addr < kstack + ctob(UPAGES)) + addr = (addr - kstack) + curpcb; + + /* + * We may no longer have a linear system page table... + * + * Here's the scoop. IdlePTD contains the physical address + * of a page table directory that always maps the kernel. + * IdlePTD is in memory that is mapped 1-to-1, so we can + * find it easily given its 'virtual' address from ksym_lookup(). + * For hysterical reasons, the value of IdlePTD is stored in sbr. + * + * To look up a kernel address, we first convert it to a 1st-level + * address and look it up in IdlePTD. This gives us the physical + * address of a page table page; we extract the 2nd-level part of + * VA and read the 2nd-level pte. Finally, we add the offset part + * of the VA into the physical address from the pte and return it. + * + * User addresses are a little more complicated. If we don't have + * a current PCB from read_pcb(), we use PTD, which is the (fixed) + * virtual address of the current ptd. Since it's NOT in 1-to-1 + * kernel space, we must look it up using IdlePTD. If we do have + * a pcb, we get the ptd from pcb_ptd. + */ + + if (INKERNEL(addr)) + current_ptd = sbr; + else if (found_pcb == 0) { + if (PTD == -1) + PTD = kvtophys(fd, ksym_lookup("PTD")); + current_ptd = PTD; + } else + current_ptd = pcb.pcb_ptd; + + /* + * Read the first-level page table (ptd). + */ + v = current_ptd + ((unsigned)addr >> PD_SHIFT) * sizeof pte; + if (physrd(fd, v, (char *)&pte, sizeof pte) < 0 || pte.pg_v == 0) + return (~0); + + /* + * Read the second-level page table. + */ + v = i386_ptob(pte.pg_pfnum) + ((addr&PT_MASK) >> PG_SHIFT) * sizeof pte; + if (physrd(fd, v, (char *) &pte, sizeof(pte)) < 0 || pte.pg_v == 0) + return (~0); + + addr = i386_ptob(pte.pg_pfnum) + (addr & PGOFSET); +#if 0 + printf("vtophys(%x) -> %x\n", oldaddr, addr); #endif + return (addr); +} + +read_pcb (fd, uaddr) +CORE_ADDR uaddr; +{ + int i; + int *pcb_regs = (int *)&pcb; + int eip; + + if (physrd(fd, uaddr, (char *)&pcb, sizeof pcb) < 0) { + error("cannot read pcb at %x\n", uaddr); + return (-1); + } + printf("current pcb at %x\n", uaddr); + + /* + * get the register values out of the sys pcb and + * store them where `read_register' will find them. + */ + for (i = 0; i < 8; ++i) + supply_register(i, &pcb_regs[i+10]); + supply_register(8, &pcb_regs[8]); /* eip */ + supply_register(9, &pcb_regs[9]); /* eflags */ + for (i = 10; i < 13; ++i) /* cs, ss, ds */ + supply_register(i, &pcb_regs[i+9]); + supply_register(13, &pcb_regs[18]); /* es */ + for (i = 14; i < 16; ++i) /* fs, gs */ + supply_register(i, &pcb_regs[i+8]); + +#if 0 /* doesn't work ??? */ + /* Hmm... */ + if (target_read_memory(pcb_regs[5+10]+4, &eip, sizeof eip, 0)) + error("Cannot read PC."); + supply_register(8, &eip); /* eip */ +#endif + + /* XXX 80387 registers? */ +} + +/* + * read len bytes from kernel virtual address 'addr' into local + * buffer 'buf'. Return numbert of bytes if read ok, 0 otherwise. On read + * errors, portion of buffer not read is zeroed. + */ +kernel_core_file_hook(fd, addr, buf, len) + CORE_ADDR addr; + char *buf; + int len; +{ + int i; + CORE_ADDR paddr; + register char *cp; + int cc; + + cp = buf; + + while (len > 0) { + paddr = kvtophys(fd, addr); + if (paddr == ~0) { + bzero(buf, len); + break; + } + /* we can't read across a page boundary */ + i = min(len, NBPG - (addr & PGOFSET)); + if ((cc = physrd(fd, paddr, cp, i)) <= 0) { + bzero(cp, len); + return (cp - buf); + } + cp += cc; + addr += cc; + len -= cc; + } + return (cp - buf); +} +#endif /* KERNEL_DEBUG */ diff --git a/gnu/usr.bin/binutils/gdb/i386/nm.h b/gnu/usr.bin/binutils/gdb/i386/nm.h index a7af00f33d87..65c73372a038 100644 --- a/gnu/usr.bin/binutils/gdb/i386/nm.h +++ b/gnu/usr.bin/binutils/gdb/i386/nm.h @@ -40,5 +40,61 @@ extern int i386_register_u_addr PARAMS ((int, int)); #define PTRACE_ARG3_TYPE char* +#define ATTACH_DETACH +#define KERNEL_DEBUG + +/* make structure definitions match up with those expected in solib.c */ + +#define link_object sod +#define lo_name sod_name +#define lo_library sod_library +#define lo_unused sod_reserved +#define lo_major sod_major +#define lo_minor sod_minor +#define lo_next sod_next + +#define link_map so_map +#define lm_addr som_addr +#define lm_name som_path +#define lm_next som_next +#define lm_lop som_sod +#define lm_lob som_sodbase +#define lm_rwt som_write +#define lm_ld som_dynamic +#define lm_lpd som_spd + +#define link_dynamic_2 section_dispatch_table +#define ld_loaded sdt_loaded +#define ld_need sdt_sods +#define ld_rules sdt_filler1 +#define ld_got sdt_got +#define ld_plt sdt_plt +#define ld_rel sdt_rel +#define ld_hash sdt_hash +#define ld_stab sdt_nzlist +#define ld_stab_hash sdt_filler2 +#define ld_buckets sdt_buckets +#define ld_symbols sdt_strings +#define ld_symb_size sdt_str_sz +#define ld_text sdt_text_sz +#define ld_plt_sz sdt_plt_sz + +#define rtc_symb rt_symbol +#define rtc_sp rt_sp +#define rtc_next rt_next + +#define ld_debug so_debug +#define ldd_version dd_version +#define ldd_in_debugger dd_in_debugger +#define ldd_sym_loaded dd_sym_loaded +#define ldd_bp_addr dd_bpt_addr +#define ldd_bp_inst dd_bpt_shadow +#define ldd_cp dd_cc + +#define link_dynamic _dynamic +#define ld_version d_version +#define ldd d_debug +#define ld_un d_un +#define ld_2 d_sdt #endif /* NM_FREEBSD_H */ diff --git a/gnu/usr.bin/binutils/gdb/i386/tm.h b/gnu/usr.bin/binutils/gdb/i386/tm.h index 25b66c709dee..a33a6685c822 100644 --- a/gnu/usr.bin/binutils/gdb/i386/tm.h +++ b/gnu/usr.bin/binutils/gdb/i386/tm.h @@ -68,7 +68,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Offset to saved PC in sigcontext, from . */ #define SIGCONTEXT_PC_OFFSET 20 -#undef FRAME_SAVED_PC(FRAME) +#undef FRAME_SAVED_PC #define FRAME_SAVED_PC(FRAME) \ (((FRAME)->signal_handler_caller \ ? sigtramp_saved_pc (FRAME) \ diff --git a/gnu/usr.bin/binutils/gdb/i386/version.c b/gnu/usr.bin/binutils/gdb/i386/version.c index d32e958a2dd1..43f63d2c71ae 100644 --- a/gnu/usr.bin/binutils/gdb/i386/version.c +++ b/gnu/usr.bin/binutils/gdb/i386/version.c @@ -1,3 +1,3 @@ -char *version = "4.11"; -char *host_canonical = "i386-unknown-freebsd"; -char *target_canonical = "i386-unknown-freebsd"; +char *version = "4.13"; +char *host_name = "i386-unknown-freebsd"; +char *target_name = "i386-unknown-freebsd"; diff --git a/gnu/usr.bin/binutils/gdb/i386/xm.h b/gnu/usr.bin/binutils/gdb/i386/xm.h index fe5fe7601fda..6a71227aec77 100644 --- a/gnu/usr.bin/binutils/gdb/i386/xm.h +++ b/gnu/usr.bin/binutils/gdb/i386/xm.h @@ -26,8 +26,4 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define PSIGNAL_IN_SIGNAL_H -/* Get rid of any system-imposed stack limit if possible. */ - -#define SET_STACK_LIMIT_HUGE - #define HAVE_TERMIOS diff --git a/gnu/usr.bin/gdb/README.FreeBSD b/gnu/usr.bin/gdb/README.FreeBSD index 75a30b2cb431..d0a0aa6352b6 100644 --- a/gnu/usr.bin/gdb/README.FreeBSD +++ b/gnu/usr.bin/gdb/README.FreeBSD @@ -1,15 +1,24 @@ -This is a greatly pared down version of GDB-4.12 for FreeBSD 1.1.5 that -supports debugging of shared executables and the new a.out format. +This is a greatly pared down version of GDB-4.13 for FreeBSD 2.0. It +also has support for kernel debugging a la the dearly beloved kgdb. +Kernel debugging is enabled either using the -k flag or by linking gdb +to kgdb and invoking it as kgdb. Linking is left up to the discretion +of the user. -I've collapsed some of the directories and removed lots of files from others. -All that's included is those necessary to compile on FreeBSD 1.1.5, this was -to keep the replacement for GDB-3 compact since none of the multiple -architecture stuff is used. All the documentation has been put in the doc/ -directory. +The kernel debugging needs testing, I didn't have any useful crash dumps +available. The new gdb produced the same output as the old kgdb with +what I had available for testing, though. -A full port of each library will probably be done for FreeBSD 2.0 and -included as system libraries so that other build tools can share them. -At that time a more complete port of GDB-4 will be done that allows -configuration for different systems and uses the full libraries. +There's rudimentary support for attaching to a running process and +debugging (attach/detach commands in gdb). This works best if the +program being debugged was compiled with -g, of course. Be aware that +detaching frequently results in the death of the process being debugged +(Trace/BKPT Trap). Haven't figured what's going on yet. Use this at your +own risk! I had to stop somewhere for the release :-) -paul@freefall.cdrom.com +Note that a plain vanilla gdb-4.13 without kernal debugging or +attach/detach support can be made by removing the + #define ATTACH_DETACH + #define KERNEL_DEBUG +lines from gdb/nm.h. + +gj@freebsd.org diff --git a/gnu/usr.bin/gdb/VERSION b/gnu/usr.bin/gdb/VERSION index b849ff8ebf1f..8c3a0151b80f 100644 --- a/gnu/usr.bin/gdb/VERSION +++ b/gnu/usr.bin/gdb/VERSION @@ -1 +1 @@ -4.11 +4.13 diff --git a/gnu/usr.bin/gdb/bfd/Makefile b/gnu/usr.bin/gdb/bfd/Makefile index ea29afed0d86..24322afcabfb 100644 --- a/gnu/usr.bin/gdb/bfd/Makefile +++ b/gnu/usr.bin/gdb/bfd/Makefile @@ -1,8 +1,17 @@ LIB = bfd -SRCS = archive.c archures.c bfd.c cache.c coffgen.c core.c ctor.c \ - format.c init.c libbfd.c opncls.c reloc.c seclet.c section.c syms.c \ - targets.c ecoff.c elf.c srec.c freebsd386.c aout32.c stab-syms.c \ - cpu-i386.c trad-core.c + +SRCS = libbfd.c opncls.c bfd.c archive.c targets.c cache.c \ + archures.c coff-i386.c aout32.c \ + srec.c \ + ecoff.c ecofflink.c \ + coffgen.c format.c \ + section.c core.c syms.c stab-syms.c reloc.c init.c ctor.c \ + trad-core.c \ + i386aout.c \ + freebsd386.c \ + cpu-i386.c \ + elf.c elf32.c elf32-i386.c \ + hash.c linker.c CFLAGS+= -I$(.CURDIR)/. -I$(.CURDIR)/../gdb/. CFLAGS+= -DDEFAULT_VECTOR=freebsd386_vec -DSELECT_VECS='&freebsd386_vec' \ diff --git a/gnu/usr.bin/gdb/bfd/README.FreeBSD b/gnu/usr.bin/gdb/bfd/README.FreeBSD index 204119c1af74..033fa005db07 100644 --- a/gnu/usr.bin/gdb/bfd/README.FreeBSD +++ b/gnu/usr.bin/gdb/bfd/README.FreeBSD @@ -1,7 +1,4 @@ This is a greatly pared down libbfd directory. Only what's required to build -gdb-4.12 on FreeBSD was kept. +gdb-4.13 on FreeBSD 2.0 was kept. -This is temporary. In FreeBSD 2.0 a fully ported libbfd will likely appear -as a system library for use by all the build tools. - -paul@freefall.cdrom.com +gj@freebsd.org diff --git a/gnu/usr.bin/gdb/bfd/VERSION b/gnu/usr.bin/gdb/bfd/VERSION index 8bbe6cf74a1e..ae7202bf99b4 100644 --- a/gnu/usr.bin/gdb/bfd/VERSION +++ b/gnu/usr.bin/gdb/bfd/VERSION @@ -1 +1 @@ -2.2 +cygnus-2.3 diff --git a/gnu/usr.bin/gdb/bfd/aout-target.h b/gnu/usr.bin/gdb/bfd/aout-target.h index 65a22fff9b04..fc8d592e4e9c 100644 --- a/gnu/usr.bin/gdb/bfd/aout-target.h +++ b/gnu/usr.bin/gdb/bfd/aout-target.h @@ -1,5 +1,5 @@ /* Define a target vector and some small routines for a variant of a.out. - Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -27,11 +27,13 @@ extern CONST struct reloc_howto_struct * NAME(aout,reloc_type_lookup) (); /* Set parameters about this a.out file that are machine-dependent. This routine is called from some_aout_object_p just before it returns. */ #ifndef MY_callback -static bfd_target * -DEFUN(MY(callback),(abfd), - bfd *abfd) +static const bfd_target * +MY(callback) (abfd) + bfd *abfd; { struct internal_exec *execp = exec_hdr (abfd); + unsigned int arch_align_power; + unsigned long arch_align; /* Calculate the file positions of the parts of a newly read aout header */ obj_textsec (abfd)->_raw_size = N_TXTSIZE(*execp); @@ -60,6 +62,26 @@ DEFUN(MY(callback),(abfd), bfd_default_set_arch_mach(abfd, DEFAULT_ARCH, 0); #endif + /* Now that we know the architecture, set the alignments of the + sections. This is normally done by NAME(aout,new_section_hook), + but when the initial sections were created the architecture had + not yet been set. However, for backward compatibility, we don't + set the alignment power any higher than as required by the size + of the section. */ + arch_align_power = bfd_get_arch_info (abfd)->section_align_power; + arch_align = 1 << arch_align_power; + if ((BFD_ALIGN (obj_textsec (abfd)->_raw_size, arch_align) + == obj_textsec (abfd)->_raw_size) + && (BFD_ALIGN (obj_datasec (abfd)->_raw_size, arch_align) + == obj_datasec (abfd)->_raw_size) + && (BFD_ALIGN (obj_bsssec (abfd)->_raw_size, arch_align) + == obj_bsssec (abfd)->_raw_size)) + { + obj_textsec (abfd)->alignment_power = arch_align_power; + obj_datasec (abfd)->alignment_power = arch_align_power; + obj_bsssec (abfd)->alignment_power = arch_align_power; + } + /* Don't set sizes now -- can't be sure until we know arch & mach. Sizes get set in set_sizes callback, later. */ #if 0 @@ -79,25 +101,26 @@ DEFUN(MY(callback),(abfd), #ifndef MY_object_p /* Finish up the reading of an a.out file header */ -static bfd_target * -DEFUN(MY(object_p),(abfd), - bfd *abfd) +static const bfd_target * +MY(object_p) (abfd) + bfd *abfd; { struct external_exec exec_bytes; /* Raw exec header from file */ struct internal_exec exec; /* Cleaned-up exec header */ - bfd_target *target; + const bfd_target *target; if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd) != EXEC_BYTES_SIZE) { - bfd_error = wrong_format; + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); return 0; } -#ifdef NO_SWAP_MAGIC - memcpy (&exec.a_info, exec_bytes.e_info, sizeof(exec.a_info)); +#ifdef SWAP_MAGIC + exec.a_info = SWAP_MAGIC (exec_bytes.e_info); #else exec.a_info = bfd_h_get_32 (abfd, exec_bytes.e_info); -#endif /* NO_SWAP_MAGIC */ +#endif /* SWAP_MAGIC */ if (N_BADMAG (exec)) return 0; #ifdef MACHTYPE_OK @@ -105,6 +128,12 @@ DEFUN(MY(object_p),(abfd), #endif NAME(aout,swap_exec_header_in)(abfd, &exec_bytes, &exec); + +#ifdef SWAP_MAGIC + /* swap_exec_header_in read in a_info with the wrong byte order */ + exec.a_info = SWAP_MAGIC (exec_bytes.e_info); +#endif /* SWAP_MAGIC */ + target = NAME(aout,some_aout_object_p) (abfd, &exec, MY(callback)); #ifdef ENTRY_CAN_BE_ZERO @@ -134,8 +163,8 @@ DEFUN(MY(object_p),(abfd), #ifndef MY_mkobject static boolean -DEFUN(MY(mkobject),(abfd), - bfd *abfd) +MY(mkobject) (abfd) + bfd *abfd; { if (NAME(aout,mkobject)(abfd) == false) return false; @@ -154,14 +183,36 @@ DEFUN(MY(mkobject),(abfd), #define MY_mkobject MY(mkobject) #endif +#ifndef MY_bfd_copy_private_section_data + +/* Copy private section data. This actually does nothing with the + sections. It copies the subformat field. We copy it here, because + we need to know whether this is a QMAGIC file before we set the + section contents, and copy_private_bfd_data is not called until + after the section contents have been set. */ + +/*ARGSUSED*/ +static boolean +MY_bfd_copy_private_section_data (ibfd, isec, obfd, osec) + bfd *ibfd; + asection *isec; + bfd *obfd; + asection *osec; +{ + obj_aout_subformat (obfd) = obj_aout_subformat (ibfd); + return true; +} + +#endif + /* Write an object file. Section contents have already been written. We write the file header, symbols, and relocation. */ #ifndef MY_write_object_contents static boolean -DEFUN(MY(write_object_contents),(abfd), - bfd *abfd) +MY(write_object_contents) (abfd) + bfd *abfd; { struct external_exec exec_bytes; struct internal_exec *execp = exec_hdr (abfd); @@ -181,31 +232,112 @@ DEFUN(MY(write_object_contents),(abfd), #ifndef MY_set_sizes static boolean -DEFUN(MY(set_sizes),(abfd), bfd *abfd) +MY(set_sizes) (abfd) + bfd *abfd; { adata(abfd).page_size = PAGE_SIZE; + #ifdef SEGMENT_SIZE adata(abfd).segment_size = SEGMENT_SIZE; #else adata(abfd).segment_size = PAGE_SIZE; #endif + +#ifdef ZMAGIC_DISK_BLOCK_SIZE + adata(abfd).zmagic_disk_block_size = ZMAGIC_DISK_BLOCK_SIZE; +#else + adata(abfd).zmagic_disk_block_size = PAGE_SIZE; +#endif + adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE; return true; } #define MY_set_sizes MY(set_sizes) #endif +#ifndef MY_exec_hdr_flags +#define MY_exec_hdr_flags 0 +#endif + #ifndef MY_backend_data + +#ifndef MY_text_includes_header +#define MY_text_includes_header 0 +#endif +#ifndef MY_add_dynamic_symbols +#define MY_add_dynamic_symbols 0 +#endif +#ifndef MY_add_one_symbol +#define MY_add_one_symbol 0 +#endif +#ifndef MY_link_dynamic_object +#define MY_link_dynamic_object 0 +#endif +#ifndef MY_write_dynamic_symbol +#define MY_write_dynamic_symbol 0 +#endif +#ifndef MY_check_dynamic_reloc +#define MY_check_dynamic_reloc 0 +#endif +#ifndef MY_finish_dynamic_link +#define MY_finish_dynamic_link 0 +#endif + static CONST struct aout_backend_data MY(backend_data) = { 0, /* zmagic contiguous */ - 0, /* text incl header */ + MY_text_includes_header, + MY_exec_hdr_flags, 0, /* text vma? */ MY_set_sizes, 0, /* exec header is counted */ + MY_add_dynamic_symbols, + MY_add_one_symbol, + MY_link_dynamic_object, + MY_write_dynamic_symbol, + MY_check_dynamic_reloc, + MY_finish_dynamic_link }; #define MY_backend_data &MY(backend_data) #endif +#ifndef MY_final_link_callback + +/* Callback for the final_link routine to set the section offsets. */ + +static void MY_final_link_callback + PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); + +static void +MY_final_link_callback (abfd, ptreloff, pdreloff, psymoff) + bfd *abfd; + file_ptr *ptreloff; + file_ptr *pdreloff; + file_ptr *psymoff; +{ + struct internal_exec *execp = exec_hdr (abfd); + + *ptreloff = N_TRELOFF (*execp); + *pdreloff = N_DRELOFF (*execp); + *psymoff = N_SYMOFF (*execp); +} + +#endif + +#ifndef MY_bfd_final_link + +/* Final link routine. We need to use a call back to get the correct + offsets in the output file. */ + +static boolean +MY_bfd_final_link (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + return NAME(aout,final_link) (abfd, info, MY_final_link_callback); +} + +#endif + /* We assume BFD generic archive files. */ #ifndef MY_openr_next_archived_file #define MY_openr_next_archived_file bfd_generic_openr_next_archived_file @@ -228,14 +360,14 @@ static CONST struct aout_backend_data MY(backend_data) = { /* No core file defined here -- configure in trad-core.c separately. */ #ifndef MY_core_file_failing_command -#define MY_core_file_failing_command _bfd_dummy_core_file_failing_command +#define MY_core_file_failing_command _bfd_nocore_core_file_failing_command #endif #ifndef MY_core_file_failing_signal -#define MY_core_file_failing_signal _bfd_dummy_core_file_failing_signal +#define MY_core_file_failing_signal _bfd_nocore_core_file_failing_signal #endif #ifndef MY_core_file_matches_executable_p #define MY_core_file_matches_executable_p \ - _bfd_dummy_core_file_matches_executable_p + _bfd_nocore_core_file_matches_executable_p #endif #ifndef MY_core_file_p #define MY_core_file_p _bfd_dummy_target @@ -261,21 +393,6 @@ static CONST struct aout_backend_data MY(backend_data) = { #ifndef MY_core_file_matches_executable_p #define MY_core_file_matches_executable_p NAME(aout,core_file_matches_executable_p) #endif -#ifndef MY_slurp_armap -#define MY_slurp_armap NAME(aout,slurp_armap) -#endif -#ifndef MY_slurp_extended_name_table -#define MY_slurp_extended_name_table NAME(aout,slurp_extended_name_table) -#endif -#ifndef MY_truncate_arname -#define MY_truncate_arname NAME(aout,truncate_arname) -#endif -#ifndef MY_write_armap -#define MY_write_armap NAME(aout,write_armap) -#endif -#ifndef MY_close_and_cleanup -#define MY_close_and_cleanup NAME(aout,close_and_cleanup) -#endif #ifndef MY_set_section_contents #define MY_set_section_contents NAME(aout,set_section_contents) #endif @@ -312,32 +429,63 @@ static CONST struct aout_backend_data MY(backend_data) = { #ifndef MY_set_arch_mach #define MY_set_arch_mach NAME(aout,set_arch_mach) #endif -#ifndef MY_openr_next_archived_file -#define MY_openr_next_archived_file NAME(aout,openr_next_archived_file) -#endif #ifndef MY_find_nearest_line #define MY_find_nearest_line NAME(aout,find_nearest_line) #endif -#ifndef MY_generic_stat_arch_elt -#define MY_generic_stat_arch_elt NAME(aout,generic_stat_arch_elt) -#endif #ifndef MY_sizeof_headers #define MY_sizeof_headers NAME(aout,sizeof_headers) #endif -#ifndef MY_bfd_debug_info_start -#define MY_bfd_debug_info_start NAME(aout,bfd_debug_info_start) +#ifndef MY_bfd_get_relocated_section_contents +#define MY_bfd_get_relocated_section_contents \ + bfd_generic_get_relocated_section_contents #endif -#ifndef MY_bfd_debug_info_end -#define MY_bfd_debug_info_end NAME(aout,bfd_debug_info_end) +#ifndef MY_bfd_relax_section +#define MY_bfd_relax_section bfd_generic_relax_section #endif -#ifndef MY_bfd_debug_info_accumulat -#define MY_bfd_debug_info_accumulat NAME(aout,bfd_debug_info_accumulat) +#ifndef MY_bfd_reloc_type_lookup +#define MY_bfd_reloc_type_lookup NAME(aout,reloc_type_lookup) #endif -#ifndef MY_reloc_howto_type_lookup -#define MY_reloc_howto_type_lookup NAME(aout,reloc_type_lookup) +#ifndef MY_bfd_make_debug_symbol +#define MY_bfd_make_debug_symbol 0 #endif -#ifndef MY_make_debug_symbol -#define MY_make_debug_symbol 0 +#ifndef MY_bfd_link_hash_table_create +#define MY_bfd_link_hash_table_create NAME(aout,link_hash_table_create) +#endif +#ifndef MY_bfd_link_add_symbols +#define MY_bfd_link_add_symbols NAME(aout,link_add_symbols) +#endif + +#ifndef MY_bfd_copy_private_bfd_data +#define MY_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data +#endif + +#ifndef MY_bfd_is_local_label +#define MY_bfd_is_local_label bfd_generic_is_local_label +#endif + +#ifndef MY_bfd_free_cached_info +#define MY_bfd_free_cached_info NAME(aout,bfd_free_cached_info) +#endif + +#ifndef MY_close_and_cleanup +#define MY_close_and_cleanup MY_bfd_free_cached_info +#endif + +#ifndef MY_get_dynamic_symtab_upper_bound +#define MY_get_dynamic_symtab_upper_bound \ + _bfd_nodynamic_get_dynamic_symtab_upper_bound +#endif +#ifndef MY_canonicalize_dynamic_symtab +#define MY_canonicalize_dynamic_symtab \ + _bfd_nodynamic_canonicalize_dynamic_symtab +#endif +#ifndef MY_get_dynamic_reloc_upper_bound +#define MY_get_dynamic_reloc_upper_bound \ + _bfd_nodynamic_get_dynamic_reloc_upper_bound +#endif +#ifndef MY_canonicalize_dynamic_reloc +#define MY_canonicalize_dynamic_reloc \ + _bfd_nodynamic_canonicalize_dynamic_reloc #endif /* Aout symbols normally have leading underscores */ @@ -351,7 +499,7 @@ static CONST struct aout_backend_data MY(backend_data) = { #endif #ifndef MY_BFD_TARGET -bfd_target MY(vec) = +const bfd_target MY(vec) = { TARGETNAME, /* name */ bfd_target_aout_flavour, @@ -392,38 +540,16 @@ bfd_target MY(vec) = {bfd_false, MY_write_object_contents, /* bfd_write_contents */ _bfd_write_archive_contents, bfd_false}, - MY_core_file_failing_command, - MY_core_file_failing_signal, - MY_core_file_matches_executable_p, - MY_slurp_armap, - MY_slurp_extended_name_table, - MY_truncate_arname, - MY_write_armap, - MY_close_and_cleanup, - MY_set_section_contents, - MY_get_section_contents, - MY_new_section_hook, - MY_get_symtab_upper_bound, - MY_get_symtab, - MY_get_reloc_upper_bound, - MY_canonicalize_reloc, - MY_make_empty_symbol, - MY_print_symbol, - MY_get_symbol_info, - MY_get_lineno, - MY_set_arch_mach, - MY_openr_next_archived_file, - MY_find_nearest_line, - MY_generic_stat_arch_elt, - MY_sizeof_headers, - MY_bfd_debug_info_start, - MY_bfd_debug_info_end, - MY_bfd_debug_info_accumulate, - bfd_generic_get_relocated_section_contents, - bfd_generic_relax_section, - bfd_generic_seclet_link, - MY_reloc_howto_type_lookup, - MY_make_debug_symbol, + BFD_JUMP_TABLE_GENERIC (MY), + BFD_JUMP_TABLE_COPY (MY), + BFD_JUMP_TABLE_CORE (MY), + BFD_JUMP_TABLE_ARCHIVE (MY), + BFD_JUMP_TABLE_SYMBOLS (MY), + BFD_JUMP_TABLE_RELOCS (MY), + BFD_JUMP_TABLE_WRITE (MY), + BFD_JUMP_TABLE_LINK (MY), + BFD_JUMP_TABLE_DYNAMIC (MY), + (PTR) MY_backend_data, }; #endif /* MY_BFD_TARGET */ diff --git a/gnu/usr.bin/gdb/bfd/aout32.c b/gnu/usr.bin/gdb/bfd/aout32.c index 84d20872fc96..294dc1de6363 100644 --- a/gnu/usr.bin/gdb/bfd/aout32.c +++ b/gnu/usr.bin/gdb/bfd/aout32.c @@ -1,5 +1,5 @@ /* BFD back-end for 32-bit a.out files. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. diff --git a/gnu/usr.bin/gdb/bfd/aoutx.h b/gnu/usr.bin/gdb/bfd/aoutx.h index 1ab442926ff2..0bcc860a6acb 100644 --- a/gnu/usr.bin/gdb/bfd/aoutx.h +++ b/gnu/usr.bin/gdb/bfd/aoutx.h @@ -1,5 +1,5 @@ /* BFD semi-generic back-end for a.out binaries. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -30,26 +30,26 @@ DESCRIPTION structures on disk, and the shape of the relocation information. - The support is split into a basic support file @code{aoutx.h} + The support is split into a basic support file @file{aoutx.h} and other files which derive functions from the base. One - derivation file is @code{aoutf1.h} (for a.out flavour 1), and + derivation file is @file{aoutf1.h} (for a.out flavour 1), and adds to the basic a.out functions support for sun3, sun4, 386 and 29k a.out files, to create a target jump vector for a specific target. This information is further split out into more specific files - for each machine, including @code{sunos.c} for sun3 and sun4, - @code{newsos3.c} for the Sony NEWS, and @code{demo64.c} for a + for each machine, including @file{sunos.c} for sun3 and sun4, + @file{newsos3.c} for the Sony NEWS, and @file{demo64.c} for a demonstration of a 64 bit a.out format. - The base file @code{aoutx.h} defines general mechanisms for - reading and writing records to and from disk, and various + The base file @file{aoutx.h} defines general mechanisms for + reading and writing records to and from disk and various other methods which BFD requires. It is included by - @code{aout32.c} and @code{aout64.c} to form the names - aout_32_swap_exec_header_in, aout_64_swap_exec_header_in, etc. + @file{aout32.c} and @file{aout64.c} to form the names + <>, <>, etc. As an example, this is what goes on to make the back end for a - sun4, from aout32.c + sun4, from @file{aout32.c}: | #define ARCH_SIZE 32 | #include "aoutx.h" @@ -63,18 +63,17 @@ DESCRIPTION | aout_32_get_reloc_upper_bound | ... - from sunos.c + from @file{sunos.c}: -| #define ARCH 32 | #define TARGET_NAME "a.out-sunos-big" | #define VECNAME sunos_big_vec | #include "aoutf1.h" - requires all the names from aout32.c, and produces the jump vector + requires all the names from @file{aout32.c}, and produces the jump vector | sunos_big_vec - The file host-aout.c is a special case. It is for a large set + The file @file{host-aout.c} is a special case. It is for a large set of hosts that use ``more or less standard'' a.out files, and for which cross-debugging is not interesting. It uses the standard 32-bit a.out support routines, but determines the @@ -93,17 +92,18 @@ DESCRIPTION | HOST_TEXT_START_ADDR | HOST_STACK_END_ADDR - in the file <<../include/sys/h-XXX.h>> (for your host). These - values, plus the structures and macros defined in <> on + in the file @file{../include/sys/h-@var{XXX}.h} (for your host). These + values, plus the structures and macros defined in @file{a.out.h} on your host system, will produce a BFD target that will access ordinary a.out files on your host. To configure a new machine - to use <., specify: + to use @file{host-aout.c}, specify: | TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec | TDEPFILES= host-aout.o trad-core.o - in the <> file, and modify configure.in to use the - <> file (by setting "<>") when your + in the @file{config/@var{XXX}.mt} file, and modify @file{configure.in} + to use the + @file{@var{XXX}.mt} file (by setting "<>") when your configuration is selected. */ @@ -120,43 +120,58 @@ DESCRIPTION #define KEEPIT flags #define KEEPITTYPE int -#include #include /* For strchr and friends */ #include "bfd.h" #include -#include +#include "bfdlink.h" -struct external_exec; #include "libaout.h" #include "libbfd.h" #include "aout/aout64.h" #include "aout/stab_gnu.h" #include "aout/ar.h" -extern void (*bfd_error_trap)(); +static boolean aout_get_external_symbols PARAMS ((bfd *)); +static boolean translate_from_native_sym_flags + PARAMS ((bfd *, aout_symbol_type *)); +static boolean translate_to_native_sym_flags + PARAMS ((bfd *, asymbol *, struct external_nlist *)); /* SUBSECTION - relocations + Relocations DESCRIPTION - The file @code{aoutx.h} caters for both the @emph{standard} + The file @file{aoutx.h} provides for both the @emph{standard} and @emph{extended} forms of a.out relocation records. - The standard records are characterised by containing only an - address, a symbol index and a type field. The extended records + The standard records contain only an + address, a symbol index, and a type field. The extended records (used on 29ks and sparcs) also have a full integer for an addend. */ +#ifndef CTOR_TABLE_RELOC_HOWTO #define CTOR_TABLE_RELOC_IDX 2 +#define CTOR_TABLE_RELOC_HOWTO(BFD) ((obj_reloc_entry_size(BFD) == RELOC_EXT_SIZE \ + ? howto_table_ext : howto_table_std) \ + + CTOR_TABLE_RELOC_IDX) +#endif + +#ifndef MY_swap_std_reloc_in +#define MY_swap_std_reloc_in NAME(aout,swap_std_reloc_in) +#endif + +#ifndef MY_swap_std_reloc_out +#define MY_swap_std_reloc_out NAME(aout,swap_std_reloc_out) +#endif #define howto_table_ext NAME(aout,ext_howto_table) #define howto_table_std NAME(aout,std_howto_table) reloc_howto_type howto_table_ext[] = { - /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ + /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ HOWTO(RELOC_8, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", false, 0,0x000000ff, false), HOWTO(RELOC_16, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", false, 0,0x0000ffff, false), HOWTO(RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", false, 0,0xffffffff, false), @@ -186,7 +201,7 @@ reloc_howto_type howto_table_ext[] = /* Convert standard reloc records to "arelent" format (incl byte swap). */ reloc_howto_type howto_table_std[] = { - /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ + /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ HOWTO( 0, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", true, 0x000000ff,0x000000ff, false), HOWTO( 1, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", true, 0x0000ffff,0x0000ffff, false), HOWTO( 2, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", true, 0xffffffff,0xffffffff, false), @@ -195,17 +210,40 @@ HOWTO( 4, 0, 0, 8, true, 0, complain_overflow_signed, 0,"DISP8", tru HOWTO( 5, 0, 1, 16, true, 0, complain_overflow_signed, 0,"DISP16", true, 0x0000ffff,0x0000ffff, false), HOWTO( 6, 0, 2, 32, true, 0, complain_overflow_signed, 0,"DISP32", true, 0xffffffff,0xffffffff, false), HOWTO( 7, 0, 4, 64, true, 0, complain_overflow_signed, 0,"DISP64", true, 0xfeedface,0xfeedface, false), -{ -1 }, +HOWTO( 8, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"GOT_REL", false, 0,0x00000000, false), HOWTO( 9, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"BASE16", false,0xffffffff,0xffffffff, false), HOWTO(10, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"BASE32", false,0xffffffff,0xffffffff, false), +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, + HOWTO(16, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"JMP_TABLE", false, 0,0x00000000, false), +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, + HOWTO(32, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"RELATIVE", false, 0,0x00000000, false), +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, +{ -1 }, + HOWTO(40, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"BASEREL", false, 0,0x00000000, false), }; #define TABLE_SIZE(TABLE) (sizeof(TABLE)/sizeof(TABLE[0])) CONST struct reloc_howto_struct * -DEFUN(NAME(aout,reloc_type_lookup),(abfd,code), - bfd *abfd AND - bfd_reloc_code_real_type code) +NAME(aout,reloc_type_lookup) (abfd,code) + bfd *abfd; + bfd_reloc_code_real_type code; { #define EXT(i,j) case i: return &howto_table_ext[j] #define STD(i,j) case i: return &howto_table_std[j] @@ -216,6 +254,9 @@ DEFUN(NAME(aout,reloc_type_lookup),(abfd,code), case 32: code = BFD_RELOC_32; break; + case 64: + code = BFD_RELOC_64; + break; } if (ext) switch (code) @@ -224,6 +265,9 @@ DEFUN(NAME(aout,reloc_type_lookup),(abfd,code), EXT (BFD_RELOC_HI22, 8); EXT (BFD_RELOC_LO10, 11); EXT (BFD_RELOC_32_PCREL_S2, 6); + EXT (BFD_RELOC_SPARC_WDISP22, 7); + EXT (BFD_RELOC_SPARC13, 10); + EXT (BFD_RELOC_SPARC_BASE13, 15); default: return (CONST struct reloc_howto_struct *) 0; } else @@ -241,14 +285,12 @@ DEFUN(NAME(aout,reloc_type_lookup),(abfd,code), } } -extern bfd_error_vector_type bfd_error_vector; - /* SUBSECTION - Internal Entry Points + Internal entry points DESCRIPTION - @code{aoutx.h} exports several routines for accessing the + @file{aoutx.h} exports several routines for accessing the contents of an a.out file, which are gathered and exported in turn by various format specific files (eg sunos.c). @@ -256,26 +298,26 @@ DESCRIPTION /* FUNCTION - aout__swap_exec_header_in - -DESCRIPTION - Swaps the information in an executable header taken from a raw - byte stream memory image, into the internal exec_header - structure. + aout_@var{size}_swap_exec_header_in SYNOPSIS - void aout__swap_exec_header_in, + void aout_@var{size}_swap_exec_header_in, (bfd *abfd, struct external_exec *raw_bytes, struct internal_exec *execp); + +DESCRIPTION + Swap the information in an executable header @var{raw_bytes} taken + from a raw byte stream memory image into the internal exec header + structure @var{execp}. */ #ifndef NAME_swap_exec_header_in void -DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp), - bfd *abfd AND - struct external_exec *raw_bytes AND - struct internal_exec *execp) +NAME(aout,swap_exec_header_in) (abfd, raw_bytes, execp) + bfd *abfd; + struct external_exec *raw_bytes; + struct internal_exec *execp; { struct external_exec *bytes = (struct external_exec *)raw_bytes; @@ -283,7 +325,7 @@ DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp), configuration (IE for i960), so ensure that all such uninitialized fields are zero'd out. There are places where two of these structs are memcmp'd, and thus the contents do matter. */ - memset (execp, 0, sizeof (struct internal_exec)); + memset ((PTR) execp, 0, sizeof (struct internal_exec)); /* Now fill in fields in the execp, from the bytes in the raw data. */ execp->a_info = bfd_h_get_32 (abfd, bytes->e_info); execp->a_text = GET_WORD (abfd, bytes->e_text); @@ -299,23 +341,23 @@ DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp), /* FUNCTION - aout__swap_exec_header_out - -DESCRIPTION - Swaps the information in an internal exec header structure - into the supplied buffer ready for writing to disk. + aout_@var{size}_swap_exec_header_out SYNOPSIS - void aout__swap_exec_header_out + void aout_@var{size}_swap_exec_header_out (bfd *abfd, struct internal_exec *execp, struct external_exec *raw_bytes); + +DESCRIPTION + Swap the information in an internal exec header structure + @var{execp} into the buffer @var{raw_bytes} ready for writing to disk. */ void -DEFUN(NAME(aout,swap_exec_header_out),(abfd, execp, raw_bytes), - bfd *abfd AND - struct internal_exec *execp AND - struct external_exec *raw_bytes) +NAME(aout,swap_exec_header_out) (abfd, execp, raw_bytes) + bfd *abfd; + struct internal_exec *execp; + struct external_exec *raw_bytes; { struct external_exec *bytes = (struct external_exec *)raw_bytes; @@ -330,37 +372,53 @@ DEFUN(NAME(aout,swap_exec_header_out),(abfd, execp, raw_bytes), PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize); } +/* Make all the section for an a.out file. */ +boolean +NAME(aout,make_sections) (abfd) + bfd *abfd; +{ + if (obj_textsec (abfd) == (asection *) NULL + && bfd_make_section (abfd, ".text") == (asection *) NULL) + return false; + if (obj_datasec (abfd) == (asection *) NULL + && bfd_make_section (abfd, ".data") == (asection *) NULL) + return false; + if (obj_bsssec (abfd) == (asection *) NULL + && bfd_make_section (abfd, ".bss") == (asection *) NULL) + return false; + return true; +} /* FUNCTION - aout__some_aout_object_p - -DESCRIPTION - Some A.OUT variant thinks that the file whose format we're - checking is an a.out file. Do some more checking, and set up - for access if it really is. Call back to the calling - environments "finish up" function just before returning, to - handle any last-minute setup. + aout_@var{size}_some_aout_object_p SYNOPSIS - bfd_target *aout__some_aout_object_p + const bfd_target *aout_@var{size}_some_aout_object_p (bfd *abfd, - bfd_target *(*callback_to_real_object_p)()); + const bfd_target *(*callback_to_real_object_p)()); + +DESCRIPTION + Some a.out variant thinks that the file open in @var{abfd} + checking is an a.out file. Do some more checking, and set up + for access if it really is. Call back to the calling + environment's "finish up" function just before returning, to + handle any last-minute setup. */ -bfd_target * -DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), - bfd *abfd AND - struct internal_exec *execp AND - bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *))) +const bfd_target * +NAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p) + bfd *abfd; + struct internal_exec *execp; + const bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *)); { struct aout_data_struct *rawptr, *oldrawptr; - bfd_target *result; + const bfd_target *result; rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, sizeof (struct aout_data_struct )); if (rawptr == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return 0; } @@ -385,19 +443,34 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), /* Setting of EXEC_P has been deferred to the bottom of this function */ if (execp->a_syms) abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS; + if (N_DYNAMIC(*execp)) + abfd->flags |= DYNAMIC; if (N_MAGIC (*execp) == ZMAGIC) { - abfd->flags |= D_PAGED|WP_TEXT; - adata(abfd).magic = z_magic; + abfd->flags |= D_PAGED | WP_TEXT; + adata (abfd).magic = z_magic; + } + else if (N_MAGIC (*execp) == QMAGIC) + { + abfd->flags |= D_PAGED | WP_TEXT; + adata (abfd).magic = z_magic; + adata (abfd).subformat = q_magic_format; } else if (N_MAGIC (*execp) == NMAGIC) { abfd->flags |= WP_TEXT; - adata(abfd).magic = n_magic; + adata (abfd).magic = n_magic; } + else if (N_MAGIC (*execp) == OMAGIC + || N_MAGIC (*execp) == BMAGIC) + adata (abfd).magic = o_magic; else - adata(abfd).magic = o_magic; + { + /* Should have been checked with N_BADMAG before this routine + was called. */ + abort (); + } bfd_get_start_address (abfd) = execp->a_entry; @@ -410,34 +483,30 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), /* The default symbol entry size is that of traditional Unix. */ obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE; - /* Create the sections. This is raunchy, but bfd_close wants to reclaim - them. */ + obj_aout_external_syms (abfd) = NULL; + obj_aout_external_strings (abfd) = NULL; + obj_aout_sym_hashes (abfd) = NULL; - obj_textsec (abfd) = bfd_make_section_old_way (abfd, ".text"); - obj_datasec (abfd) = bfd_make_section_old_way (abfd, ".data"); - obj_bsssec (abfd) = bfd_make_section_old_way (abfd, ".bss"); - -#if 0 - (void)bfd_make_section (abfd, ".text"); - (void)bfd_make_section (abfd, ".data"); - (void)bfd_make_section (abfd, ".bss"); -#endif + if (! NAME(aout,make_sections) (abfd)) + return NULL; obj_datasec (abfd)->_raw_size = execp->a_data; obj_bsssec (abfd)->_raw_size = execp->a_bss; - obj_textsec (abfd)->flags = (execp->a_trsize != 0 ? - (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC) : - (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)); - obj_datasec (abfd)->flags = (execp->a_drsize != 0 ? - (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC) : - (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS)); + obj_textsec (abfd)->flags = + (execp->a_trsize != 0 + ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC) + : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)); + obj_datasec (abfd)->flags = + (execp->a_drsize != 0 + ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC) + : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS)); obj_bsssec (abfd)->flags = SEC_ALLOC; #ifdef THIS_IS_ONLY_DOCUMENTATION /* The common code can't fill in these things because they depend on either the start address of the text segment, the rounding - up of virtual addersses between segments, or the starting file + up of virtual addresses between segments, or the starting file position of the text segment -- all of which varies among different versions of a.out. */ @@ -493,6 +562,23 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), result = (*callback_to_real_object_p)(abfd); +#if defined(MACH) || defined(STAT_FOR_EXEC) + /* The original heuristic doesn't work in some important cases. The + * a.out file has no information about the text start address. For + * files (like kernels) linked to non-standard addresses (ld -Ttext + * nnn) the entry point may not be between the default text start + * (obj_textsec(abfd)->vma) and (obj_textsec(abfd)->vma) + text size + * This is not just a mach issue. Many kernels are loaded at non + * standard addresses. + */ + { + struct stat stat_buf; + if (abfd->iostream + && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0) + && ((stat_buf.st_mode & 0111) != 0)) + abfd->flags |= EXEC_P; + } +#else /* ! MACH */ /* Now that the segment addresses have been worked out, take a better guess at whether the file is executable. If the entry point is within the text segment, assume it is. (This makes files @@ -504,6 +590,7 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), if ((execp->a_entry >= obj_textsec(abfd)->vma) && (execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size)) abfd->flags |= EXEC_P; +#endif /* MACH */ if (result) { #if 0 /* These should be set correctly anyways. */ @@ -522,45 +609,37 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p), /* FUNCTION - aout__mkobject - -DESCRIPTION - This routine initializes a BFD for use with a.out files. + aout_@var{size}_mkobject SYNOPSIS - boolean aout__mkobject, (bfd *); + boolean aout_@var{size}_mkobject, (bfd *abfd); + +DESCRIPTION + Initialize BFD @var{abfd} for use with a.out files. */ boolean -DEFUN(NAME(aout,mkobject),(abfd), - bfd *abfd) +NAME(aout,mkobject) (abfd) + bfd *abfd; { struct aout_data_struct *rawptr; - bfd_error = system_call_error; + bfd_set_error (bfd_error_system_call); /* Use an intermediate variable for clarity */ rawptr = (struct aout_data_struct *)bfd_zalloc (abfd, sizeof (struct aout_data_struct )); if (rawptr == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } abfd->tdata.aout_data = rawptr; exec_hdr (abfd) = &(rawptr->e); - /* For simplicity's sake we just make all the sections right here. */ - obj_textsec (abfd) = (asection *)NULL; obj_datasec (abfd) = (asection *)NULL; obj_bsssec (abfd) = (asection *)NULL; - bfd_make_section (abfd, ".text"); - bfd_make_section (abfd, ".data"); - bfd_make_section (abfd, ".bss"); - bfd_make_section (abfd, BFD_ABS_SECTION_NAME); - bfd_make_section (abfd, BFD_UND_SECTION_NAME); - bfd_make_section (abfd, BFD_COM_SECTION_NAME); return true; } @@ -568,31 +647,33 @@ DEFUN(NAME(aout,mkobject),(abfd), /* FUNCTION - aout__machine_type + aout_@var{size}_machine_type + +SYNOPSIS + enum machine_type aout_@var{size}_machine_type + (enum bfd_architecture arch, + unsigned long machine)); DESCRIPTION Keep track of machine architecture and machine type for - a.out's. Return the machine_type for a particular - arch&machine, or M_UNKNOWN if that exact arch&machine can't be - represented in a.out format. + a.out's. Return the <> for a particular + architecture and machine, or <> if that exact architecture + and machine can't be represented in a.out format. If the architecture is understood, machine type 0 (default) - should always be understood. - -SYNOPSIS - enum machine_type aout__machine_type - (enum bfd_architecture arch, - unsigned long machine)); + is always understood. */ enum machine_type -DEFUN(NAME(aout,machine_type),(arch, machine), - enum bfd_architecture arch AND - unsigned long machine) +NAME(aout,machine_type) (arch, machine, unknown) + enum bfd_architecture arch; + unsigned long machine; + boolean *unknown; { enum machine_type arch_flags; arch_flags = M_UNKNOWN; + *unknown = true; switch (arch) { case bfd_arch_sparc: @@ -602,7 +683,7 @@ DEFUN(NAME(aout,machine_type),(arch, machine), case bfd_arch_m68k: switch (machine) { case 0: arch_flags = M_68010; break; - case 68000: arch_flags = M_UNKNOWN; break; + case 68000: arch_flags = M_UNKNOWN; *unknown = false; break; case 68010: arch_flags = M_68010; break; case 68020: arch_flags = M_68020; break; default: arch_flags = M_UNKNOWN; break; @@ -629,41 +710,59 @@ DEFUN(NAME(aout,machine_type),(arch, machine), } break; + case bfd_arch_ns32k: + switch (machine) { + case 0: arch_flags = M_NS32532; break; + case 32032: arch_flags = M_NS32032; break; + case 32532: arch_flags = M_NS32532; break; + default: arch_flags = M_UNKNOWN; break; + } + break; + default: arch_flags = M_UNKNOWN; } + + if (arch_flags != M_UNKNOWN) + *unknown = false; + return arch_flags; } /* FUNCTION - aout__set_arch_mach - -DESCRIPTION - Sets the architecture and the machine of the BFD to those - values supplied. Verifies that the format can support the - architecture required. + aout_@var{size}_set_arch_mach SYNOPSIS - boolean aout__set_arch_mach, + boolean aout_@var{size}_set_arch_mach, (bfd *, - enum bfd_architecture, + enum bfd_architecture arch, unsigned long machine)); + +DESCRIPTION + Set the architecture and the machine of the BFD @var{abfd} to the + values @var{arch} and @var{machine}. Verify that @var{abfd}'s format + can support the architecture required. */ boolean -DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine), - bfd *abfd AND - enum bfd_architecture arch AND - unsigned long machine) +NAME(aout,set_arch_mach) (abfd, arch, machine) + bfd *abfd; + enum bfd_architecture arch; + unsigned long machine; { if (! bfd_default_set_arch_mach (abfd, arch, machine)) return false; - if (arch != bfd_arch_unknown && - NAME(aout,machine_type) (arch, machine) == M_UNKNOWN) - return false; /* We can't represent this type */ + if (arch != bfd_arch_unknown) + { + boolean unknown; + + NAME(aout,machine_type) (arch, machine, &unknown); + if (unknown) + return false; + } /* Determine the size of a relocation entry */ switch (arch) { @@ -680,29 +779,224 @@ DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine), return (*aout_backend_info(abfd)->set_sizes) (abfd); } +static void +adjust_o_magic (abfd, execp) + bfd *abfd; + struct internal_exec *execp; +{ + file_ptr pos = adata (abfd).exec_bytes_size; + bfd_vma vma = 0; + int pad = 0; + + /* Text. */ + obj_textsec(abfd)->filepos = pos; + pos += obj_textsec(abfd)->_raw_size; + vma += obj_textsec(abfd)->_raw_size; + + /* Data. */ + if (!obj_datasec(abfd)->user_set_vma) + { +#if 0 /* ?? Does alignment in the file image really matter? */ + pad = align_power (vma, obj_datasec(abfd)->alignment_power) - vma; +#endif + obj_textsec(abfd)->_raw_size += pad; + pos += pad; + vma += pad; + obj_datasec(abfd)->vma = vma; + } + obj_datasec(abfd)->filepos = pos; + pos += obj_datasec(abfd)->_raw_size; + vma += obj_datasec(abfd)->_raw_size; + + /* BSS. */ + if (!obj_bsssec(abfd)->user_set_vma) + { +#if 0 + pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; +#endif + obj_datasec(abfd)->_raw_size += pad; + pos += pad; + vma += pad; + obj_bsssec(abfd)->vma = vma; + } + obj_bsssec(abfd)->filepos = pos; + + /* Fix up the exec header. */ + execp->a_text = obj_textsec(abfd)->_raw_size; + execp->a_data = obj_datasec(abfd)->_raw_size; + execp->a_bss = obj_bsssec(abfd)->_raw_size; + N_SET_MAGIC (*execp, OMAGIC); +} + +static void +adjust_z_magic (abfd, execp) + bfd *abfd; + struct internal_exec *execp; +{ + bfd_size_type data_pad, text_pad; + file_ptr text_end; + CONST struct aout_backend_data *abdp; + int ztih; /* Nonzero if text includes exec header. */ + + abdp = aout_backend_info (abfd); + + /* Text. */ + ztih = (abdp != NULL + && (abdp->text_includes_header + || obj_aout_subformat (abfd) == q_magic_format)); + obj_textsec(abfd)->filepos = (ztih + ? adata(abfd).exec_bytes_size + : adata(abfd).zmagic_disk_block_size); + if (! obj_textsec(abfd)->user_set_vma) + /* ?? Do we really need to check for relocs here? */ + obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC) + ? 0 + : (ztih + ? (abdp->default_text_vma + + adata(abfd).exec_bytes_size) + : abdp->default_text_vma)); + /* Could take strange alignment of text section into account here? */ + + /* Find start of data. */ + if (ztih) + { + text_end = obj_textsec (abfd)->filepos + obj_textsec (abfd)->_raw_size; + text_pad = BFD_ALIGN (text_end, adata (abfd).page_size) - text_end; + } + else + { + /* Note that if page_size == zmagic_disk_block_size, then + filepos == page_size, and this case is the same as the ztih + case. */ + text_end = obj_textsec (abfd)->_raw_size; + text_pad = BFD_ALIGN (text_end, adata (abfd).page_size) - text_end; + text_end += obj_textsec (abfd)->filepos; + } + obj_textsec(abfd)->_raw_size += text_pad; + text_end += text_pad; + + /* Data. */ + if (!obj_datasec(abfd)->user_set_vma) + { + bfd_vma vma; + vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size; + obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); + } + if (abdp && abdp->zmagic_mapped_contiguous) + { + text_pad = (obj_datasec(abfd)->vma + - obj_textsec(abfd)->vma + - obj_textsec(abfd)->_raw_size); + obj_textsec(abfd)->_raw_size += text_pad; + } + obj_datasec(abfd)->filepos = (obj_textsec(abfd)->filepos + + obj_textsec(abfd)->_raw_size); + + /* Fix up exec header while we're at it. */ + execp->a_text = obj_textsec(abfd)->_raw_size; + if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted))) + execp->a_text += adata(abfd).exec_bytes_size; + if (obj_aout_subformat (abfd) == q_magic_format) + N_SET_MAGIC (*execp, QMAGIC); + else + N_SET_MAGIC (*execp, ZMAGIC); + + /* Spec says data section should be rounded up to page boundary. */ + obj_datasec(abfd)->_raw_size + = align_power (obj_datasec(abfd)->_raw_size, + obj_bsssec(abfd)->alignment_power); + execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size, + adata(abfd).page_size); + data_pad = execp->a_data - obj_datasec(abfd)->_raw_size; + + /* BSS. */ + if (!obj_bsssec(abfd)->user_set_vma) + obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma + + obj_datasec(abfd)->_raw_size); + /* If the BSS immediately follows the data section and extra space + in the page is left after the data section, fudge data + in the header so that the bss section looks smaller by that + amount. We'll start the bss section there, and lie to the OS. + (Note that a linker script, as well as the above assignment, + could have explicitly set the BSS vma to immediately follow + the data section.) */ + if (align_power (obj_bsssec(abfd)->vma, obj_bsssec(abfd)->alignment_power) + == obj_datasec(abfd)->vma + obj_datasec(abfd)->_raw_size) + execp->a_bss = (data_pad > obj_bsssec(abfd)->_raw_size) ? 0 : + obj_bsssec(abfd)->_raw_size - data_pad; + else + execp->a_bss = obj_bsssec(abfd)->_raw_size; +} + +static void +adjust_n_magic (abfd, execp) + bfd *abfd; + struct internal_exec *execp; +{ + file_ptr pos = adata(abfd).exec_bytes_size; + bfd_vma vma = 0; + int pad; + + /* Text. */ + obj_textsec(abfd)->filepos = pos; + if (!obj_textsec(abfd)->user_set_vma) + obj_textsec(abfd)->vma = vma; + else + vma = obj_textsec(abfd)->vma; + pos += obj_textsec(abfd)->_raw_size; + vma += obj_textsec(abfd)->_raw_size; + + /* Data. */ + obj_datasec(abfd)->filepos = pos; + if (!obj_datasec(abfd)->user_set_vma) + obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); + vma = obj_datasec(abfd)->vma; + + /* Since BSS follows data immediately, see if it needs alignment. */ + vma += obj_datasec(abfd)->_raw_size; + pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; + obj_datasec(abfd)->_raw_size += pad; + pos += obj_datasec(abfd)->_raw_size; + + /* BSS. */ + if (!obj_bsssec(abfd)->user_set_vma) + obj_bsssec(abfd)->vma = vma; + else + vma = obj_bsssec(abfd)->vma; + + /* Fix up exec header. */ + execp->a_text = obj_textsec(abfd)->_raw_size; + execp->a_data = obj_datasec(abfd)->_raw_size; + execp->a_bss = obj_bsssec(abfd)->_raw_size; + N_SET_MAGIC (*execp, NMAGIC); +} + boolean -DEFUN (NAME (aout,adjust_sizes_and_vmas), (abfd, text_size, text_end), - bfd *abfd AND bfd_size_type *text_size AND file_ptr *text_end) +NAME(aout,adjust_sizes_and_vmas) (abfd, text_size, text_end) + bfd *abfd; + bfd_size_type *text_size; + file_ptr *text_end; { struct internal_exec *execp = exec_hdr (abfd); - if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL)) - { - bfd_error = invalid_operation; - return false; - } - if (adata(abfd).magic != undecided_magic) return true; + + if (! NAME(aout,make_sections) (abfd)) + return false; + + if (adata(abfd).magic != undecided_magic) + return true; + obj_textsec(abfd)->_raw_size = align_power(obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->alignment_power); *text_size = obj_textsec (abfd)->_raw_size; /* Rule (heuristic) for when to pad to a new page. Note that there - * are (at least) two ways demand-paged (ZMAGIC) files have been - * handled. Most Berkeley-based systems start the text segment at - * (PAGE_SIZE). However, newer versions of SUNOS start the text - * segment right after the exec header; the latter is counted in the - * text segment size, and is paged in by the kernel with the rest of - * the text. */ + are (at least) two ways demand-paged (ZMAGIC) files have been + handled. Most Berkeley-based systems start the text segment at + (PAGE_SIZE). However, newer versions of SUNOS start the text + segment right after the exec header; the latter is counted in the + text segment size, and is paged in by the kernel with the rest of + the text. */ /* This perhaps isn't the right way to do this, but made it simpler for me to understand enough to implement it. Better would probably be to go @@ -711,17 +1005,14 @@ DEFUN (NAME (aout,adjust_sizes_and_vmas), (abfd, text_size, text_end), other magic, that it was a little hard for me to understand. I think I understand it better now, but I haven't time to do the cleanup this minute. */ - if (adata(abfd).magic == undecided_magic) - { - if (abfd->flags & D_PAGED) - /* Whether or not WP_TEXT is set -- let D_PAGED override. */ - /* @@ What about QMAGIC? */ - adata(abfd).magic = z_magic; - else if (abfd->flags & WP_TEXT) - adata(abfd).magic = n_magic; - else - adata(abfd).magic = o_magic; - } + + if (abfd->flags & D_PAGED) + /* Whether or not WP_TEXT is set -- let D_PAGED override. */ + adata(abfd).magic = z_magic; + else if (abfd->flags & WP_TEXT) + adata(abfd).magic = n_magic; + else + adata(abfd).magic = o_magic; #ifdef BFD_AOUT_DEBUG /* requires gcc2 */ #if __GNUC__ >= 2 @@ -735,187 +1026,59 @@ DEFUN (NAME (aout,adjust_sizes_and_vmas), (abfd, text_size, text_end), } str; }), - obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->alignment_power, - obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, obj_datasec(abfd)->alignment_power, - obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size, obj_bsssec(abfd)->alignment_power); + obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, + obj_textsec(abfd)->alignment_power, + obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, + obj_datasec(abfd)->alignment_power, + obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size, + obj_bsssec(abfd)->alignment_power); #endif #endif switch (adata(abfd).magic) { case o_magic: - { - file_ptr pos = adata (abfd).exec_bytes_size; - bfd_vma vma = 0; - int pad = 0; - - obj_textsec(abfd)->filepos = pos; - pos += obj_textsec(abfd)->_raw_size; - vma += obj_textsec(abfd)->_raw_size; - if (!obj_datasec(abfd)->user_set_vma) - { -#if 0 /* ?? Does alignment in the file image really matter? */ - pad = align_power (vma, obj_datasec(abfd)->alignment_power) - vma; -#endif - obj_textsec(abfd)->_raw_size += pad; - pos += pad; - vma += pad; - obj_datasec(abfd)->vma = vma; - } - obj_datasec(abfd)->filepos = pos; - pos += obj_datasec(abfd)->_raw_size; - vma += obj_datasec(abfd)->_raw_size; - if (!obj_bsssec(abfd)->user_set_vma) - { -#if 0 - pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; -#endif - obj_datasec(abfd)->_raw_size += pad; - pos += pad; - vma += pad; - obj_bsssec(abfd)->vma = vma; - } - obj_bsssec(abfd)->filepos = pos; - execp->a_text = obj_textsec(abfd)->_raw_size; - execp->a_data = obj_datasec(abfd)->_raw_size; - execp->a_bss = obj_bsssec(abfd)->_raw_size; - N_SET_MAGIC (*execp, OMAGIC); - } + adjust_o_magic (abfd, execp); break; case z_magic: - { - bfd_size_type data_pad, text_pad; - file_ptr text_end; - CONST struct aout_backend_data *abdp; - int ztih; - bfd_vma data_vma; - - abdp = aout_backend_info (abfd); - ztih = abdp && abdp->text_includes_header; - obj_textsec(abfd)->filepos = (ztih - ? adata(abfd).exec_bytes_size - : adata(abfd).page_size); - if (! obj_textsec(abfd)->user_set_vma) - /* ?? Do we really need to check for relocs here? */ - obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC) - ? 0 - : (ztih - ? (abdp->default_text_vma - + adata(abfd).exec_bytes_size) - : abdp->default_text_vma)); - /* Could take strange alignment of text section into account here? */ - - /* Find start of data. */ - text_end = obj_textsec(abfd)->filepos + obj_textsec(abfd)->_raw_size; - text_pad = BFD_ALIGN (text_end, adata(abfd).page_size) - text_end; - obj_textsec(abfd)->_raw_size += text_pad; - text_end += text_pad; - - if (!obj_datasec(abfd)->user_set_vma) - { - bfd_vma vma; - vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size; - obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); - } - data_vma = obj_datasec(abfd)->vma; - if (abdp && abdp->zmagic_mapped_contiguous) - { - text_pad = (obj_datasec(abfd)->vma - - obj_textsec(abfd)->vma - - obj_textsec(abfd)->_raw_size); - obj_textsec(abfd)->_raw_size += text_pad; - } - obj_datasec(abfd)->filepos = (obj_textsec(abfd)->filepos - + obj_textsec(abfd)->_raw_size); - - /* Fix up exec header while we're at it. */ - execp->a_text = obj_textsec(abfd)->_raw_size; - if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted))) - execp->a_text += adata(abfd).exec_bytes_size; - N_SET_MAGIC (*execp, ZMAGIC); - /* Spec says data section should be rounded up to page boundary. */ - /* If extra space in page is left after data section, fudge data - in the header so that the bss section looks smaller by that - amount. We'll start the bss section there, and lie to the OS. */ - obj_datasec(abfd)->_raw_size - = align_power (obj_datasec(abfd)->_raw_size, - obj_bsssec(abfd)->alignment_power); - execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size, - adata(abfd).page_size); - data_pad = execp->a_data - obj_datasec(abfd)->_raw_size; - - if (!obj_bsssec(abfd)->user_set_vma) - obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma - + obj_datasec(abfd)->_raw_size); - if (data_pad > obj_bsssec(abfd)->_raw_size) - execp->a_bss = 0; - else - execp->a_bss = obj_bsssec(abfd)->_raw_size - data_pad; - } + adjust_z_magic (abfd, execp); break; case n_magic: - { - file_ptr pos = adata(abfd).exec_bytes_size; - bfd_vma vma = 0; - int pad; - - obj_textsec(abfd)->filepos = pos; - if (!obj_textsec(abfd)->user_set_vma) - obj_textsec(abfd)->vma = vma; - else - vma = obj_textsec(abfd)->vma; - pos += obj_textsec(abfd)->_raw_size; - vma += obj_textsec(abfd)->_raw_size; - obj_datasec(abfd)->filepos = pos; - if (!obj_datasec(abfd)->user_set_vma) - obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); - vma = obj_datasec(abfd)->vma; - - /* Since BSS follows data immediately, see if it needs alignment. */ - vma += obj_datasec(abfd)->_raw_size; - pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; - obj_datasec(abfd)->_raw_size += pad; - pos += obj_datasec(abfd)->_raw_size; - - if (!obj_bsssec(abfd)->user_set_vma) - obj_bsssec(abfd)->vma = vma; - else - vma = obj_bsssec(abfd)->vma; - } - execp->a_text = obj_textsec(abfd)->_raw_size; - execp->a_data = obj_datasec(abfd)->_raw_size; - execp->a_bss = obj_bsssec(abfd)->_raw_size; - N_SET_MAGIC (*execp, NMAGIC); + adjust_n_magic (abfd, execp); break; default: abort (); } + #ifdef BFD_AOUT_DEBUG fprintf (stderr, " text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n", - obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->filepos, - obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, obj_datasec(abfd)->filepos, + obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, + obj_textsec(abfd)->filepos, + obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, + obj_datasec(abfd)->filepos, obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size); #endif + return true; } /* FUNCTION - aout__new_section_hook + aout_@var{size}_new_section_hook + +SYNOPSIS + boolean aout_@var{size}_new_section_hook, + (bfd *abfd, + asection *newsect)); DESCRIPTION Called by the BFD in response to a @code{bfd_make_section} request. - -SYNOPSIS - boolean aout__new_section_hook, - (bfd *abfd, - asection *newsect)); */ boolean -DEFUN(NAME(aout,new_section_hook),(abfd, newsect), - bfd *abfd AND - asection *newsect) +NAME(aout,new_section_hook) (abfd, newsect) + bfd *abfd; + asection *newsect; { /* align to double at least */ newsect->alignment_power = bfd_get_arch_info(abfd)->section_align_power; @@ -925,19 +1088,19 @@ DEFUN(NAME(aout,new_section_hook),(abfd, newsect), { if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) { obj_textsec(abfd)= newsect; - newsect->target_index = N_TEXT | N_EXT; + newsect->target_index = N_TEXT; return true; } if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) { obj_datasec(abfd) = newsect; - newsect->target_index = N_DATA | N_EXT; + newsect->target_index = N_DATA; return true; } if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) { obj_bsssec(abfd) = newsect; - newsect->target_index = N_BSS | N_EXT; + newsect->target_index = N_BSS; return true; } @@ -948,12 +1111,12 @@ DEFUN(NAME(aout,new_section_hook),(abfd, newsect), } boolean -DEFUN(NAME(aout,set_section_contents),(abfd, section, location, offset, count), - bfd *abfd AND - sec_ptr section AND - PTR location AND - file_ptr offset AND - bfd_size_type count) +NAME(aout,set_section_contents) (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; { file_ptr text_end; bfd_size_type text_size; @@ -969,7 +1132,8 @@ DEFUN(NAME(aout,set_section_contents),(abfd, section, location, offset, count), /* regardless, once we know what we're doing, we might as well get going */ if (section != obj_bsssec(abfd)) { - bfd_seek (abfd, section->filepos + offset, SEEK_SET); + if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0) + return false; if (count) { return (bfd_write ((PTR)location, 1, count, abfd) == count) ? @@ -980,113 +1144,259 @@ DEFUN(NAME(aout,set_section_contents),(abfd, section, location, offset, count), return true; } -/* Classify stabs symbols */ +/* Read the external symbols from an a.out file. */ -#define sym_in_text_section(sym) \ - (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT) - -#define sym_in_data_section(sym) \ - (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA) - -#define sym_in_bss_section(sym) \ - (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS) - -/* Symbol is undefined if type is N_UNDF|N_EXT and if it has - zero in the "value" field. Nonzeroes there are fortrancommon - symbols. */ -#define sym_is_undefined(sym) \ - ((sym)->type == (N_UNDF | N_EXT) && (sym)->symbol.value == 0) - -/* Symbol is a global definition if N_EXT is on and if it has - a nonzero type field. */ -#define sym_is_global_defn(sym) \ - (((sym)->type & N_EXT) && (sym)->type & N_TYPE) - -/* Symbol is debugger info if any bits outside N_TYPE or N_EXT - are on. */ -#define sym_is_debugger_info(sym) \ - (((sym)->type & ~(N_EXT | N_TYPE)) || (sym)->type == N_FN) - -#define sym_is_fortrancommon(sym) \ - (((sym)->type == (N_EXT)) && (sym)->symbol.value != 0) - -/* Symbol is absolute if it has N_ABS set */ -#define sym_is_absolute(sym) \ - (((sym)->type & N_TYPE)== N_ABS) - - -#define sym_is_indirect(sym) \ - (((sym)->type & N_ABS)== N_ABS) - -/* Only in their own functions for ease of debugging; when sym flags have - stabilised these should be inlined into their (single) caller */ - -static void -DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd), - struct external_nlist *sym_pointer AND - aout_symbol_type * cache_ptr AND - bfd * abfd) +static boolean +aout_get_external_symbols (abfd) + bfd *abfd; { - cache_ptr->symbol.section = 0; - switch (cache_ptr->type & N_TYPE) + if (obj_aout_external_syms (abfd) == (struct external_nlist *) NULL) { - case N_SETA: - case N_SETT: - case N_SETD: - case N_SETB: + bfd_size_type count; + struct external_nlist *syms; + + count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE; + + /* We allocate using malloc to make the values easy to free + later on. If we put them on the obstack it might not be + possible to free them. */ + syms = ((struct external_nlist *) + malloc ((size_t) count * EXTERNAL_NLIST_SIZE)); + if (syms == (struct external_nlist *) NULL && count != 0) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0 + || (bfd_read (syms, 1, exec_hdr (abfd)->a_syms, abfd) + != exec_hdr (abfd)->a_syms)) + { + free (syms); + return false; + } + + obj_aout_external_syms (abfd) = syms; + obj_aout_external_sym_count (abfd) = count; + } + + if (obj_aout_external_strings (abfd) == NULL + && exec_hdr (abfd)->a_syms != 0) + { + unsigned char string_chars[BYTES_IN_WORD]; + bfd_size_type stringsize; + char *strings; + + /* Get the size of the strings. */ + if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0 + || (bfd_read ((PTR) string_chars, BYTES_IN_WORD, 1, abfd) + != BYTES_IN_WORD)) + return false; + stringsize = GET_WORD (abfd, string_chars); + + strings = (char *) malloc ((size_t) stringsize + 1); + if (strings == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + /* Skip space for the string count in the buffer for convenience + when using indexes. */ + if (bfd_read (strings + BYTES_IN_WORD, 1, stringsize - BYTES_IN_WORD, + abfd) + != stringsize - BYTES_IN_WORD) + { + free (strings); + return false; + } + + /* Sanity preservation. */ + strings[stringsize] = '\0'; + + obj_aout_external_strings (abfd) = strings; + obj_aout_external_string_size (abfd) = stringsize; + } + + return true; +} + +/* Translate an a.out symbol into a BFD symbol. The desc, other, type + and symbol->value fields of CACHE_PTR will be set from the a.out + nlist structure. This function is responsible for setting + symbol->flags and symbol->section, and adjusting symbol->value. */ + +static boolean +translate_from_native_sym_flags (abfd, cache_ptr) + bfd *abfd; + aout_symbol_type *cache_ptr; +{ + flagword visible; + + if ((cache_ptr->type & N_STAB) != 0 + || cache_ptr->type == N_FN) + { + asection *sec; + + /* This is a debugging symbol. */ + + cache_ptr->symbol.flags = BSF_DEBUGGING; + + /* Work out the symbol section. */ + switch (cache_ptr->type & N_TYPE) + { + case N_TEXT: + case N_FN: + sec = obj_textsec (abfd); + break; + case N_DATA: + sec = obj_datasec (abfd); + break; + case N_BSS: + sec = obj_bsssec (abfd); + break; + default: + case N_ABS: + sec = bfd_abs_section_ptr; + break; + } + + cache_ptr->symbol.section = sec; + cache_ptr->symbol.value -= sec->vma; + + return true; + } + + /* Get the default visibility. This does not apply to all types, so + we just hold it in a local variable to use if wanted. */ + if ((cache_ptr->type & N_EXT) == 0) + visible = BSF_LOCAL; + else + visible = BSF_GLOBAL; + + switch (cache_ptr->type) + { + default: + case N_ABS: case N_ABS | N_EXT: + cache_ptr->symbol.section = bfd_abs_section_ptr; + cache_ptr->symbol.flags = visible; + break; + + case N_UNDF | N_EXT: + if (cache_ptr->symbol.value != 0) + { + /* This is a common symbol. */ + cache_ptr->symbol.flags = BSF_GLOBAL; + cache_ptr->symbol.section = bfd_com_section_ptr; + } + else + { + cache_ptr->symbol.flags = 0; + cache_ptr->symbol.section = bfd_und_section_ptr; + } + break; + + case N_TEXT: case N_TEXT | N_EXT: + cache_ptr->symbol.section = obj_textsec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = visible; + break; + + /* N_SETV symbols used to represent set vectors placed in the + data section. They are no longer generated. Theoretically, + it was possible to extract the entries and combine them with + new ones, although I don't know if that was ever actually + done. Unless that feature is restored, treat them as data + symbols. */ + case N_SETV: case N_SETV | N_EXT: + case N_DATA: case N_DATA | N_EXT: + cache_ptr->symbol.section = obj_datasec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = visible; + break; + + case N_BSS: case N_BSS | N_EXT: + cache_ptr->symbol.section = obj_bsssec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = visible; + break; + + case N_SETA: case N_SETA | N_EXT: + case N_SETT: case N_SETT | N_EXT: + case N_SETD: case N_SETD | N_EXT: + case N_SETB: case N_SETB | N_EXT: { - char *copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1); asection *section; + arelent_chain *reloc; asection *into_section; - arelent_chain *reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain)); - strcpy (copy, cache_ptr->symbol.name); + /* This is a set symbol. The name of the symbol is the name + of the set (e.g., __CTOR_LIST__). The value of the symbol + is the value to add to the set. We create a section with + the same name as the symbol, and add a reloc to insert the + appropriate value into the section. - /* Make sure that this bfd has a section with the right contructor - name */ - section = bfd_get_section_by_name (abfd, copy); - if (!section) - section = bfd_make_section (abfd, copy); + This action is actually obsolete; it used to make the + linker do the right thing, but the linker no longer uses + this function. */ - /* Build a relocation entry for the constructor */ - switch ((cache_ptr->type & N_TYPE)) + section = bfd_get_section_by_name (abfd, cache_ptr->symbol.name); + if (section == NULL) + { + char *copy; + + copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1); + if (copy == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + strcpy (copy, cache_ptr->symbol.name); + section = bfd_make_section (abfd, copy); + if (section == NULL) + return false; + } + + reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain)); + if (reloc == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + /* Build a relocation entry for the constructor. */ + switch (cache_ptr->type & N_TYPE) { case N_SETA: - into_section = &bfd_abs_section; + into_section = bfd_abs_section_ptr; cache_ptr->type = N_ABS; break; case N_SETT: - into_section = (asection *) obj_textsec (abfd); + into_section = obj_textsec (abfd); cache_ptr->type = N_TEXT; break; case N_SETD: - into_section = (asection *) obj_datasec (abfd); + into_section = obj_datasec (abfd); cache_ptr->type = N_DATA; break; case N_SETB: - into_section = (asection *) obj_bsssec (abfd); + into_section = obj_bsssec (abfd); cache_ptr->type = N_BSS; break; - default: - abort (); } - /* Build a relocation pointing into the constuctor section - pointing at the symbol in the set vector specified */ - + /* Build a relocation pointing into the constructor section + pointing at the symbol in the set vector specified. */ reloc->relent.addend = cache_ptr->symbol.value; - cache_ptr->symbol.section = into_section->symbol->section; + cache_ptr->symbol.section = into_section; reloc->relent.sym_ptr_ptr = into_section->symbol_ptr_ptr; - - /* We modify the symbol to belong to a section depending upon the - name of the symbol - probably __CTOR__ or __DTOR__ but we don't - really care, and add to the size of the section to contain a - pointer to the symbol. Build a reloc entry to relocate to this - symbol attached to this section. */ - - section->flags = SEC_CONSTRUCTOR; - + /* We modify the symbol to belong to a section depending upon + the name of the symbol, and add to the size of the section + to contain a pointer to the symbol. Build a reloc entry to + relocate to this symbol attached to this section. */ + section->flags = SEC_CONSTRUCTOR | SEC_RELOC; section->reloc_count++; section->alignment_power = 2; @@ -1094,735 +1404,529 @@ DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd), reloc->next = section->constructor_chain; section->constructor_chain = reloc; reloc->relent.address = section->_raw_size; - section->_raw_size += sizeof (int *); + section->_raw_size += BYTES_IN_WORD; + + reloc->relent.howto = CTOR_TABLE_RELOC_HOWTO(abfd); - reloc->relent.howto - = (obj_reloc_entry_size(abfd) == RELOC_EXT_SIZE - ? howto_table_ext : howto_table_std) - + CTOR_TABLE_RELOC_IDX; cache_ptr->symbol.flags |= BSF_CONSTRUCTOR; } break; - default: - if (cache_ptr->type == N_WARNING) - { - /* This symbol is the text of a warning message, the next symbol - is the symbol to associate the warning with */ - cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING; - /* @@ Stuffing pointers into integers is a no-no. - We can usually get away with it if the integer is - large enough though. */ - if (sizeof (cache_ptr + 1) > sizeof (bfd_vma)) - abort (); - cache_ptr->symbol.value = (bfd_vma) ((cache_ptr + 1)); + case N_WARNING: + /* This symbol is the text of a warning message. The next + symbol is the symbol to associate the warning with. If a + reference is made to that symbol, a warning is issued. */ + cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING; - /* We furgle with the next symbol in place. - We don't want it to be undefined, we'll trample the type */ - (sym_pointer + 1)->e_type[0] = 0xff; - break; - } - if ((cache_ptr->type | N_EXT) == (N_INDR | N_EXT)) - { - /* Two symbols in a row for an INDR message. The first symbol - contains the name we will match, the second symbol contains - the name the first name is translated into. It is supplied to - us undefined. This is good, since we want to pull in any files - which define it */ - cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT; + /* @@ Stuffing pointers into integers is a no-no. We can + usually get away with it if the integer is large enough + though. */ + if (sizeof (cache_ptr + 1) > sizeof (bfd_vma)) + abort (); + cache_ptr->symbol.value = (bfd_vma) (cache_ptr + 1); - /* @@ Stuffing pointers into integers is a no-no. - We can usually get away with it if the integer is - large enough though. */ - if (sizeof (cache_ptr + 1) > sizeof (bfd_vma)) - abort (); + cache_ptr->symbol.section = bfd_abs_section_ptr; - cache_ptr->symbol.value = (bfd_vma) ((cache_ptr + 1)); - cache_ptr->symbol.section = &bfd_ind_section; - } + break; - else if (sym_is_debugger_info (cache_ptr)) - { - cache_ptr->symbol.flags = BSF_DEBUGGING; - /* Work out the section correct for this symbol */ - switch (cache_ptr->type & N_TYPE) - { - case N_TEXT: - case N_FN: - cache_ptr->symbol.section = obj_textsec (abfd); - cache_ptr->symbol.value -= obj_textsec (abfd)->vma; - break; - case N_DATA: - cache_ptr->symbol.value -= obj_datasec (abfd)->vma; - cache_ptr->symbol.section = obj_datasec (abfd); - break; - case N_BSS: - cache_ptr->symbol.section = obj_bsssec (abfd); - cache_ptr->symbol.value -= obj_bsssec (abfd)->vma; - break; - default: - case N_ABS: + case N_INDR: case N_INDR | N_EXT: + /* An indirect symbol. This consists of two symbols in a row. + The first symbol is the name of the indirection. The second + symbol is the name of the target. A reference to the first + symbol becomes a reference to the second. */ + cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT | visible; - cache_ptr->symbol.section = &bfd_abs_section; - break; - } - } - else - { + /* @@ Stuffing pointers into integers is a no-no. We can + usually get away with it if the integer is large enough + though. */ + if (sizeof (cache_ptr + 1) > sizeof (bfd_vma)) + abort (); + cache_ptr->symbol.value = (bfd_vma) (cache_ptr + 1); - if (sym_is_fortrancommon (cache_ptr)) - { - cache_ptr->symbol.flags = 0; - cache_ptr->symbol.section = &bfd_com_section; - } - else - { + cache_ptr->symbol.section = bfd_ind_section_ptr; + break; - } + case N_WEAKU: + cache_ptr->symbol.section = bfd_und_section_ptr; + cache_ptr->symbol.flags = BSF_WEAK; + break; - /* In a.out, the value of a symbol is always relative to the - * start of the file, if this is a data symbol we'll subtract - * the size of the text section to get the section relative - * value. If this is a bss symbol (which would be strange) - * we'll subtract the size of the previous two sections - * to find the section relative address. - */ + case N_WEAKA: + cache_ptr->symbol.section = bfd_abs_section_ptr; + cache_ptr->symbol.flags = BSF_WEAK; + break; - if (sym_in_text_section (cache_ptr)) - { - cache_ptr->symbol.value -= obj_textsec (abfd)->vma; - cache_ptr->symbol.section = obj_textsec (abfd); - } - else if (sym_in_data_section (cache_ptr)) - { - cache_ptr->symbol.value -= obj_datasec (abfd)->vma; - cache_ptr->symbol.section = obj_datasec (abfd); - } - else if (sym_in_bss_section (cache_ptr)) - { - cache_ptr->symbol.section = obj_bsssec (abfd); - cache_ptr->symbol.value -= obj_bsssec (abfd)->vma; - } - else if (sym_is_undefined (cache_ptr)) - { - cache_ptr->symbol.flags = 0; - cache_ptr->symbol.section = &bfd_und_section; - } - else if (sym_is_absolute (cache_ptr)) - { - cache_ptr->symbol.section = &bfd_abs_section; - } + case N_WEAKT: + cache_ptr->symbol.section = obj_textsec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = BSF_WEAK; + break; - if (sym_is_global_defn (cache_ptr)) - { - cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT; - } - else - { - cache_ptr->symbol.flags = BSF_LOCAL; - } - } + case N_WEAKD: + cache_ptr->symbol.section = obj_datasec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = BSF_WEAK; + break; + + case N_WEAKB: + cache_ptr->symbol.section = obj_bsssec (abfd); + cache_ptr->symbol.value -= cache_ptr->symbol.section->vma; + cache_ptr->symbol.flags = BSF_WEAK; + break; } - if (cache_ptr->symbol.section == 0) - abort (); + + return true; } +/* Set the fields of SYM_POINTER according to CACHE_PTR. */ - -static void -DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd), - struct external_nlist *sym_pointer AND - asymbol *cache_ptr AND - bfd *abfd) +static boolean +translate_to_native_sym_flags (abfd, cache_ptr, sym_pointer) + bfd *abfd; + asymbol *cache_ptr; + struct external_nlist *sym_pointer; { bfd_vma value = cache_ptr->value; - /* mask out any existing type bits in case copying from one section - to another */ + /* Mask out any existing type bits in case copying from one section + to another. */ sym_pointer->e_type[0] &= ~N_TYPE; - - /* We attempt to order these tests by decreasing frequency of success, - according to tcov when linking the linker. */ - if (bfd_get_output_section(cache_ptr) == &bfd_abs_section) { + if (bfd_is_abs_section (bfd_get_section (cache_ptr))) sym_pointer->e_type[0] |= N_ABS; - } - else if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) { + else if (bfd_get_section (cache_ptr) == obj_textsec (abfd) + || (bfd_get_section (cache_ptr)->output_section + == obj_textsec (abfd))) sym_pointer->e_type[0] |= N_TEXT; - } - else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) { + else if (bfd_get_section (cache_ptr) == obj_datasec (abfd) + || (bfd_get_section (cache_ptr)->output_section + == obj_datasec (abfd))) sym_pointer->e_type[0] |= N_DATA; - } - else if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) { + else if (bfd_get_section (cache_ptr) == obj_bsssec (abfd) + || (bfd_get_section (cache_ptr)->output_section + == obj_bsssec (abfd))) sym_pointer->e_type[0] |= N_BSS; - } - else if (bfd_get_output_section(cache_ptr) == &bfd_und_section) + else if (bfd_get_section (cache_ptr) == NULL) { - sym_pointer->e_type[0] = (N_UNDF | N_EXT); + /* Protect the bfd_is_com_section call. This case occurs, e.g., + for the *DEBUG* section of a COFF file. */ + bfd_set_error (bfd_error_nonrepresentable_section); + return false; } - else if (bfd_get_output_section(cache_ptr) == &bfd_ind_section) + else if (bfd_is_und_section (bfd_get_section (cache_ptr))) + sym_pointer->e_type[0] = N_UNDF | N_EXT; + else if (bfd_is_ind_section (bfd_get_section (cache_ptr))) + sym_pointer->e_type[0] = N_INDR; + else if (bfd_is_com_section (bfd_get_section (cache_ptr))) + sym_pointer->e_type[0] = N_UNDF | N_EXT; + else { - sym_pointer->e_type[0] = N_INDR; + bfd_set_error (bfd_error_nonrepresentable_section); + return false; } - else if (bfd_is_com_section (bfd_get_output_section (cache_ptr))) { - sym_pointer->e_type[0] = (N_UNDF | N_EXT); - } - else { - if (cache_ptr->section->output_section) - { - bfd_error_vector.nonrepresentable_section(abfd, - bfd_get_output_section(cache_ptr)->name); - } - else - { - bfd_error_vector.nonrepresentable_section(abfd, - cache_ptr->section->name); - - } - - } /* Turn the symbol from section relative to absolute again */ + value += cache_ptr->section->vma; - value += cache_ptr->section->output_section->vma + cache_ptr->section->output_offset ; + if ((cache_ptr->flags & BSF_WARNING) != 0) + sym_pointer->e_type[0] = N_WARNING; - - if (cache_ptr->flags & (BSF_WARNING)) { - (sym_pointer+1)->e_type[0] = 1; - } - - if (cache_ptr->flags & BSF_DEBUGGING) { - sym_pointer->e_type[0] = ((aout_symbol_type *)cache_ptr)->type; - } - else if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) { + if ((cache_ptr->flags & BSF_DEBUGGING) != 0) + sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type; + else if ((cache_ptr->flags & BSF_GLOBAL) != 0) sym_pointer->e_type[0] |= N_EXT; - } - if (cache_ptr->flags & BSF_CONSTRUCTOR) { - int type = ((aout_symbol_type *)cache_ptr)->type; - switch (type) - { - case N_ABS: type = N_SETA; break; - case N_TEXT: type = N_SETT; break; - case N_DATA: type = N_SETD; break; - case N_BSS: type = N_SETB; break; - } - sym_pointer->e_type[0] = type; - } + + if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0) + { + int type = ((aout_symbol_type *) cache_ptr)->type; + switch (type) + { + case N_ABS: type = N_SETA; break; + case N_TEXT: type = N_SETT; break; + case N_DATA: type = N_SETD; break; + case N_BSS: type = N_SETB; break; + } + sym_pointer->e_type[0] = type; + } + + if ((cache_ptr->flags & BSF_WEAK) != 0) + { + int type; + + switch (sym_pointer->e_type[0] & N_TYPE) + { + default: + case N_ABS: type = N_WEAKA; break; + case N_TEXT: type = N_WEAKT; break; + case N_DATA: type = N_WEAKD; break; + case N_BSS: type = N_WEAKB; break; + case N_UNDF: type = N_WEAKU; break; + } + sym_pointer->e_type[0] = type; + } PUT_WORD(abfd, value, sym_pointer->e_value); + + return true; } /* Native-level interface to symbols. */ -/* We read the symbols into a buffer, which is discarded when this -function exits. We read the strings into a buffer large enough to -hold them all plus all the cached symbol entries. */ - asymbol * -DEFUN(NAME(aout,make_empty_symbol),(abfd), - bfd *abfd) +NAME(aout,make_empty_symbol) (abfd) + bfd *abfd; { aout_symbol_type *new = (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type)); + if (!new) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } new->symbol.the_bfd = abfd; return &new->symbol; } +/* Translate a set of internal symbols into external symbols. */ + boolean -DEFUN(NAME(aout,slurp_symbol_table),(abfd), - bfd *abfd) +NAME(aout,translate_symbol_table) (abfd, in, ext, count, str, strsize, dynamic) + bfd *abfd; + aout_symbol_type *in; + struct external_nlist *ext; + bfd_size_type count; + char *str; + bfd_size_type strsize; + boolean dynamic; { - bfd_size_type symbol_size; - bfd_size_type string_size; - unsigned char string_chars[BYTES_IN_WORD]; - struct external_nlist *syms; - char *strings; - aout_symbol_type *cached; + struct external_nlist *ext_end; - /* If there's no work to be done, don't do any */ - if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true; - symbol_size = exec_hdr(abfd)->a_syms; - if (symbol_size == 0) + ext_end = ext + count; + for (; ext < ext_end; ext++, in++) { - bfd_error = no_symbols; - return false; + bfd_vma x; + + x = GET_WORD (abfd, ext->e_strx); + in->symbol.the_bfd = abfd; + + /* For the normal symbols, the zero index points at the number + of bytes in the string table but is to be interpreted as the + null string. For the dynamic symbols, the number of bytes in + the string table is stored in the __DYNAMIC structure and the + zero index points at an actual string. */ + if (x == 0 && ! dynamic) + in->symbol.name = ""; + else if (x < strsize) + in->symbol.name = str + x; + else + return false; + + in->symbol.value = GET_SWORD (abfd, ext->e_value); + in->desc = bfd_h_get_16 (abfd, ext->e_desc); + in->other = bfd_h_get_8 (abfd, ext->e_other); + in->type = bfd_h_get_8 (abfd, ext->e_type); + in->symbol.udata = 0; + + if (! translate_from_native_sym_flags (abfd, in)) + return false; + + if (dynamic) + in->symbol.flags |= BSF_DYNAMIC; } - bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET); - if (bfd_read ((PTR)string_chars, BYTES_IN_WORD, 1, abfd) != BYTES_IN_WORD) - return false; - string_size = GET_WORD (abfd, string_chars); - - strings =(char *) bfd_alloc(abfd, string_size + 1); - cached = (aout_symbol_type *) - bfd_zalloc(abfd, (bfd_size_type)(bfd_get_symcount (abfd) * sizeof(aout_symbol_type))); - - /* malloc this, so we can free it if simply. The symbol caching - might want to allocate onto the bfd's obstack */ - syms = (struct external_nlist *) bfd_xmalloc(symbol_size); - bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET); - if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size) - { - bailout: - if (syms) - free (syms); - if (cached) - bfd_release (abfd, cached); - if (strings) - bfd_release (abfd, strings); - return false; - } - - bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET); - if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size) - { - goto bailout; - } - strings[string_size] = 0; /* Just in case. */ - - /* OK, now walk the new symtable, cacheing symbol properties */ - { - register struct external_nlist *sym_pointer; - register struct external_nlist *sym_end = syms + bfd_get_symcount (abfd); - register aout_symbol_type *cache_ptr = cached; - - /* Run through table and copy values */ - for (sym_pointer = syms, cache_ptr = cached; - sym_pointer < sym_end; sym_pointer ++, cache_ptr++) - { - long x = GET_WORD(abfd, sym_pointer->e_strx); - cache_ptr->symbol.the_bfd = abfd; - if (x == 0) - cache_ptr->symbol.name = ""; - else if (x >= 0 && x < string_size) - cache_ptr->symbol.name = x + strings; - else - goto bailout; - - cache_ptr->symbol.value = GET_SWORD(abfd, sym_pointer->e_value); - cache_ptr->desc = bfd_h_get_16(abfd, sym_pointer->e_desc); - cache_ptr->other = bfd_h_get_8(abfd, sym_pointer->e_other); - cache_ptr->type = bfd_h_get_8(abfd, sym_pointer->e_type); - cache_ptr->symbol.udata = 0; - translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd); - } - } - - obj_aout_symbols (abfd) = cached; - free((PTR)syms); - return true; } +/* We read the symbols into a buffer, which is discarded when this + function exits. We read the strings into a buffer large enough to + hold them all plus all the cached symbol entries. */ + +boolean +NAME(aout,slurp_symbol_table) (abfd) + bfd *abfd; +{ + struct external_nlist *old_external_syms; + aout_symbol_type *cached; + size_t cached_size; + + /* If there's no work to be done, don't do any */ + if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL) + return true; + + old_external_syms = obj_aout_external_syms (abfd); + + if (! aout_get_external_symbols (abfd)) + return false; + + if (obj_aout_external_sym_count (abfd) == 0) + { + bfd_set_error (bfd_error_no_symbols); + return false; + } + + cached_size = (obj_aout_external_sym_count (abfd) + * sizeof (aout_symbol_type)); + cached = (aout_symbol_type *) malloc (cached_size); + if (cached == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + memset (cached, 0, cached_size); + + /* Convert from external symbol information to internal. */ + if (! (NAME(aout,translate_symbol_table) + (abfd, cached, + obj_aout_external_syms (abfd), + obj_aout_external_sym_count (abfd), + obj_aout_external_strings (abfd), + obj_aout_external_string_size (abfd), + false))) + { + free (cached); + return false; + } + + bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd); + + obj_aout_symbols (abfd) = cached; + + /* It is very likely that anybody who calls this function will not + want the external symbol information, so if it was allocated + because of our call to aout_get_external_symbols, we free it up + right away to save space. */ + if (old_external_syms == (struct external_nlist *) NULL + && obj_aout_external_syms (abfd) != (struct external_nlist *) NULL) + { + free (obj_aout_external_syms (abfd)); + obj_aout_external_syms (abfd) = NULL; + } + + return true; +} -/* Possible improvements: +/* We use a hash table when writing out symbols so that we only write + out a particular string once. This helps particularly when the + linker writes out stabs debugging entries, because each different + contributing object file tends to have many duplicate stabs + strings. + + Possible improvements: + look for strings matching trailing substrings of other strings + better data structures? balanced trees? - + smaller per-string or per-symbol data? re-use some of the symbol's - data fields? - + also look at reducing memory use elsewhere -- maybe if we didn't have to - construct the entire symbol table at once, we could get by with smaller - amounts of VM? (What effect does that have on the string table - reductions?) - + rip this out of here, put it into its own file in bfd or libiberty, so - coff and elf can use it too. I'll work on this soon, but have more - pressing tasks right now. + + look at reducing memory use elsewhere -- maybe if we didn't have + to construct the entire symbol table at once, we could get by + with smaller amounts of VM? (What effect does that have on the + string table reductions?) - A hash table might(?) be more efficient for handling exactly the cases that - are handled now, but for trailing substring matches, I think we want to - examine the `nearest' values (reverse-)lexically, not merely impose a strict - order, nor look only for exact-match or not-match. I don't think a hash - table would be very useful for that, and I don't feel like fleshing out two - completely different implementations. [raeburn:930419.0331EDT] */ + This hash table code breaks dbx on SunOS 4.1.3, so we don't do it + if BFD_TRADITIONAL_FORMAT is set. */ -struct stringtab_entry { - /* Hash value for this string. Only useful so long as we aren't doing - substring matches. */ - unsigned int hash; +/* An entry in the strtab hash table. */ - /* Next node to look at, depending on whether the hash value of the string - being searched for is less than or greater than the hash value of the - current node. For now, `equal to' is lumped in with `greater than', for - space efficiency. It's not a common enough case to warrant another field - to be used for all nodes. */ - struct stringtab_entry *less; - struct stringtab_entry *greater; - - /* The string itself. */ - CONST char *string; - - /* The index allocated for this string. */ +struct strtab_hash_entry +{ + struct bfd_hash_entry root; + /* Index in string table. */ bfd_size_type index; - -#ifdef GATHER_STATISTICS - /* How many references have there been to this string? (Not currently used; - could be dumped out for anaylsis, if anyone's interested.) */ - unsigned long count; -#endif - - /* Next node in linked list, in suggested output order. */ - struct stringtab_entry *next_to_output; + /* Next string in strtab. */ + struct strtab_hash_entry *next; }; -struct stringtab_data { - /* Tree of string table entries. */ - struct stringtab_entry *strings; +/* The strtab hash table. */ - /* Fudge factor used to center top node of tree. */ - int hash_zero; - - /* Next index value to issue. */ - bfd_size_type index; - - /* Index used for empty strings. Cached here because checking for them - is really easy, and we can avoid searching the tree. */ - bfd_size_type empty_string_index; - - /* These fields indicate the two ends of a singly-linked list that indicates - the order strings should be written out in. Use this order, and no - seeking will need to be done, so output efficiency should be maximized. */ - struct stringtab_entry **end; - struct stringtab_entry *output_order; - -#ifdef GATHER_STATISTICS - /* Number of strings which duplicate strings already in the table. */ - unsigned long duplicates; - - /* Number of bytes saved by not having to write all the duplicate strings. */ - unsigned long bytes_saved; - - /* Number of zero-length strings. Currently, these all turn into - references to the null byte at the end of the first string. In some - cases (possibly not all? explore this...), it should be possible to - simply write out a zero index value. */ - unsigned long empty_strings; - - /* Number of times the hash values matched but the strings were different. - Note that this includes the number of times the other string(s) occurs, so - there may only be two strings hashing to the same value, even if this - number is very large. */ - unsigned long bad_hash_matches; - - /* Null strings aren't counted in this one. - This will probably only be nonzero if we've got an input file - which was produced by `ld -r' (i.e., it's already been processed - through this code). Under some operating systems, native tools - may make all empty strings have the same index; but the pointer - check won't catch those, because to get to that stage we'd already - have to compute the checksum, which requires reading the string, - so we short-circuit that case with empty_string_index above. */ - unsigned long pointer_matches; - - /* Number of comparisons done. I figure with the algorithms in use below, - the average number of comparisons done (per symbol) should be roughly - log-base-2 of the number of unique strings. */ - unsigned long n_compares; -#endif +struct strtab_hash +{ + struct bfd_hash_table table; + /* Size of strtab--also next available index. */ + bfd_size_type size; + /* First string in strtab. */ + struct strtab_hash_entry *first; + /* Last string in strtab. */ + struct strtab_hash_entry *last; }; -/* Some utility functions for the string table code. */ +static struct bfd_hash_entry *strtab_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +static boolean stringtab_init PARAMS ((struct strtab_hash *)); +static bfd_size_type add_to_stringtab + PARAMS ((bfd *, struct strtab_hash *, const char *, boolean)); +static boolean emit_stringtab PARAMS ((bfd *, struct strtab_hash *)); -/* For speed, only hash on the first this many bytes of strings. - This number was chosen by profiling ld linking itself, with -g. */ -#define HASHMAXLEN 25 +/* Routine to create an entry in a strtab. */ -#define HASH_CHAR(c) (sum ^= sum >> 20, sum ^= sum << 7, sum += (c)) - -static INLINE unsigned int -hash (string, len) - unsigned char *string; - register unsigned int len; +static struct bfd_hash_entry * +strtab_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; { - register unsigned int sum = 0; + struct strtab_hash_entry *ret = (struct strtab_hash_entry *) entry; - if (len > HASHMAXLEN) + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct strtab_hash_entry *) NULL) + ret = ((struct strtab_hash_entry *) + bfd_hash_allocate (table, sizeof (struct strtab_hash_entry))); + if (ret == (struct strtab_hash_entry *) NULL) { - HASH_CHAR (len); - len = HASHMAXLEN; + bfd_set_error (bfd_error_no_memory); + return NULL; } - while (len--) + /* Call the allocation method of the superclass. */ + ret = ((struct strtab_hash_entry *) + bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); + + if (ret) { - HASH_CHAR (*string++); + /* Initialize the local fields. */ + ret->index = (bfd_size_type) -1; + ret->next = NULL; } - return sum; + + return (struct bfd_hash_entry *) ret; } -static INLINE void -stringtab_init (tab) - struct stringtab_data *tab; +/* Look up an entry in an strtab. */ + +#define strtab_hash_lookup(t, string, create, copy) \ + ((struct strtab_hash_entry *) \ + bfd_hash_lookup (&(t)->table, (string), (create), (copy))) + +/* Create a new strtab. */ + +static boolean +stringtab_init (table) + struct strtab_hash *table; { - tab->strings = 0; - tab->output_order = 0; - tab->end = &tab->output_order; + if (! bfd_hash_table_init (&table->table, strtab_hash_newfunc)) + return false; - /* Initial string table length includes size of length field. */ - tab->index = BYTES_IN_WORD; - tab->empty_string_index = -1; -#ifdef GATHER_STATISTICS - tab->duplicates = 0; - tab->empty_strings = 0; - tab->bad_hash_matches = 0; - tab->pointer_matches = 0; - tab->bytes_saved = 0; - tab->n_compares = 0; -#endif + /* Leave space for the size of the string table. */ + table->size = BYTES_IN_WORD; + + table->first = NULL; + table->last = NULL; + + return true; } -static INLINE int -compare (entry, str, hash) - struct stringtab_entry *entry; - CONST char *str; - unsigned int hash; -{ - return hash - entry->hash; -} +/* Free a strtab. */ -#ifdef GATHER_STATISTICS -/* Don't want to have to link in math library with all bfd applications... */ -static INLINE double -log2 (num) - int num; -{ - double d = num; - int n = 0; - while (d >= 2.0) - n++, d /= 2.0; - return ((d > 1.41) ? 0.5 : 0) + n; -} -#endif +#define stringtab_free(tab) bfd_hash_table_free (&(tab)->table) -/* Main string table routines. */ -/* Returns index in string table. Whether or not this actually adds an - entry into the string table should be irrelevant -- it just has to - return a valid index. */ -static bfd_size_type -add_to_stringtab (abfd, str, tab, check) +/* Get the index of a string in a strtab, adding it if it is not + already present. If HASH is false, we don't really use the hash + table, and we don't eliminate duplicate strings. */ + +static INLINE bfd_size_type +add_to_stringtab (abfd, tab, str, copy) bfd *abfd; - CONST char *str; - struct stringtab_data *tab; - int check; + struct strtab_hash *tab; + const char *str; + boolean copy; { - struct stringtab_entry **ep; - register struct stringtab_entry *entry; - unsigned int hashval, len; + register struct strtab_hash_entry *entry; - if (str[0] == 0) + /* An index of 0 always means the empty string. */ + if (*str == '\0') + return 0; + + if ((abfd->flags & BFD_TRADITIONAL_FORMAT) == 0) { - bfd_size_type index; - CONST bfd_size_type minus_one = -1; - -#ifdef GATHER_STATISTICS - tab->empty_strings++; -#endif - index = tab->empty_string_index; - if (index != minus_one) - { - got_empty: -#ifdef GATHER_STATISTICS - tab->bytes_saved++; - tab->duplicates++; -#endif - return index; - } - - /* Need to find it. */ - entry = tab->strings; - if (entry) - { - index = entry->index + strlen (entry->string); - tab->empty_string_index = index; - goto got_empty; - } - len = 0; + entry = strtab_hash_lookup (tab, str, true, copy); + if (entry == NULL) + return (bfd_size_type) -1; } else - len = strlen (str); - - /* The hash_zero value is chosen such that the first symbol gets a value of - zero. With a balanced tree, this wouldn't be very useful, but without it, - we might get a more even split at the top level, instead of skewing it - badly should hash("/usr/lib/crt0.o") (or whatever) be far from zero. */ - hashval = hash (str, len) ^ tab->hash_zero; - ep = &tab->strings; - if (!*ep) { - tab->hash_zero = hashval; - hashval = 0; - goto add_it; - } - - while (*ep) - { - register int cmp; - - entry = *ep; -#ifdef GATHER_STATISTICS - tab->n_compares++; -#endif - cmp = compare (entry, str, hashval); - /* The not-equal cases are more frequent, so check them first. */ - if (cmp > 0) - ep = &entry->greater; - else if (cmp < 0) - ep = &entry->less; + entry = ((struct strtab_hash_entry *) + bfd_hash_allocate (&tab->table, + sizeof (struct strtab_hash_entry))); + if (entry == NULL) + return (bfd_size_type) -1; + if (! copy) + entry->root.string = str; else { - if (entry->string == str) - { -#ifdef GATHER_STATISTICS - tab->pointer_matches++; -#endif - goto match; - } - /* Compare the first bytes to save a function call if they - don't match. */ - if (entry->string[0] == str[0] && !strcmp (entry->string, str)) - { - match: -#ifdef GATHER_STATISTICS - entry->count++; - tab->bytes_saved += len + 1; - tab->duplicates++; -#endif - /* If we're in the linker, and the new string is from a new - input file which might have already had these reductions - run over it, we want to keep the new string pointer. I - don't think we're likely to see any (or nearly as many, - at least) cases where a later string is in the same location - as an earlier one rather than this one. */ - entry->string = str; - return entry->index; - } -#ifdef GATHER_STATISTICS - tab->bad_hash_matches++; -#endif - ep = &entry->greater; + char *n; + + n = (char *) bfd_hash_allocate (&tab->table, strlen (str) + 1); + if (n == NULL) + return (bfd_size_type) -1; + entry->root.string = n; } + entry->index = (bfd_size_type) -1; + entry->next = NULL; } - /* If we get here, nothing that's in the table already matched. - EP points to the `next' field at the end of the chain; stick a - new entry on here. */ - add_it: - entry = (struct stringtab_entry *) - bfd_alloc_by_size_t (abfd, sizeof (struct stringtab_entry)); + if (entry->index == (bfd_size_type) -1) + { + entry->index = tab->size; + tab->size += strlen (str) + 1; + if (tab->first == NULL) + tab->first = entry; + else + tab->last->next = entry; + tab->last = entry; + } - entry->less = entry->greater = 0; - entry->hash = hashval; - entry->index = tab->index; - entry->string = str; - entry->next_to_output = 0; -#ifdef GATHER_STATISTICS - entry->count = 1; -#endif - - assert (*tab->end == 0); - *(tab->end) = entry; - tab->end = &entry->next_to_output; - assert (*tab->end == 0); - - { - tab->index += len + 1; - if (len == 0) - tab->empty_string_index = entry->index; - } - assert (*ep == 0); - *ep = entry; return entry->index; } -static void -emit_strtab (abfd, tab) - bfd *abfd; - struct stringtab_data *tab; +/* Write out a strtab. ABFD is already at the right location in the + file. */ + +static boolean +emit_stringtab (abfd, tab) + register bfd *abfd; + struct strtab_hash *tab; { - struct stringtab_entry *entry; -#ifdef GATHER_STATISTICS - int count = 0; -#endif + bfd_byte buffer[BYTES_IN_WORD]; + register struct strtab_hash_entry *entry; - /* Be sure to put string length into correct byte ordering before writing - it out. */ - char buffer[BYTES_IN_WORD]; + PUT_WORD (abfd, tab->size, buffer); + if (bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd) != BYTES_IN_WORD) + return false; - PUT_WORD (abfd, tab->index, (unsigned char *) buffer); - bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd); - - for (entry = tab->output_order; entry; entry = entry->next_to_output) + for (entry = tab->first; entry != NULL; entry = entry->next) { - bfd_write ((PTR) entry->string, 1, strlen (entry->string) + 1, abfd); -#ifdef GATHER_STATISTICS - count++; -#endif + register const char *str; + register size_t len; + + str = entry->root.string; + len = strlen (str) + 1; + if (bfd_write ((PTR) str, 1, len, abfd) != len) + return false; } -#ifdef GATHER_STATISTICS - /* Short form only, for now. - To do: Specify output file. Conditionalize on environment? Detailed - analysis if desired. */ - { - int n_syms = bfd_get_symcount (abfd); - - fprintf (stderr, "String table data for output file:\n"); - fprintf (stderr, " %8d symbols output\n", n_syms); - fprintf (stderr, " %8d duplicate strings\n", tab->duplicates); - fprintf (stderr, " %8d empty strings\n", tab->empty_strings); - fprintf (stderr, " %8d unique strings output\n", count); - fprintf (stderr, " %8d pointer matches\n", tab->pointer_matches); - fprintf (stderr, " %8d bytes saved\n", tab->bytes_saved); - fprintf (stderr, " %8d bad hash matches\n", tab->bad_hash_matches); - fprintf (stderr, " %8d hash-val comparisons\n", tab->n_compares); - if (n_syms) - { - double n_compares = tab->n_compares; - double avg_compares = n_compares / n_syms; - /* The second value here should usually be near one. */ - fprintf (stderr, - "\t average %f comparisons per symbol (%f * log2 nstrings)\n", - avg_compares, avg_compares / log2 (count)); - } - } -#endif - -/* Old code: - unsigned int count; - generic = bfd_get_outsymbols(abfd); - for (count = 0; count < bfd_get_symcount(abfd); count++) - { - asymbol *g = *(generic++); - - if (g->name) - { - size_t length = strlen(g->name)+1; - bfd_write((PTR)g->name, 1, length, abfd); - } - g->KEEPIT = (KEEPITTYPE) count; - } */ + return true; } - -void -DEFUN(NAME(aout,write_syms),(abfd), - bfd *abfd) + +boolean +NAME(aout,write_syms) (abfd) + bfd *abfd; { unsigned int count ; asymbol **generic = bfd_get_outsymbols (abfd); - struct stringtab_data strtab; + struct strtab_hash strtab; - stringtab_init (&strtab); + if (! stringtab_init (&strtab)) + return false; for (count = 0; count < bfd_get_symcount (abfd); count++) { asymbol *g = generic[count]; + bfd_size_type indx; struct external_nlist nsp; - if (g->name) - PUT_WORD (abfd, add_to_stringtab (abfd, g->name, &strtab), - (unsigned char *) nsp.e_strx); - else - PUT_WORD (abfd, 0, (unsigned char *)nsp.e_strx); + indx = add_to_stringtab (abfd, &strtab, g->name, false); + if (indx == (bfd_size_type) -1) + goto error_return; + PUT_WORD (abfd, indx, (bfd_byte *) nsp.e_strx); if (bfd_asymbol_flavour(g) == abfd->xvec->flavour) { @@ -1837,28 +1941,41 @@ DEFUN(NAME(aout,write_syms),(abfd), bfd_h_put_8(abfd, 0, nsp.e_type); } - translate_to_native_sym_flags (&nsp, g, abfd); + if (! translate_to_native_sym_flags (abfd, g, &nsp)) + goto error_return; - bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd); + if (bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd) + != EXTERNAL_NLIST_SIZE) + goto error_return; /* NB: `KEEPIT' currently overlays `flags', so set this only here, at the end. */ g->KEEPIT = count; } - emit_strtab (abfd, &strtab); + if (! emit_stringtab (abfd, &strtab)) + goto error_return; + + stringtab_free (&strtab); + + return true; + +error_return: + stringtab_free (&strtab); + return false; } -unsigned int -DEFUN(NAME(aout,get_symtab),(abfd, location), - bfd *abfd AND - asymbol **location) +long +NAME(aout,get_symtab) (abfd, location) + bfd *abfd; + asymbol **location; { unsigned int counter = 0; aout_symbol_type *symbase; - if (!NAME(aout,slurp_symbol_table)(abfd)) return 0; + if (!NAME(aout,slurp_symbol_table)(abfd)) + return -1; for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);) *(location++) = (asymbol *)( symbase++); @@ -1871,10 +1988,10 @@ DEFUN(NAME(aout,get_symtab),(abfd, location), /* Output standard relocation information to a file in target byte order. */ void -DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), - bfd *abfd AND - arelent *g AND - struct reloc_std_external *natptr) +NAME(aout,swap_std_reloc_out) (abfd, g, natptr) + bfd *abfd; + arelent *g; + struct reloc_std_external *natptr; { int r_index; asymbol *sym = *(g->sym_ptr_ptr); @@ -1882,7 +1999,6 @@ DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), unsigned int r_length; int r_pcrel; int r_baserel, r_jmptable, r_relative; - unsigned int r_addend; asection *output_section = sym->section->output_section; PUT_WORD(abfd, g->address, natptr->r_address); @@ -1891,11 +2007,13 @@ DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */ /* XXX This relies on relocs coming from a.out files. */ r_baserel = (g->howto->type & 8) != 0; - /* r_jmptable, r_relative??? FIXME-soon */ - r_jmptable = 0; - r_relative = 0; + r_jmptable = (g->howto->type & 16) != 0; + r_relative = (g->howto->type & 32) != 0; +#if 0 + /* For a standard reloc, the addend is in the object file. */ r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma; +#endif /* name was clobbered by aout_write_syms to be symbol index */ @@ -1909,10 +2027,10 @@ DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), if (bfd_is_com_section (output_section) - || output_section == &bfd_abs_section - || output_section == &bfd_und_section) + || bfd_is_abs_section (output_section) + || bfd_is_und_section (output_section)) { - if (bfd_abs_section.symbol == sym) + if (bfd_abs_section_ptr->symbol == sym) { /* Whoops, looked like an abs symbol, but is really an offset from the abs section */ @@ -1965,10 +2083,10 @@ DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr), /* Output extended relocation information to a file in target byte order. */ void -DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr), - bfd *abfd AND - arelent *g AND - register struct reloc_ext_external *natptr) +NAME(aout,swap_ext_reloc_out) (abfd, g, natptr) + bfd *abfd; + arelent *g; + register struct reloc_ext_external *natptr; { int r_index; int r_extern; @@ -1991,10 +2109,10 @@ DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr), check for that here. */ if (bfd_is_com_section (output_section) - || output_section == &bfd_abs_section - || output_section == &bfd_und_section) + || bfd_is_abs_section (output_section) + || bfd_is_und_section (output_section)) { - if (bfd_abs_section.symbol == sym) + if (bfd_abs_section_ptr->symbol == sym) { /* Whoops, looked like an abs symbol, but is really an offset from the abs section */ @@ -2070,18 +2188,18 @@ DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr), default: \ case N_ABS: \ case N_ABS | N_EXT: \ - cache_ptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr; \ + cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \ cache_ptr->addend = ad; \ break; \ } \ } \ void -DEFUN(NAME(aout,swap_ext_reloc_in), (abfd, bytes, cache_ptr, symbols), - bfd *abfd AND - struct reloc_ext_external *bytes AND - arelent *cache_ptr AND - asymbol **symbols) +NAME(aout,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols) + bfd *abfd; + struct reloc_ext_external *bytes; + arelent *cache_ptr; + asymbol **symbols; { int r_index; int r_extern; @@ -2112,11 +2230,11 @@ DEFUN(NAME(aout,swap_ext_reloc_in), (abfd, bytes, cache_ptr, symbols), } void -DEFUN(NAME(aout,swap_std_reloc_in), (abfd, bytes, cache_ptr, symbols), - bfd *abfd AND - struct reloc_std_external *bytes AND - arelent *cache_ptr AND - asymbol **symbols) +NAME(aout,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols) + bfd *abfd; + struct reloc_std_external *bytes; + arelent *cache_ptr; + asymbol **symbols; { int r_index; int r_extern; @@ -2153,109 +2271,111 @@ DEFUN(NAME(aout,swap_std_reloc_in), (abfd, bytes, cache_ptr, symbols), >> RELOC_STD_BITS_LENGTH_SH_LITTLE; } - howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel; + howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel + + 16 * r_jmptable + 32 * r_relative; BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); cache_ptr->howto = howto_table_std + howto_idx; BFD_ASSERT (cache_ptr->howto->type != -1); - BFD_ASSERT (r_jmptable == 0); - BFD_ASSERT (r_relative == 0); - /* FIXME-soon: Roll jmptable, relative bits into howto setting */ MOVE_ADDRESS(0); } -/* Reloc hackery */ +/* Read and swap the relocs for a section. */ boolean -DEFUN(NAME(aout,slurp_reloc_table),(abfd, asect, symbols), - bfd *abfd AND - sec_ptr asect AND - asymbol **symbols) +NAME(aout,slurp_reloc_table) (abfd, asect, symbols) + bfd *abfd; + sec_ptr asect; + asymbol **symbols; { unsigned int count; bfd_size_type reloc_size; PTR relocs; arelent *reloc_cache; size_t each_size; + unsigned int counter = 0; + arelent *cache_ptr; - if (asect->relocation) return true; + if (asect->relocation) + return true; - if (asect->flags & SEC_CONSTRUCTOR) return true; + if (asect->flags & SEC_CONSTRUCTOR) + return true; - if (asect == obj_datasec (abfd)) { + if (asect == obj_datasec (abfd)) reloc_size = exec_hdr(abfd)->a_drsize; - goto doit; - } - - if (asect == obj_textsec (abfd)) { + else if (asect == obj_textsec (abfd)) reloc_size = exec_hdr(abfd)->a_trsize; - goto doit; - } + else if (asect == obj_bsssec (abfd)) + reloc_size = 0; + else + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } - bfd_error = invalid_operation; - return false; + if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0) + return false; - doit: - bfd_seek (abfd, asect->rel_filepos, SEEK_SET); each_size = obj_reloc_entry_size (abfd); count = reloc_size / each_size; - - reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t)(count * sizeof - (arelent))); - if (!reloc_cache) { -nomem: - bfd_error = no_memory; - return false; - } - - relocs = (PTR) bfd_alloc (abfd, reloc_size); - if (!relocs) { - bfd_release (abfd, reloc_cache); - goto nomem; - } - - if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) { - bfd_release (abfd, relocs); - bfd_release (abfd, reloc_cache); - bfd_error = system_call_error; - return false; - } - - if (each_size == RELOC_EXT_SIZE) { - register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs; - unsigned int counter = 0; - arelent *cache_ptr = reloc_cache; - - for (; counter < count; counter++, rptr++, cache_ptr++) { - NAME(aout,swap_ext_reloc_in)(abfd, rptr, cache_ptr, symbols); + reloc_cache = (arelent *) malloc ((size_t) (count * sizeof (arelent))); + if (reloc_cache == NULL && count != 0) + { + bfd_set_error (bfd_error_no_memory); + return false; } - } else { - register struct reloc_std_external *rptr = (struct reloc_std_external*) relocs; - unsigned int counter = 0; - arelent *cache_ptr = reloc_cache; + memset (reloc_cache, 0, count * sizeof (arelent)); - for (; counter < count; counter++, rptr++, cache_ptr++) { - NAME(aout,swap_std_reloc_in)(abfd, rptr, cache_ptr, symbols); + relocs = malloc (reloc_size); + if (relocs == NULL && reloc_size != 0) + { + free (reloc_cache); + bfd_set_error (bfd_error_no_memory); + return false; } - } + if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) + { + free (relocs); + free (reloc_cache); + return false; + } + + cache_ptr = reloc_cache; + if (each_size == RELOC_EXT_SIZE) + { + register struct reloc_ext_external *rptr = + (struct reloc_ext_external *) relocs; + + for (; counter < count; counter++, rptr++, cache_ptr++) + NAME(aout,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols); + } + else + { + register struct reloc_std_external *rptr = + (struct reloc_std_external *) relocs; + + for (; counter < count; counter++, rptr++, cache_ptr++) + MY_swap_std_reloc_in(abfd, rptr, cache_ptr, symbols); + } + + free (relocs); - bfd_release (abfd,relocs); asect->relocation = reloc_cache; - asect->reloc_count = count; + asect->reloc_count = cache_ptr - reloc_cache; + return true; } - - /* Write out a relocation section into an object file. */ boolean -DEFUN(NAME(aout,squirt_out_relocs),(abfd, section), - bfd *abfd AND - asection *section) +NAME(aout,squirt_out_relocs) (abfd, section) + bfd *abfd; + asection *section; { arelent **generic; unsigned char *native, *natptr; @@ -2270,7 +2390,7 @@ DEFUN(NAME(aout,squirt_out_relocs),(abfd, section), natsize = each_size * count; native = (unsigned char *) bfd_zalloc (abfd, natsize); if (!native) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } @@ -2288,7 +2408,7 @@ DEFUN(NAME(aout,squirt_out_relocs),(abfd, section), for (natptr = native; count != 0; --count, natptr += each_size, ++generic) - NAME(aout,swap_std_reloc_out)(abfd, *generic, (struct reloc_std_external *)natptr); + MY_swap_std_reloc_out(abfd, *generic, (struct reloc_std_external *)natptr); } if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) { @@ -2301,18 +2421,24 @@ DEFUN(NAME(aout,squirt_out_relocs),(abfd, section), } /* This is stupid. This function should be a boolean predicate */ -unsigned int -DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols), - bfd *abfd AND - sec_ptr section AND - arelent **relptr AND - asymbol **symbols) +long +NAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols) + bfd *abfd; + sec_ptr section; + arelent **relptr; + asymbol **symbols; { arelent *tblptr = section->relocation; unsigned int count; + if (section == obj_bsssec (abfd)) + { + *relptr = NULL; + return 0; + } + if (!(tblptr || NAME(aout,slurp_reloc_table)(abfd, section, symbols))) - return 0; + return -1; if (section->flags & SEC_CONSTRUCTOR) { arelent_chain *chain = section->constructor_chain; @@ -2323,7 +2449,6 @@ DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols), } else { tblptr = section->relocation; - if (!tblptr) return 0; for (count = 0; count++ < section->reloc_count;) { @@ -2335,56 +2460,65 @@ DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols), return section->reloc_count; } -unsigned int -DEFUN(NAME(aout,get_reloc_upper_bound),(abfd, asect), - bfd *abfd AND - sec_ptr asect) +long +NAME(aout,get_reloc_upper_bound) (abfd, asect) + bfd *abfd; + sec_ptr asect; { if (bfd_get_format (abfd) != bfd_object) { - bfd_error = invalid_operation; - return 0; + bfd_set_error (bfd_error_invalid_operation); + return -1; } if (asect->flags & SEC_CONSTRUCTOR) { return (sizeof (arelent *) * (asect->reloc_count+1)); } - if (asect == obj_datasec (abfd)) - return (sizeof (arelent *) * - ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd)) - +1)); + return (sizeof (arelent *) + * ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd)) + + 1)); if (asect == obj_textsec (abfd)) - return (sizeof (arelent *) * - ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd)) - +1)); + return (sizeof (arelent *) + * ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd)) + + 1)); - bfd_error = invalid_operation; - return 0; + if (asect == obj_bsssec (abfd)) + return sizeof (arelent *); + + if (asect == obj_bsssec (abfd)) + return 0; + + bfd_set_error (bfd_error_invalid_operation); + return -1; } - unsigned int -DEFUN(NAME(aout,get_symtab_upper_bound),(abfd), - bfd *abfd) +long +NAME(aout,get_symtab_upper_bound) (abfd) + bfd *abfd; { - if (!NAME(aout,slurp_symbol_table)(abfd)) return 0; + if (!NAME(aout,slurp_symbol_table)(abfd)) + return -1; return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *)); } + +/*ARGSUSED*/ alent * -DEFUN(NAME(aout,get_lineno),(ignore_abfd, ignore_symbol), - bfd *ignore_abfd AND - asymbol *ignore_symbol) +NAME(aout,get_lineno) (ignore_abfd, ignore_symbol) + bfd *ignore_abfd; + asymbol *ignore_symbol; { return (alent *)NULL; } +/*ARGSUSED*/ void -DEFUN(NAME(aout,get_symbol_info),(ignore_abfd, symbol, ret), - bfd *ignore_abfd AND - asymbol *symbol AND - symbol_info *ret) +NAME(aout,get_symbol_info) (ignore_abfd, symbol, ret) + bfd *ignore_abfd; + asymbol *symbol; + symbol_info *ret; { bfd_symbol_info (symbol, ret); @@ -2406,12 +2540,13 @@ DEFUN(NAME(aout,get_symbol_info),(ignore_abfd, symbol, ret), } } +/*ARGSUSED*/ void -DEFUN(NAME(aout,print_symbol),(ignore_abfd, afile, symbol, how), - bfd *ignore_abfd AND - PTR afile AND - asymbol *symbol AND - bfd_print_symbol_type how) +NAME(aout,print_symbol) (ignore_abfd, afile, symbol, how) + bfd *ignore_abfd; + PTR afile; + asymbol *symbol; + bfd_print_symbol_type how; { FILE *file = (FILE *)afile; @@ -2451,20 +2586,15 @@ DEFUN(NAME(aout,print_symbol),(ignore_abfd, afile, symbol, how), */ boolean -DEFUN(NAME(aout,find_nearest_line),(abfd, - section, - symbols, - offset, - filename_ptr, - functionname_ptr, - line_ptr), - bfd *abfd AND - asection *section AND - asymbol **symbols AND - bfd_vma offset AND - CONST char **filename_ptr AND - CONST char **functionname_ptr AND - unsigned int *line_ptr) +NAME(aout,find_nearest_line) + (abfd, section, symbols, offset, filename_ptr, functionname_ptr, line_ptr) + bfd *abfd; + asection *section; + asymbol **symbols; + bfd_vma offset; + CONST char **filename_ptr; + CONST char **functionname_ptr; + unsigned int *line_ptr; { /* Run down the file looking for the filename, function and linenumber */ asymbol **p; @@ -2528,7 +2658,18 @@ DEFUN(NAME(aout,find_nearest_line),(abfd, if (*line_ptr && func) { CONST char *function = func->name; char *p; - strncpy(buffer, function, sizeof(buffer)-1); + + /* The caller expects a symbol name. We actually have a + function name, without the leading underscore. Put the + underscore back in, so that the caller gets a symbol + name. */ + if (bfd_get_symbol_leading_char (abfd) == '\0') + strncpy (buffer, function, sizeof (buffer) - 1); + else + { + buffer[0] = bfd_get_symbol_leading_char (abfd); + strncpy (buffer + 1, function, sizeof (buffer) - 2); + } buffer[sizeof(buffer)-1] = 0; /* Have to remove : stuff */ p = strchr(buffer,':'); @@ -2559,10 +2700,2295 @@ DEFUN(NAME(aout,find_nearest_line),(abfd, } +/*ARGSUSED*/ int -DEFUN(NAME(aout,sizeof_headers),(abfd, execable), - bfd *abfd AND - boolean execable) +NAME(aout,sizeof_headers) (abfd, execable) + bfd *abfd; + boolean execable; { return adata(abfd).exec_bytes_size; } + +/* Free all information we have cached for this BFD. We can always + read it again later if we need it. */ + +boolean +NAME(aout,bfd_free_cached_info) (abfd) + bfd *abfd; +{ + asection *o; + + if (bfd_get_format (abfd) != bfd_object) + return true; + +#define BFCI_FREE(x) if (x != NULL) { free (x); x = NULL; } + BFCI_FREE (obj_aout_symbols (abfd)); + BFCI_FREE (obj_aout_external_syms (abfd)); + BFCI_FREE (obj_aout_external_strings (abfd)); + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + BFCI_FREE (o->relocation); +#undef BFCI_FREE + + return true; +} + +/* a.out link code. */ + +static boolean aout_link_add_object_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean aout_link_check_archive_element + PARAMS ((bfd *, struct bfd_link_info *, boolean *)); +static boolean aout_link_free_symbols PARAMS ((bfd *)); +static boolean aout_link_check_ar_symbols + PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded)); +static boolean aout_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Routine to create an entry in an a.out link hash table. */ + +struct bfd_hash_entry * +NAME(aout,link_hash_newfunc) (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct aout_link_hash_entry *ret = (struct aout_link_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct aout_link_hash_entry *) NULL) + ret = ((struct aout_link_hash_entry *) + bfd_hash_allocate (table, sizeof (struct aout_link_hash_entry))); + if (ret == (struct aout_link_hash_entry *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return (struct bfd_hash_entry *) ret; + } + + /* Call the allocation method of the superclass. */ + ret = ((struct aout_link_hash_entry *) + _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, + table, string)); + if (ret) + { + /* Set local fields. */ + ret->written = false; + ret->indx = -1; + } + + return (struct bfd_hash_entry *) ret; +} + +/* Initialize an a.out link hash table. */ + +boolean +NAME(aout,link_hash_table_init) (table, abfd, newfunc) + struct aout_link_hash_table *table; + bfd *abfd; + struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *)); +{ + return _bfd_link_hash_table_init (&table->root, abfd, newfunc); +} + +/* Create an a.out link hash table. */ + +struct bfd_link_hash_table * +NAME(aout,link_hash_table_create) (abfd) + bfd *abfd; +{ + struct aout_link_hash_table *ret; + + ret = ((struct aout_link_hash_table *) + malloc (sizeof (struct aout_link_hash_table))); + if (ret == (struct aout_link_hash_table *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return (struct bfd_link_hash_table *) NULL; + } + if (! NAME(aout,link_hash_table_init) (ret, abfd, + NAME(aout,link_hash_newfunc))) + { + free (ret); + return (struct bfd_link_hash_table *) NULL; + } + return &ret->root; +} + +/* Given an a.out BFD, add symbols to the global hash table as + appropriate. */ + +boolean +NAME(aout,link_add_symbols) (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + switch (bfd_get_format (abfd)) + { + case bfd_object: + return aout_link_add_object_symbols (abfd, info); + case bfd_archive: + return _bfd_generic_link_add_archive_symbols + (abfd, info, aout_link_check_archive_element); + default: + bfd_set_error (bfd_error_wrong_format); + return false; + } +} + +/* Add symbols from an a.out object file. */ + +static boolean +aout_link_add_object_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + if (! aout_get_external_symbols (abfd)) + return false; + if (! aout_link_add_symbols (abfd, info)) + return false; + if (! info->keep_memory) + { + if (! aout_link_free_symbols (abfd)) + return false; + } + return true; +} + +/* Check a single archive element to see if we need to include it in + the link. *PNEEDED is set according to whether this element is + needed in the link or not. This is called from + _bfd_generic_link_add_archive_symbols. */ + +static boolean +aout_link_check_archive_element (abfd, info, pneeded) + bfd *abfd; + struct bfd_link_info *info; + boolean *pneeded; +{ + if (! aout_get_external_symbols (abfd)) + return false; + + if (! aout_link_check_ar_symbols (abfd, info, pneeded)) + return false; + + if (*pneeded) + { + if (! aout_link_add_symbols (abfd, info)) + return false; + } + + /* We keep around the symbols even if we aren't going to use this + object file, because we may want to reread it. This doesn't + waste too much memory, because it isn't all that common to read + an archive element but not need it. */ + if (! info->keep_memory) + { + if (! aout_link_free_symbols (abfd)) + return false; + } + + return true; +} + +/* Free up the internal symbols read from an a.out file. */ + +static boolean +aout_link_free_symbols (abfd) + bfd *abfd; +{ + if (obj_aout_external_syms (abfd) != (struct external_nlist *) NULL) + { + free ((PTR) obj_aout_external_syms (abfd)); + obj_aout_external_syms (abfd) = (struct external_nlist *) NULL; + } + if (obj_aout_external_strings (abfd) != (char *) NULL) + { + free ((PTR) obj_aout_external_strings (abfd)); + obj_aout_external_strings (abfd) = (char *) NULL; + } + return true; +} + +/* Look through the internal symbols to see if this object file should + be included in the link. We should include this object file if it + defines any symbols which are currently undefined. If this object + file defines a common symbol, then we may adjust the size of the + known symbol but we do not include the object file in the link + (unless there is some other reason to include it). */ + +static boolean +aout_link_check_ar_symbols (abfd, info, pneeded) + bfd *abfd; + struct bfd_link_info *info; + boolean *pneeded; +{ + register struct external_nlist *p; + struct external_nlist *pend; + char *strings; + + *pneeded = false; + + /* Look through all the symbols. */ + p = obj_aout_external_syms (abfd); + pend = p + obj_aout_external_sym_count (abfd); + strings = obj_aout_external_strings (abfd); + for (; p < pend; p++) + { + int type = bfd_h_get_8 (abfd, p->e_type); + const char *name; + struct bfd_link_hash_entry *h; + + /* Ignore symbols that are not externally visible. This is an + optimization only, as we check the type more thoroughly + below. */ + if (((type & N_EXT) == 0 + || (type & N_STAB) != 0 + || type == N_FN) + && type != N_WEAKA + && type != N_WEAKT + && type != N_WEAKD + && type != N_WEAKB) + { + if (type == N_WARNING + || type == N_INDR) + ++p; + continue; + } + + name = strings + GET_WORD (abfd, p->e_strx); + h = bfd_link_hash_lookup (info->hash, name, false, false, true); + + /* We are only interested in symbols that are currently + undefined or common. */ + if (h == (struct bfd_link_hash_entry *) NULL + || (h->type != bfd_link_hash_undefined + && h->type != bfd_link_hash_common)) + { + if (type == (N_INDR | N_EXT)) + ++p; + continue; + } + + if (type == (N_TEXT | N_EXT) + || type == (N_DATA | N_EXT) + || type == (N_BSS | N_EXT) + || type == (N_ABS | N_EXT) + || type == (N_INDR | N_EXT)) + { + /* This object file defines this symbol. We must link it + in. This is true regardless of whether the current + definition of the symbol is undefined or common. If the + current definition is common, we have a case in which we + have already seen an object file including + int a; + and this object file from the archive includes + int a = 5; + In such a case we must include this object file. + + FIXME: The SunOS 4.1.3 linker will pull in the archive + element if the symbol is defined in the .data section, + but not if it is defined in the .text section. That + seems a bit crazy to me, and I haven't implemented it. + However, it might be correct. */ + if (! (*info->callbacks->add_archive_element) (info, abfd, name)) + return false; + *pneeded = true; + return true; + } + + if (type == (N_UNDF | N_EXT)) + { + bfd_vma value; + + value = GET_WORD (abfd, p->e_value); + if (value != 0) + { + /* This symbol is common in the object from the archive + file. */ + if (h->type == bfd_link_hash_undefined) + { + bfd *symbfd; + + symbfd = h->u.undef.abfd; + if (symbfd == (bfd *) NULL) + { + /* This symbol was created as undefined from + outside BFD. We assume that we should link + in the object file. This is done for the -u + option in the linker. */ + if (! (*info->callbacks->add_archive_element) (info, + abfd, + name)) + return false; + *pneeded = true; + return true; + } + /* Turn the current link symbol into a common + symbol. It is already on the undefs list. */ + h->type = bfd_link_hash_common; + h->u.c.size = value; + h->u.c.section = bfd_make_section_old_way (symbfd, + "COMMON"); + } + else + { + /* Adjust the size of the common symbol if + necessary. */ + if (value > h->u.c.size) + h->u.c.size = value; + } + } + } + + if (type == N_WEAKA + || type == N_WEAKT + || type == N_WEAKD + || type == N_WEAKB) + { + /* This symbol is weak but defined. We must pull it in if + the current link symbol is undefined, but we don't want + it if the current link symbol is common. */ + if (h->type == bfd_link_hash_undefined) + { + if (! (*info->callbacks->add_archive_element) (info, abfd, name)) + return false; + *pneeded = true; + return true; + } + } + } + + /* We do not need this object file. */ + return true; +} + +/* Add all symbols from an object file to the hash table. */ + +static boolean +aout_link_add_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + boolean (*add_one_symbol) PARAMS ((struct bfd_link_info *, bfd *, + const char *, flagword, asection *, + bfd_vma, const char *, boolean, + boolean, + struct bfd_link_hash_entry **)); + bfd_size_type sym_count; + char *strings; + boolean copy; + struct aout_link_hash_entry **sym_hash; + register struct external_nlist *p; + struct external_nlist *pend; + + sym_count = obj_aout_external_sym_count (abfd); + strings = obj_aout_external_strings (abfd); + if (info->keep_memory) + copy = false; + else + copy = true; + + /* We keep a list of the linker hash table entries that correspond + to particular symbols. We could just look them up in the hash + table, but keeping the list is more efficient. Perhaps this + should be conditional on info->keep_memory. */ + sym_hash = ((struct aout_link_hash_entry **) + bfd_alloc (abfd, + ((size_t) sym_count + * sizeof (struct aout_link_hash_entry *)))); + if (sym_hash == NULL && sym_count != 0) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + obj_aout_sym_hashes (abfd) = sym_hash; + + if ((abfd->flags & DYNAMIC) != 0 + && aout_backend_info (abfd)->add_dynamic_symbols != NULL) + { + if (! (*aout_backend_info (abfd)->add_dynamic_symbols) (abfd, info)) + return false; + } + + add_one_symbol = aout_backend_info (abfd)->add_one_symbol; + if (add_one_symbol == NULL) + add_one_symbol = _bfd_generic_link_add_one_symbol; + + p = obj_aout_external_syms (abfd); + pend = p + sym_count; + for (; p < pend; p++, sym_hash++) + { + int type; + const char *name; + bfd_vma value; + asection *section; + flagword flags; + const char *string; + + *sym_hash = NULL; + + type = bfd_h_get_8 (abfd, p->e_type); + + /* Ignore debugging symbols. */ + if ((type & N_STAB) != 0) + continue; + + name = strings + GET_WORD (abfd, p->e_strx); + value = GET_WORD (abfd, p->e_value); + flags = BSF_GLOBAL; + string = NULL; + switch (type) + { + default: + abort (); + + case N_UNDF: + case N_ABS: + case N_TEXT: + case N_DATA: + case N_BSS: + case N_FN_SEQ: + case N_COMM: + case N_SETV: + case N_FN: + /* Ignore symbols that are not externally visible. */ + continue; + case N_INDR: + /* Ignore local indirect symbol. */ + ++p; + ++sym_hash; + continue; + + case N_UNDF | N_EXT: + if (value == 0) + { + section = bfd_und_section_ptr; + flags = 0; + } + else + section = bfd_com_section_ptr; + break; + case N_ABS | N_EXT: + section = bfd_abs_section_ptr; + break; + case N_TEXT | N_EXT: + section = obj_textsec (abfd); + value -= bfd_get_section_vma (abfd, section); + break; + case N_DATA | N_EXT: + case N_SETV | N_EXT: + /* Treat N_SETV symbols as N_DATA symbol; see comment in + translate_from_native_sym_flags. */ + section = obj_datasec (abfd); + value -= bfd_get_section_vma (abfd, section); + break; + case N_BSS | N_EXT: + section = obj_bsssec (abfd); + value -= bfd_get_section_vma (abfd, section); + break; + case N_INDR | N_EXT: + /* An indirect symbol. The next symbol is the symbol + which this one really is. */ + BFD_ASSERT (p + 1 < pend); + ++p; + string = strings + GET_WORD (abfd, p->e_strx); + section = bfd_ind_section_ptr; + flags |= BSF_INDIRECT; + break; + case N_COMM | N_EXT: + section = bfd_com_section_ptr; + break; + case N_SETA: case N_SETA | N_EXT: + section = bfd_abs_section_ptr; + flags |= BSF_CONSTRUCTOR; + break; + case N_SETT: case N_SETT | N_EXT: + section = obj_textsec (abfd); + flags |= BSF_CONSTRUCTOR; + value -= bfd_get_section_vma (abfd, section); + break; + case N_SETD: case N_SETD | N_EXT: + section = obj_datasec (abfd); + flags |= BSF_CONSTRUCTOR; + value -= bfd_get_section_vma (abfd, section); + break; + case N_SETB: case N_SETB | N_EXT: + section = obj_bsssec (abfd); + flags |= BSF_CONSTRUCTOR; + value -= bfd_get_section_vma (abfd, section); + break; + case N_WARNING: + /* A warning symbol. The next symbol is the one to warn + about. */ + BFD_ASSERT (p + 1 < pend); + ++p; + string = name; + name = strings + GET_WORD (abfd, p->e_strx); + section = bfd_und_section_ptr; + flags |= BSF_WARNING; + break; + case N_WEAKU: + section = bfd_und_section_ptr; + flags = BSF_WEAK; + break; + case N_WEAKA: + section = bfd_abs_section_ptr; + flags = BSF_WEAK; + break; + case N_WEAKT: + section = obj_textsec (abfd); + value -= bfd_get_section_vma (abfd, section); + flags = BSF_WEAK; + break; + case N_WEAKD: + section = obj_datasec (abfd); + value -= bfd_get_section_vma (abfd, section); + flags = BSF_WEAK; + break; + case N_WEAKB: + section = obj_bsssec (abfd); + value -= bfd_get_section_vma (abfd, section); + flags = BSF_WEAK; + break; + } + + if (! ((*add_one_symbol) + (info, abfd, name, flags, section, value, string, copy, false, + (struct bfd_link_hash_entry **) sym_hash))) + return false; + + if (type == (N_INDR | N_EXT) || type == N_WARNING) + ++sym_hash; + } + + return true; +} + +/* During the final link step we need to pass around a bunch of + information, so we do it in an instance of this structure. */ + +struct aout_final_link_info +{ + /* General link information. */ + struct bfd_link_info *info; + /* Output bfd. */ + bfd *output_bfd; + /* Reloc file positions. */ + file_ptr treloff, dreloff; + /* File position of symbols. */ + file_ptr symoff; + /* String table. */ + struct strtab_hash strtab; +}; + +static boolean aout_link_input_bfd + PARAMS ((struct aout_final_link_info *, bfd *input_bfd)); +static boolean aout_link_write_symbols + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, int *symbol_map)); +static boolean aout_link_write_other_symbol + PARAMS ((struct aout_link_hash_entry *, PTR)); +static boolean aout_link_input_section + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, + asection *input_section, file_ptr *reloff_ptr, + bfd_size_type rel_size, int *symbol_map)); +static boolean aout_link_input_section_std + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, + asection *input_section, struct reloc_std_external *, + bfd_size_type rel_size, bfd_byte *contents, int *symbol_map)); +static boolean aout_link_input_section_ext + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, + asection *input_section, struct reloc_ext_external *, + bfd_size_type rel_size, bfd_byte *contents, int *symbol_map)); +static INLINE asection *aout_reloc_index_to_section + PARAMS ((bfd *, int)); +static boolean aout_link_reloc_link_order + PARAMS ((struct aout_final_link_info *, asection *, + struct bfd_link_order *)); + +/* Do the final link step. This is called on the output BFD. The + INFO structure should point to a list of BFDs linked through the + link_next field which can be used to find each BFD which takes part + in the output. Also, each section in ABFD should point to a list + of bfd_link_order structures which list all the input sections for + the output section. */ + +boolean +NAME(aout,final_link) (abfd, info, callback) + bfd *abfd; + struct bfd_link_info *info; + void (*callback) PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); +{ + struct aout_final_link_info aout_info; + register bfd *sub; + bfd_size_type text_size; + file_ptr text_end; + register struct bfd_link_order *p; + asection *o; + boolean have_link_order_relocs; + + aout_info.info = info; + aout_info.output_bfd = abfd; + + if (! info->relocateable) + { + exec_hdr (abfd)->a_trsize = 0; + exec_hdr (abfd)->a_drsize = 0; + } + else + { + bfd_size_type trsize, drsize; + + /* Count up the relocation sizes. */ + trsize = 0; + drsize = 0; + for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) + { + if (bfd_get_flavour (sub) == bfd_target_aout_flavour) + { + trsize += exec_hdr (sub)->a_trsize; + drsize += exec_hdr (sub)->a_drsize; + } + else + { + /* FIXME: We need to identify the .text and .data sections + and call get_reloc_upper_bound and canonicalize_reloc to + work out the number of relocs needed, and then multiply + by the reloc size. */ + abort (); + } + } + if (obj_textsec (abfd) != (asection *) NULL) + trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd) + ->link_order_head) + * obj_reloc_entry_size (abfd)); + exec_hdr (abfd)->a_trsize = trsize; + if (obj_datasec (abfd) != (asection *) NULL) + drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd) + ->link_order_head) + * obj_reloc_entry_size (abfd)); + exec_hdr (abfd)->a_drsize = drsize; + } + + exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd); + + /* Adjust the section sizes and vmas according to the magic number. + This sets a_text, a_data and a_bss in the exec_hdr and sets the + filepos for each section. */ + if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end)) + return false; + + /* The relocation and symbol file positions differ among a.out + targets. We are passed a callback routine from the backend + specific code to handle this. + FIXME: At this point we do not know how much space the symbol + table will require. This will not work for any (nonstandard) + a.out target that needs to know the symbol table size before it + can compute the relocation file positions. This may or may not + be the case for the hp300hpux target, for example. */ + (*callback) (abfd, &aout_info.treloff, &aout_info.dreloff, + &aout_info.symoff); + obj_textsec (abfd)->rel_filepos = aout_info.treloff; + obj_datasec (abfd)->rel_filepos = aout_info.dreloff; + obj_sym_filepos (abfd) = aout_info.symoff; + + /* We keep a count of the symbols as we output them. */ + obj_aout_external_sym_count (abfd) = 0; + + /* We accumulate the string table as we write out the symbols. */ + if (! stringtab_init (&aout_info.strtab)) + return false; + + /* The most time efficient way to do the link would be to read all + the input object files into memory and then sort out the + information into the output file. Unfortunately, that will + probably use too much memory. Another method would be to step + through everything that composes the text section and write it + out, and then everything that composes the data section and write + it out, and then write out the relocs, and then write out the + symbols. Unfortunately, that requires reading stuff from each + input file several times, and we will not be able to keep all the + input files open simultaneously, and reopening them will be slow. + + What we do is basically process one input file at a time. We do + everything we need to do with an input file once--copy over the + section contents, handle the relocation information, and write + out the symbols--and then we throw away the information we read + from it. This approach requires a lot of lseeks of the output + file, which is unfortunate but still faster than reopening a lot + of files. + + We use the output_has_begun field of the input BFDs to see + whether we have already handled it. */ + for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) + sub->output_has_begun = false; + + have_link_order_relocs = false; + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + for (p = o->link_order_head; + p != (struct bfd_link_order *) NULL; + p = p->next) + { + if (p->type == bfd_indirect_link_order + && (bfd_get_flavour (p->u.indirect.section->owner) + == bfd_target_aout_flavour)) + { + bfd *input_bfd; + + input_bfd = p->u.indirect.section->owner; + if (! input_bfd->output_has_begun) + { + if (! aout_link_input_bfd (&aout_info, input_bfd)) + return false; + input_bfd->output_has_begun = true; + } + } + else if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + { + /* These are handled below. */ + have_link_order_relocs = true; + } + else + { + if (! _bfd_default_link_order (abfd, info, o, p)) + return false; + } + } + } + + /* Write out any symbols that we have not already written out. */ + aout_link_hash_traverse (aout_hash_table (info), + aout_link_write_other_symbol, + (PTR) &aout_info); + + /* Now handle any relocs we were asked to create by the linker. + These did not come from any input file. We must do these after + we have written out all the symbols, so that we know the symbol + indices to use. */ + if (have_link_order_relocs) + { + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + for (p = o->link_order_head; + p != (struct bfd_link_order *) NULL; + p = p->next) + { + if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + { + if (! aout_link_reloc_link_order (&aout_info, o, p)) + return false; + } + } + } + } + + /* Finish up any dynamic linking we may be doing. */ + if (aout_backend_info (abfd)->finish_dynamic_link != NULL) + { + if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info)) + return false; + } + + /* Update the header information. */ + abfd->symcount = obj_aout_external_sym_count (abfd); + exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE; + obj_str_filepos (abfd) = obj_sym_filepos (abfd) + exec_hdr (abfd)->a_syms; + obj_textsec (abfd)->reloc_count = + exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd); + obj_datasec (abfd)->reloc_count = + exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd); + + /* Write out the string table. */ + if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0) + return false; + return emit_stringtab (abfd, &aout_info.strtab); +} + +/* Link an a.out input BFD into the output file. */ + +static boolean +aout_link_input_bfd (finfo, input_bfd) + struct aout_final_link_info *finfo; + bfd *input_bfd; +{ + bfd_size_type sym_count; + int *symbol_map = NULL; + + BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object); + + /* If this is a dynamic object, it may need special handling. */ + if ((input_bfd->flags & DYNAMIC) != 0 + && aout_backend_info (input_bfd)->link_dynamic_object != NULL) + { + return ((*aout_backend_info (input_bfd)->link_dynamic_object) + (finfo->info, input_bfd)); + } + + /* Get the symbols. We probably have them already, unless + finfo->info->keep_memory is false. */ + if (! aout_get_external_symbols (input_bfd)) + return false; + + sym_count = obj_aout_external_sym_count (input_bfd); + symbol_map = (int *) malloc ((size_t) sym_count * sizeof (int)); + if (symbol_map == NULL && sym_count != 0) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + /* Write out the symbols and get a map of the new indices. */ + if (! aout_link_write_symbols (finfo, input_bfd, symbol_map)) + goto error_return; + + /* Relocate and write out the sections. */ + if (! aout_link_input_section (finfo, input_bfd, + obj_textsec (input_bfd), + &finfo->treloff, + exec_hdr (input_bfd)->a_trsize, + symbol_map) + || ! aout_link_input_section (finfo, input_bfd, + obj_datasec (input_bfd), + &finfo->dreloff, + exec_hdr (input_bfd)->a_drsize, + symbol_map)) + goto error_return; + + /* If we are not keeping memory, we don't need the symbols any + longer. We still need them if we are keeping memory, because the + strings in the hash table point into them. */ + if (! finfo->info->keep_memory) + { + if (! aout_link_free_symbols (input_bfd)) + goto error_return; + } + + if (symbol_map != NULL) + free (symbol_map); + return true; + error_return: + if (symbol_map != NULL) + free (symbol_map); + return false; +} + +/* Adjust and write out the symbols for an a.out file. Set the new + symbol indices into a symbol_map. */ + +static boolean +aout_link_write_symbols (finfo, input_bfd, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + int *symbol_map; +{ + bfd *output_bfd; + bfd_size_type sym_count; + char *strings; + enum bfd_link_strip strip; + enum bfd_link_discard discard; + struct external_nlist *output_syms = NULL; + struct external_nlist *outsym; + bfd_size_type strtab_index; + register struct external_nlist *sym; + struct external_nlist *sym_end; + struct aout_link_hash_entry **sym_hash; + boolean pass; + boolean skip_indirect; + + output_bfd = finfo->output_bfd; + sym_count = obj_aout_external_sym_count (input_bfd); + strings = obj_aout_external_strings (input_bfd); + strip = finfo->info->strip; + discard = finfo->info->discard; + output_syms = ((struct external_nlist *) + malloc ((size_t) (sym_count + 1) * EXTERNAL_NLIST_SIZE)); + if (output_syms == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + outsym = output_syms; + + /* First write out a symbol for this object file, unless we are + discarding such symbols. */ + if (strip != strip_all + && (strip != strip_some + || bfd_hash_lookup (finfo->info->keep_hash, input_bfd->filename, + false, false) != NULL) + && discard != discard_all) + { + bfd_h_put_8 (output_bfd, N_TEXT, outsym->e_type); + bfd_h_put_8 (output_bfd, 0, outsym->e_other); + bfd_h_put_16 (output_bfd, (bfd_vma) 0, outsym->e_desc); + strtab_index = add_to_stringtab (output_bfd, &finfo->strtab, + input_bfd->filename, false); + if (strtab_index == (bfd_size_type) -1) + goto error_return; + PUT_WORD (output_bfd, strtab_index, outsym->e_strx); + PUT_WORD (output_bfd, + (bfd_get_section_vma (output_bfd, + obj_textsec (input_bfd)->output_section) + + obj_textsec (input_bfd)->output_offset), + outsym->e_value); + ++obj_aout_external_sym_count (output_bfd); + ++outsym; + } + + pass = false; + skip_indirect = false; + sym = obj_aout_external_syms (input_bfd); + sym_end = sym + sym_count; + sym_hash = obj_aout_sym_hashes (input_bfd); + for (; sym < sym_end; sym++, sym_hash++, symbol_map++) + { + const char *name; + int type; + struct aout_link_hash_entry *h; + boolean skip; + asection *symsec; + bfd_vma val = 0; + boolean copy; + + *symbol_map = -1; + + type = bfd_h_get_8 (input_bfd, sym->e_type); + name = strings + GET_WORD (input_bfd, sym->e_strx); + + h = NULL; + + if (pass) + { + /* Pass this symbol through. It is the target of an + indirect or warning symbol. */ + val = GET_WORD (input_bfd, sym->e_value); + pass = false; + } + else if (skip_indirect) + { + /* Skip this symbol, which is the target of an indirect + symbol that we have changed to no longer be an indirect + symbol. */ + skip_indirect = false; + continue; + } + else + { + struct aout_link_hash_entry *hresolve; + + /* We have saved the hash table entry for this symbol, if + there is one. Note that we could just look it up again + in the hash table, provided we first check that it is an + external symbol. */ + h = *sym_hash; + + /* If this is an indirect or warning symbol, then change + hresolve to the base symbol. We also change *sym_hash so + that the relocation routines relocate against the real + symbol. */ + hresolve = h; + if (h != (struct aout_link_hash_entry *) NULL + && (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning)) + { + hresolve = (struct aout_link_hash_entry *) h->root.u.i.link; + while (hresolve->root.type == bfd_link_hash_indirect + || hresolve->root.type == bfd_link_hash_warning) + hresolve = ((struct aout_link_hash_entry *) + hresolve->root.u.i.link); + *sym_hash = hresolve; + } + + /* If the symbol has already been written out, skip it. */ + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type != bfd_link_hash_warning + && h->written) + { + if ((type & N_TYPE) == N_INDR) + skip_indirect = true; + *symbol_map = h->indx; + continue; + } + + /* See if we are stripping this symbol. */ + skip = false; + switch (strip) + { + case strip_none: + break; + case strip_debugger: + if ((type & N_STAB) != 0) + skip = true; + break; + case strip_some: + if (bfd_hash_lookup (finfo->info->keep_hash, name, false, false) + == NULL) + skip = true; + break; + case strip_all: + skip = true; + break; + } + if (skip) + { + if (h != (struct aout_link_hash_entry *) NULL) + h->written = true; + continue; + } + + /* Get the value of the symbol. */ + if ((type & N_TYPE) == N_TEXT + || type == N_WEAKT) + symsec = obj_textsec (input_bfd); + else if ((type & N_TYPE) == N_DATA + || type == N_WEAKD) + symsec = obj_datasec (input_bfd); + else if ((type & N_TYPE) == N_BSS + || type == N_WEAKB) + symsec = obj_bsssec (input_bfd); + else if ((type & N_TYPE) == N_ABS + || type == N_WEAKA) + symsec = bfd_abs_section_ptr; + else if (((type & N_TYPE) == N_INDR + && (hresolve == (struct aout_link_hash_entry *) NULL + || (hresolve->root.type != bfd_link_hash_defined + && hresolve->root.type != bfd_link_hash_common))) + || type == N_WARNING) + { + /* Pass the next symbol through unchanged. The + condition above for indirect symbols is so that if + the indirect symbol was defined, we output it with + the correct definition so the debugger will + understand it. */ + pass = true; + val = GET_WORD (input_bfd, sym->e_value); + symsec = NULL; + } + else if ((type & N_STAB) != 0) + { + val = GET_WORD (input_bfd, sym->e_value); + symsec = NULL; + } + else + { + /* If we get here with an indirect symbol, it means that + we are outputting it with a real definition. In such + a case we do not want to output the next symbol, + which is the target of the indirection. */ + if ((type & N_TYPE) == N_INDR) + skip_indirect = true; + + /* We need to get the value from the hash table. We use + hresolve so that if we have defined an indirect + symbol we output the final definition. */ + if (h == (struct aout_link_hash_entry *) NULL) + val = 0; + else if (hresolve->root.type == bfd_link_hash_defined) + { + asection *input_section; + asection *output_section; + + /* This case means a common symbol which was turned + into a defined symbol. */ + input_section = hresolve->root.u.def.section; + output_section = input_section->output_section; + BFD_ASSERT (bfd_is_abs_section (output_section) + || output_section->owner == output_bfd); + val = (hresolve->root.u.def.value + + bfd_get_section_vma (output_bfd, output_section) + + input_section->output_offset); + + /* Get the correct type based on the section. If + this is a constructed set, force it to be + globally visible. */ + if (type == N_SETT + || type == N_SETD + || type == N_SETB + || type == N_SETA) + type |= N_EXT; + + type &=~ N_TYPE; + + if (output_section == obj_textsec (output_bfd)) + type |= N_TEXT; + else if (output_section == obj_datasec (output_bfd)) + type |= N_DATA; + else if (output_section == obj_bsssec (output_bfd)) + type |= N_BSS; + else + type |= N_ABS; + } + else if (hresolve->root.type == bfd_link_hash_common) + val = hresolve->root.u.c.size; + else if (hresolve->root.type == bfd_link_hash_weak) + { + val = 0; + type = N_WEAKU; + } + else + val = 0; + + symsec = NULL; + } + if (symsec != (asection *) NULL) + val = (symsec->output_section->vma + + symsec->output_offset + + (GET_WORD (input_bfd, sym->e_value) + - symsec->vma)); + + /* If this is a global symbol set the written flag, and if + it is a local symbol see if we should discard it. */ + if (h != (struct aout_link_hash_entry *) NULL) + { + h->written = true; + h->indx = obj_aout_external_sym_count (output_bfd); + } + else + { + switch (discard) + { + case discard_none: + break; + case discard_l: + if (*name == *finfo->info->lprefix + && (finfo->info->lprefix_len == 1 + || strncmp (name, finfo->info->lprefix, + finfo->info->lprefix_len) == 0)) + skip = true; + break; + case discard_all: + skip = true; + break; + } + if (skip) + { + pass = false; + continue; + } + } + } + + /* Copy this symbol into the list of symbols we are going to + write out. */ + bfd_h_put_8 (output_bfd, type, outsym->e_type); + bfd_h_put_8 (output_bfd, bfd_h_get_8 (input_bfd, sym->e_other), + outsym->e_other); + bfd_h_put_16 (output_bfd, bfd_h_get_16 (input_bfd, sym->e_desc), + outsym->e_desc); + copy = false; + if (! finfo->info->keep_memory) + { + /* name points into a string table which we are going to + free. If there is a hash table entry, use that string. + Otherwise, copy name into memory. */ + if (h != (struct aout_link_hash_entry *) NULL) + name = (*sym_hash)->root.root.string; + else + copy = true; + } + strtab_index = add_to_stringtab (output_bfd, &finfo->strtab, + name, copy); + if (strtab_index == (bfd_size_type) -1) + goto error_return; + PUT_WORD (output_bfd, strtab_index, outsym->e_strx); + PUT_WORD (output_bfd, val, outsym->e_value); + *symbol_map = obj_aout_external_sym_count (output_bfd); + ++obj_aout_external_sym_count (output_bfd); + ++outsym; + } + + /* Write out the output symbols we have just constructed. */ + if (outsym > output_syms) + { + bfd_size_type outsym_count; + + if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0) + goto error_return; + outsym_count = outsym - output_syms; + if (bfd_write ((PTR) output_syms, (bfd_size_type) EXTERNAL_NLIST_SIZE, + (bfd_size_type) outsym_count, output_bfd) + != outsym_count * EXTERNAL_NLIST_SIZE) + goto error_return; + finfo->symoff += outsym_count * EXTERNAL_NLIST_SIZE; + } + + if (output_syms != NULL) + free (output_syms); + return true; + error_return: + if (output_syms != NULL) + free (output_syms); + return false; +} + +/* Write out a symbol that was not associated with an a.out input + object. */ + +static boolean +aout_link_write_other_symbol (h, data) + struct aout_link_hash_entry *h; + PTR data; +{ + struct aout_final_link_info *finfo = (struct aout_final_link_info *) data; + bfd *output_bfd; + int type; + bfd_vma val; + struct external_nlist outsym; + bfd_size_type indx; + + output_bfd = finfo->output_bfd; + + if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL) + { + if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol) + (output_bfd, finfo->info, h))) + { + /* FIXME: No way to handle errors. */ + abort (); + } + } + + if (h->written) + return true; + + h->written = true; + + if (finfo->info->strip == strip_all + || (finfo->info->strip == strip_some + && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string, + false, false) == NULL)) + return true; + + switch (h->root.type) + { + default: + case bfd_link_hash_new: + abort (); + /* Avoid variable not initialized warnings. */ + return true; + case bfd_link_hash_undefined: + type = N_UNDF | N_EXT; + val = 0; + break; + case bfd_link_hash_defined: + { + asection *sec; + + sec = h->root.u.def.section->output_section; + BFD_ASSERT (bfd_is_abs_section (sec) + || sec->owner == output_bfd); + if (sec == obj_textsec (output_bfd)) + type = N_TEXT | N_EXT; + else if (sec == obj_datasec (output_bfd)) + type = N_DATA | N_EXT; + else if (sec == obj_bsssec (output_bfd)) + type = N_BSS | N_EXT; + else + type = N_ABS | N_EXT; + val = (h->root.u.def.value + + sec->vma + + h->root.u.def.section->output_offset); + } + break; + case bfd_link_hash_common: + type = N_UNDF | N_EXT; + val = h->root.u.c.size; + break; + case bfd_link_hash_weak: + type = N_WEAKU; + val = 0; + case bfd_link_hash_indirect: + case bfd_link_hash_warning: + /* FIXME: Ignore these for now. The circumstances under which + they should be written out are not clear to me. */ + return true; + } + + bfd_h_put_8 (output_bfd, type, outsym.e_type); + bfd_h_put_8 (output_bfd, 0, outsym.e_other); + bfd_h_put_16 (output_bfd, 0, outsym.e_desc); + indx = add_to_stringtab (output_bfd, &finfo->strtab, h->root.root.string, + false); + if (indx == (bfd_size_type) -1) + { + /* FIXME: No way to handle errors. */ + abort (); + } + PUT_WORD (output_bfd, indx, outsym.e_strx); + PUT_WORD (output_bfd, val, outsym.e_value); + + if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0 + || bfd_write ((PTR) &outsym, (bfd_size_type) EXTERNAL_NLIST_SIZE, + (bfd_size_type) 1, output_bfd) != EXTERNAL_NLIST_SIZE) + { + /* FIXME: No way to handle errors. */ + abort (); + } + + finfo->symoff += EXTERNAL_NLIST_SIZE; + h->indx = obj_aout_external_sym_count (output_bfd); + ++obj_aout_external_sym_count (output_bfd); + + return true; +} + +/* Link an a.out section into the output file. */ + +static boolean +aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr, + rel_size, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + asection *input_section; + file_ptr *reloff_ptr; + bfd_size_type rel_size; + int *symbol_map; +{ + bfd_size_type input_size; + bfd_byte *contents = NULL; + PTR relocs; + PTR free_relocs = NULL; + + /* Get the section contents. */ + input_size = bfd_section_size (input_bfd, input_section); + contents = (bfd_byte *) malloc (input_size); + if (contents == NULL && input_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + if (! bfd_get_section_contents (input_bfd, input_section, (PTR) contents, + (file_ptr) 0, input_size)) + goto error_return; + + /* Read in the relocs if we haven't already done it. */ + if (aout_section_data (input_section) != NULL + && aout_section_data (input_section)->relocs != NULL) + relocs = aout_section_data (input_section)->relocs; + else + { + relocs = free_relocs = (PTR) malloc (rel_size); + if (relocs == NULL && rel_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0 + || bfd_read (relocs, 1, rel_size, input_bfd) != rel_size) + goto error_return; + } + + /* Relocate the section contents. */ + if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE) + { + if (! aout_link_input_section_std (finfo, input_bfd, input_section, + (struct reloc_std_external *) relocs, + rel_size, contents, symbol_map)) + goto error_return; + } + else + { + if (! aout_link_input_section_ext (finfo, input_bfd, input_section, + (struct reloc_ext_external *) relocs, + rel_size, contents, symbol_map)) + goto error_return; + } + + /* Write out the section contents. */ + if (! bfd_set_section_contents (finfo->output_bfd, + input_section->output_section, + (PTR) contents, + input_section->output_offset, + input_size)) + goto error_return; + + /* If we are producing relocateable output, the relocs were + modified, and we now write them out. */ + if (finfo->info->relocateable) + { + if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0) + goto error_return; + if (bfd_write (relocs, (bfd_size_type) 1, rel_size, finfo->output_bfd) + != rel_size) + goto error_return; + *reloff_ptr += rel_size; + + /* Assert that the relocs have not run into the symbols, and + that if these are the text relocs they have not run into the + data relocs. */ + BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) + && (reloff_ptr != &finfo->treloff + || (*reloff_ptr + <= obj_datasec (finfo->output_bfd)->rel_filepos))); + } + + if (free_relocs != NULL) + free (free_relocs); + if (contents != NULL) + free (contents); + return true; + error_return: + if (free_relocs != NULL) + free (free_relocs); + if (contents != NULL) + free (contents); + return false; +} + +/* Get the section corresponding to a reloc index. */ + +static INLINE asection * +aout_reloc_index_to_section (abfd, indx) + bfd *abfd; + int indx; +{ + switch (indx & N_TYPE) + { + case N_TEXT: + return obj_textsec (abfd); + case N_DATA: + return obj_datasec (abfd); + case N_BSS: + return obj_bsssec (abfd); + case N_ABS: + case N_UNDF: + return bfd_abs_section_ptr; + default: + abort (); + } +} + +/* Relocate an a.out section using standard a.out relocs. */ + +static boolean +aout_link_input_section_std (finfo, input_bfd, input_section, relocs, + rel_size, contents, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + asection *input_section; + struct reloc_std_external *relocs; + bfd_size_type rel_size; + bfd_byte *contents; + int *symbol_map; +{ + boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *, + bfd *, asection *, + struct aout_link_hash_entry *, + PTR, boolean *)); + bfd *output_bfd; + boolean relocateable; + struct external_nlist *syms; + char *strings; + struct aout_link_hash_entry **sym_hashes; + bfd_size_type reloc_count; + register struct reloc_std_external *rel; + struct reloc_std_external *rel_end; + + output_bfd = finfo->output_bfd; + check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; + + BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE); + BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p + == output_bfd->xvec->header_byteorder_big_p); + + relocateable = finfo->info->relocateable; + syms = obj_aout_external_syms (input_bfd); + strings = obj_aout_external_strings (input_bfd); + sym_hashes = obj_aout_sym_hashes (input_bfd); + + reloc_count = rel_size / RELOC_STD_SIZE; + rel = relocs; + rel_end = rel + reloc_count; + for (; rel < rel_end; rel++) + { + bfd_vma r_addr; + int r_index; + int r_extern; + int r_pcrel; + int r_baserel; + int r_jmptable; + int r_relative; + int r_length; + int howto_idx; + reloc_howto_type *howto; + bfd_vma relocation; + bfd_reloc_status_type r; + + r_addr = GET_SWORD (input_bfd, rel->r_address); + +#ifdef MY_reloc_howto + howto = MY_reloc_howto(input_bfd, rel, r_index, r_extern, r_pcrel); +#else + if (input_bfd->xvec->header_byteorder_big_p) + { + r_index = ((rel->r_index[0] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[2]); + r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); + r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); + r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); + r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); + r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG)); + r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_BIG) + >> RELOC_STD_BITS_LENGTH_SH_BIG); + } + else + { + r_index = ((rel->r_index[2] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[0]); + r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE)); + r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); + r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE)); + r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE)); + r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE)); + r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) + >> RELOC_STD_BITS_LENGTH_SH_LITTLE); + } + + howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel + + 16 * r_jmptable + 32 * r_relative; + BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); + howto = howto_table_std + howto_idx; +#endif + + if (relocateable) + { + /* We are generating a relocateable output file, and must + modify the reloc accordingly. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + /* If we know the symbol this relocation is against, + convert it into a relocation against a section. This + is what the native linker does. */ + h = sym_hashes[r_index]; + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + asection *output_section; + + /* Change the r_extern value. */ + if (output_bfd->xvec->header_byteorder_big_p) + rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG; + else + rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE; + + /* Compute a new r_index. */ + output_section = h->root.u.def.section->output_section; + if (output_section == obj_textsec (output_bfd)) + r_index = N_TEXT; + else if (output_section == obj_datasec (output_bfd)) + r_index = N_DATA; + else if (output_section == obj_bsssec (output_bfd)) + r_index = N_BSS; + else + r_index = N_ABS; + + /* Add the symbol value and the section VMA to the + addend stored in the contents. */ + relocation = (h->root.u.def.value + + output_section->vma + + h->root.u.def.section->output_offset); + } + else + { + /* We must change r_index according to the symbol + map. */ + r_index = symbol_map[r_index]; + + if (r_index == -1) + { + const char *name; + + name = strings + GET_WORD (input_bfd, + syms[r_index].e_strx); + if (! ((*finfo->info->callbacks->unattached_reloc) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + r_index = 0; + } + + relocation = 0; + } + + /* Write out the new r_index value. */ + if (output_bfd->xvec->header_byteorder_big_p) + { + rel->r_index[0] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[2] = r_index; + } + else + { + rel->r_index[2] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[0] = r_index; + } + } + else + { + asection *section; + + /* This is a relocation against a section. We must + adjust by the amount that the section moved. */ + section = aout_reloc_index_to_section (input_bfd, r_index); + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + } + + /* Change the address of the relocation. */ + PUT_WORD (output_bfd, + r_addr + input_section->output_offset, + rel->r_address); + + /* Adjust a PC relative relocation by removing the reference + to the original address in the section and including the + reference to the new address. */ + if (r_pcrel) + relocation -= (input_section->output_section->vma + + input_section->output_offset + - input_section->vma); + + if (relocation == 0) + r = bfd_reloc_ok; + else + r = _bfd_relocate_contents (howto, + input_bfd, relocation, + contents + r_addr); + } + else + { + /* We are generating an executable, and must do a full + relocation. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + h = sym_hashes[r_index]; + + if (check_dynamic_reloc != NULL) + { + boolean skip; + + if (! ((*check_dynamic_reloc) + (finfo->info, input_bfd, input_section, h, + (PTR) rel, &skip))) + return false; + if (skip) + continue; + } + + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + relocation = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + } + else if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_weak) + relocation = 0; + else + { + const char *name; + + name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); + if (! ((*finfo->info->callbacks->undefined_symbol) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + relocation = 0; + } + } + else + { + asection *section; + + section = aout_reloc_index_to_section (input_bfd, r_index); + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + if (r_pcrel) + relocation += input_section->vma; + } + + r = _bfd_final_link_relocate (howto, + input_bfd, input_section, + contents, r_addr, relocation, + (bfd_vma) 0); + } + + if (r != bfd_reloc_ok) + { + switch (r) + { + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + { + const char *name; + + if (r_extern) + name = strings + GET_WORD (input_bfd, + syms[r_index].e_strx); + else + { + asection *s; + + s = aout_reloc_index_to_section (input_bfd, r_index); + name = bfd_section_name (input_bfd, s); + } + if (! ((*finfo->info->callbacks->reloc_overflow) + (finfo->info, name, howto->name, + (bfd_vma) 0, input_bfd, input_section, r_addr))) + return false; + } + break; + } + } + } + + return true; +} + +/* Relocate an a.out section using extended a.out relocs. */ + +static boolean +aout_link_input_section_ext (finfo, input_bfd, input_section, relocs, + rel_size, contents, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + asection *input_section; + struct reloc_ext_external *relocs; + bfd_size_type rel_size; + bfd_byte *contents; + int *symbol_map; +{ + boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *, + bfd *, asection *, + struct aout_link_hash_entry *, + PTR, boolean *)); + bfd *output_bfd; + boolean relocateable; + struct external_nlist *syms; + char *strings; + struct aout_link_hash_entry **sym_hashes; + bfd_size_type reloc_count; + register struct reloc_ext_external *rel; + struct reloc_ext_external *rel_end; + + output_bfd = finfo->output_bfd; + check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc; + + BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_EXT_SIZE); + BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p + == output_bfd->xvec->header_byteorder_big_p); + + relocateable = finfo->info->relocateable; + syms = obj_aout_external_syms (input_bfd); + strings = obj_aout_external_strings (input_bfd); + sym_hashes = obj_aout_sym_hashes (input_bfd); + + reloc_count = rel_size / RELOC_EXT_SIZE; + rel = relocs; + rel_end = rel + reloc_count; + for (; rel < rel_end; rel++) + { + bfd_vma r_addr; + int r_index; + int r_extern; + int r_type; + bfd_vma r_addend; + bfd_vma relocation; + + r_addr = GET_SWORD (input_bfd, rel->r_address); + + if (input_bfd->xvec->header_byteorder_big_p) + { + r_index = ((rel->r_index[0] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[2]); + r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); + r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) + >> RELOC_EXT_BITS_TYPE_SH_BIG); + } + else + { + r_index = ((rel->r_index[2] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[0]); + r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); + r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) + >> RELOC_EXT_BITS_TYPE_SH_LITTLE); + } + + r_addend = GET_SWORD (input_bfd, rel->r_addend); + + BFD_ASSERT (r_type >= 0 + && r_type < TABLE_SIZE (howto_table_ext)); + + if (relocateable) + { + /* We are generating a relocateable output file, and must + modify the reloc accordingly. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + /* If we know the symbol this relocation is against, + convert it into a relocation against a section. This + is what the native linker does. */ + h = sym_hashes[r_index]; + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + asection *output_section; + + /* Change the r_extern value. */ + if (output_bfd->xvec->header_byteorder_big_p) + rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG; + else + rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE; + + /* Compute a new r_index. */ + output_section = h->root.u.def.section->output_section; + if (output_section == obj_textsec (output_bfd)) + r_index = N_TEXT; + else if (output_section == obj_datasec (output_bfd)) + r_index = N_DATA; + else if (output_section == obj_bsssec (output_bfd)) + r_index = N_BSS; + else + r_index = N_ABS; + + /* Add the symbol value and the section VMA to the + addend. */ + relocation = (h->root.u.def.value + + output_section->vma + + h->root.u.def.section->output_offset); + + /* Now RELOCATION is the VMA of the final + destination. If this is a PC relative reloc, + then ADDEND is the negative of the source VMA. + We want to set ADDEND to the difference between + the destination VMA and the source VMA, which + means we must adjust RELOCATION by the change in + the source VMA. This is done below. */ + } + else + { + /* We must change r_index according to the symbol + map. */ + r_index = symbol_map[r_index]; + + if (r_index == -1) + { + const char *name; + + name = (strings + + GET_WORD (input_bfd, syms[r_index].e_strx)); + if (! ((*finfo->info->callbacks->unattached_reloc) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + r_index = 0; + } + + relocation = 0; + + /* If this is a PC relative reloc, then the addend + is the negative of the source VMA. We must + adjust it by the change in the source VMA. This + is done below. */ + } + + /* Write out the new r_index value. */ + if (output_bfd->xvec->header_byteorder_big_p) + { + rel->r_index[0] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[2] = r_index; + } + else + { + rel->r_index[2] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[0] = r_index; + } + } + else + { + asection *section; + + /* This is a relocation against a section. We must + adjust by the amount that the section moved. */ + section = aout_reloc_index_to_section (input_bfd, r_index); + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + + /* If this is a PC relative reloc, then the addend is + the difference in VMA between the destination and the + source. We have just adjusted for the change in VMA + of the destination, so we must also adjust by the + change in VMA of the source. This is done below. */ + } + + /* As described above, we must always adjust a PC relative + reloc by the change in VMA of the source. */ + if (howto_table_ext[r_type].pc_relative) + relocation -= (input_section->output_section->vma + + input_section->output_offset + - input_section->vma); + + /* Change the addend if necessary. */ + if (relocation != 0) + PUT_WORD (output_bfd, r_addend + relocation, rel->r_addend); + + /* Change the address of the relocation. */ + PUT_WORD (output_bfd, + r_addr + input_section->output_offset, + rel->r_address); + } + else + { + bfd_reloc_status_type r; + + /* We are generating an executable, and must do a full + relocation. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + h = sym_hashes[r_index]; + + if (check_dynamic_reloc != NULL) + { + boolean skip; + + if (! ((*check_dynamic_reloc) + (finfo->info, input_bfd, input_section, h, + (PTR) rel, &skip))) + return false; + if (skip) + continue; + } + + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + relocation = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + } + else if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_weak) + relocation = 0; + else + { + const char *name; + + name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); + if (! ((*finfo->info->callbacks->undefined_symbol) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + relocation = 0; + } + } + else + { + asection *section; + + section = aout_reloc_index_to_section (input_bfd, r_index); + + /* If this is a PC relative reloc, then R_ADDEND is the + difference between the two vmas, or + old_dest_sec + old_dest_off - (old_src_sec + old_src_off) + where + old_dest_sec == section->vma + and + old_src_sec == input_section->vma + and + old_src_off == r_addr + + _bfd_final_link_relocate expects RELOCATION + + R_ADDEND to be the VMA of the destination minus + r_addr (the minus r_addr is because this relocation + is not pcrel_offset, which is a bit confusing and + should, perhaps, be changed), or + new_dest_sec + where + new_dest_sec == output_section->vma + output_offset + We arrange for this to happen by setting RELOCATION to + new_dest_sec + old_src_sec - old_dest_sec + + If this is not a PC relative reloc, then R_ADDEND is + simply the VMA of the destination, so we set + RELOCATION to the change in the destination VMA, or + new_dest_sec - old_dest_sec + */ + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + if (howto_table_ext[r_type].pc_relative) + relocation += input_section->vma; + } + + r = _bfd_final_link_relocate (howto_table_ext + r_type, + input_bfd, input_section, + contents, r_addr, relocation, + r_addend); + if (r != bfd_reloc_ok) + { + switch (r) + { + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + { + const char *name; + + if (r_extern) + name = strings + GET_WORD (input_bfd, + syms[r_index].e_strx); + else + { + asection *s; + + s = aout_reloc_index_to_section (input_bfd, r_index); + name = bfd_section_name (input_bfd, s); + } + if (! ((*finfo->info->callbacks->reloc_overflow) + (finfo->info, name, howto_table_ext[r_type].name, + r_addend, input_bfd, input_section, r_addr))) + return false; + } + break; + } + } + } + } + + return true; +} + +/* Handle a link order which is supposed to generate a reloc. */ + +static boolean +aout_link_reloc_link_order (finfo, o, p) + struct aout_final_link_info *finfo; + asection *o; + struct bfd_link_order *p; +{ + struct bfd_link_order_reloc *pr; + int r_index; + int r_extern; + const reloc_howto_type *howto; + file_ptr *reloff_ptr; + struct reloc_std_external srel; + struct reloc_ext_external erel; + PTR rel_ptr; + + pr = p->u.reloc.p; + + if (p->type == bfd_section_reloc_link_order) + { + r_extern = 0; + if (bfd_is_abs_section (pr->u.section)) + r_index = N_ABS | N_EXT; + else + { + BFD_ASSERT (pr->u.section->owner == finfo->output_bfd); + r_index = pr->u.section->target_index; + } + } + else + { + struct aout_link_hash_entry *h; + + BFD_ASSERT (p->type == bfd_symbol_reloc_link_order); + r_extern = 1; + h = aout_link_hash_lookup (aout_hash_table (finfo->info), + pr->u.name, false, false, true); + if (h != (struct aout_link_hash_entry *) NULL + && h->indx == -1) + r_index = h->indx; + else + { + if (! ((*finfo->info->callbacks->unattached_reloc) + (finfo->info, pr->u.name, (bfd *) NULL, + (asection *) NULL, (bfd_vma) 0))) + return false; + r_index = 0; + } + } + + howto = bfd_reloc_type_lookup (finfo->output_bfd, pr->reloc); + if (howto == (const reloc_howto_type *) NULL) + { + bfd_set_error (bfd_error_bad_value); + return false; + } + + if (o == obj_textsec (finfo->output_bfd)) + reloff_ptr = &finfo->treloff; + else if (o == obj_datasec (finfo->output_bfd)) + reloff_ptr = &finfo->dreloff; + else + abort (); + + if (obj_reloc_entry_size (finfo->output_bfd) == RELOC_STD_SIZE) + { + int r_pcrel; + int r_baserel; + int r_jmptable; + int r_relative; + int r_length; + +#ifdef MY_put_reloc + MY_put_reloc(finfo->output_bfd, r_extern, r_index, p->offset, howto, &srel); +#else + r_pcrel = howto->pc_relative; + r_baserel = (howto->type & 8) != 0; + r_jmptable = (howto->type & 16) != 0; + r_relative = (howto->type & 32) != 0; + r_length = howto->size; + + PUT_WORD (finfo->output_bfd, p->offset, srel.r_address); + if (finfo->output_bfd->xvec->header_byteorder_big_p) + { + srel.r_index[0] = r_index >> 16; + srel.r_index[1] = r_index >> 8; + srel.r_index[2] = r_index; + srel.r_type[0] = + ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0) + | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0) + | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0) + | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0) + | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0) + | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG)); + } + else + { + srel.r_index[2] = r_index >> 16; + srel.r_index[1] = r_index >> 8; + srel.r_index[0] = r_index; + srel.r_type[0] = + ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0) + | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0) + | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0) + | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0) + | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0) + | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)); + } +#endif + rel_ptr = (PTR) &srel; + + /* We have to write the addend into the object file, since + standard a.out relocs are in place. It would be more + reliable if we had the current contents of the file here, + rather than assuming zeroes, but we can't read the file since + it was opened using bfd_openw. */ + if (pr->addend != 0) + { + bfd_size_type size; + bfd_reloc_status_type r; + bfd_byte *buf; + boolean ok; + + size = bfd_get_reloc_size (howto); + buf = (bfd_byte *) bfd_zmalloc (size); + if (buf == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + r = _bfd_relocate_contents (howto, finfo->output_bfd, + pr->addend, buf); + switch (r) + { + case bfd_reloc_ok: + break; + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + if (! ((*finfo->info->callbacks->reloc_overflow) + (finfo->info, + (p->type == bfd_section_reloc_link_order + ? bfd_section_name (finfo->output_bfd, + pr->u.section) + : pr->u.name), + howto->name, pr->addend, (bfd *) NULL, + (asection *) NULL, (bfd_vma) 0))) + { + free (buf); + return false; + } + break; + } + ok = bfd_set_section_contents (finfo->output_bfd, o, + (PTR) buf, + (file_ptr) p->offset, + size); + free (buf); + if (! ok) + return false; + } + } + else + { + PUT_WORD (finfo->output_bfd, p->offset, erel.r_address); + + if (finfo->output_bfd->xvec->header_byteorder_big_p) + { + erel.r_index[0] = r_index >> 16; + erel.r_index[1] = r_index >> 8; + erel.r_index[2] = r_index; + erel.r_type[0] = + ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0) + | (howto->type << RELOC_EXT_BITS_TYPE_SH_BIG)); + } + else + { + erel.r_index[2] = r_index >> 16; + erel.r_index[1] = r_index >> 8; + erel.r_index[0] = r_index; + erel.r_type[0] = + (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0) + | (howto->type << RELOC_EXT_BITS_TYPE_SH_LITTLE); + } + + PUT_WORD (finfo->output_bfd, pr->addend, erel.r_addend); + + rel_ptr = (PTR) &erel; + } + + if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0 + || (bfd_write (rel_ptr, (bfd_size_type) 1, + obj_reloc_entry_size (finfo->output_bfd), + finfo->output_bfd) + != obj_reloc_entry_size (finfo->output_bfd))) + return false; + + *reloff_ptr += obj_reloc_entry_size (finfo->output_bfd); + + /* Assert that the relocs have not run into the symbols, and that n + the text relocs have not run into the data relocs. */ + BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) + && (reloff_ptr != &finfo->treloff + || (*reloff_ptr + <= obj_datasec (finfo->output_bfd)->rel_filepos))); + + return true; +} diff --git a/gnu/usr.bin/gdb/bfd/archive.c b/gnu/usr.bin/gdb/bfd/archive.c index 5edae9d3db0a..a91b49677f89 100644 --- a/gnu/usr.bin/gdb/bfd/archive.c +++ b/gnu/usr.bin/gdb/bfd/archive.c @@ -1,5 +1,5 @@ /* BFD back-end for archive files (libraries). - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault. This file is part of BFD, the Binary File Descriptor library. @@ -24,28 +24,26 @@ SECTION Archives DESCRIPTION - Archives are supported in BFD in <>. - An archive (or library) is just another BFD. It has a symbol table, although there's not much a user program will do with it. The big difference between an archive BFD and an ordinary BFD is that the archive doesn't have sections. Instead it has a - chain of BFDs considered its contents. These BFDs can be - manipulated just like any other. The BFDs contained in an - archive opened for reading will all be opened for reading; you + chain of BFDs that are considered its contents. These BFDs can + be manipulated like any other. The BFDs contained in an + archive opened for reading will all be opened for reading. You may put either input or output BFDs into an archive opened for - output; it will be handled correctly when the archive is closed. + output; they will be handled correctly when the archive is closed. - Use <> to step through all - the contents of an archive opened for input. It's not - required that you read the entire archive if you don't want + Use <> to step through + the contents of an archive opened for input. You don't + have to read the entire archive if you don't want to! Read it until you find what you want. Archive contents of output BFDs are chained through the <> pointer in a BFD. The first one is findable through the <> slot of the archive. Set it with - <> (q.v.). A given BFD may be in only one + <> (q.v.). A given BFD may be in only one open output archive at a time. As expected, the BFD archive code is more general than the @@ -56,7 +54,7 @@ DESCRIPTION This can cause unexpected confusion, since some archive formats are more expressive than others. For instance, Intel - COFF archives can preserve long filenames; Sun a.out archives + COFF archives can preserve long filenames; SunOS a.out archives cannot. If you move a file from the first to the second format and back again, the filename may be truncated. Likewise, different a.out environments have different @@ -67,10 +65,13 @@ DESCRIPTION Beware: most of these formats do not react well to the presence of spaces in filenames. We do the best we can, but - can't always handle this due to restrctions in the format of - archives. Many unix utilities are braindead in regards to + can't always handle this case due to restrictions in the format of + archives. Many Unix utilities are braindead in regards to spaces and such in filenames anyway, so this shouldn't be much of a restriction. + + Archives are supported in BFD in <>. + */ /* Assumes: @@ -80,12 +81,12 @@ DESCRIPTION */ /* Some formats provide a way to cram a long filename into the short - (16 chars) space provided by a bsd archive. The trick is: make a + (16 chars) space provided by a BSD archive. The trick is: make a special "file" in the front of the archive, sort of like the SYMDEF entry. If the filename is too long to fit, put it in the extended name table, and use its index as the filename. To prevent confusion prepend the index with a space. This means you can't - have filenames that start with a space, but then again, many unix + have filenames that start with a space, but then again, many Unix utilities can't handle that anyway. This scheme unfortunately requires that you stand on your head in @@ -99,7 +100,7 @@ DESCRIPTION BSD 4.4 uses a third scheme: It writes a long filename directly after the header. This allows 'ar q' to work. - We current can read BSD 4.4 archives, but not write them. + We currently can read BSD 4.4 archives, but not write them. */ /* Summary of archive member names: @@ -141,7 +142,7 @@ extern int errno; #define BFD_GNU960_ARMAG(abfd) (BFD_COFF_FILE_P((abfd)) ? ARMAG : ARMAGB) #endif -/* Can't define this in hosts/*.h, because (e.g. in gprof) the hosts file +/* Can't define this in hosts/foo.h, because (e.g. in gprof) the hosts file is included, then obstack.h, which thinks if offsetof is defined, it doesn't need to include stddef.h. */ /* Define offsetof for those systems which lack it */ @@ -157,9 +158,10 @@ extern int errno; Note that the pointers here point to the front of the ar_hdr, not to the front of the contents! */ -struct ar_cache { +struct ar_cache +{ file_ptr ptr; - bfd* arelt; + bfd *arelt; struct ar_cache *next; }; @@ -169,28 +171,39 @@ struct ar_cache { #define arch_eltdata(bfd) ((struct areltdata *)((bfd)->arelt_data)) #define arch_hdr(bfd) ((struct ar_hdr *)arch_eltdata(bfd)->arch_header) -/* Forward declarations of functions */ - -boolean -compute_and_write_armap PARAMS ((bfd *arch, unsigned int elength)); - -static boolean -bsd_update_armap_timestamp PARAMS ((bfd *arch)); - - +static char *get_extended_arelt_filename PARAMS ((bfd *arch, + const char *name)); +static boolean do_slurp_bsd_armap PARAMS ((bfd *abfd)); +static boolean do_slurp_coff_armap PARAMS ((bfd *abfd)); +static const char *normalize PARAMS ((const char *file)); +static boolean bfd_construct_extended_name_table PARAMS ((bfd *abfd, + char **tabloc, + unsigned int *)); +static struct areltdata *bfd_ar_hdr_from_filesystem PARAMS ((bfd *abfd, + const char *)); +static boolean compute_and_write_armap PARAMS ((bfd *arch, + unsigned int elength)); +static boolean bsd_update_armap_timestamp PARAMS ((bfd *arch)); boolean _bfd_generic_mkarchive (abfd) bfd *abfd; { - abfd->tdata.aout_ar_data = (struct artdata *)bfd_zalloc(abfd, - sizeof (struct artdata)); + abfd->tdata.aout_ar_data = ((struct artdata *) + bfd_zalloc (abfd, sizeof (struct artdata))); - if (bfd_ardata (abfd) == NULL) { - bfd_error = no_memory; + if (bfd_ardata (abfd) == NULL) + { + bfd_set_error (bfd_error_no_memory); return false; } - bfd_ardata(abfd)->cache = 0; + + bfd_ardata (abfd)->cache = NULL; + bfd_ardata (abfd)->archive_head = NULL; + bfd_ardata (abfd)->symdefs = NULL; + bfd_ardata (abfd)->extended_names = NULL; + bfd_ardata (abfd)->tdata = NULL; + return true; } @@ -199,16 +212,16 @@ FUNCTION bfd_get_next_mapent SYNOPSIS - symindex bfd_get_next_mapent(bfd *, symindex previous, carsym ** sym); + symindex bfd_get_next_mapent(bfd *abfd, symindex previous, carsym **sym); DESCRIPTION - This function steps through an archive's symbol table (if it - has one). Successively updates <> with the next symbol's + Step through archive @var{abfd}'s symbol table (if it + has one). Successively update @var{sym} with the next symbol's information, returning that symbol's (internal) index into the symbol table. - Supply BFD_NO_MORE_SYMBOLS as the <> entry to get - the first one; returns BFD_NO_MORE_SYMBOLS when you're already + Supply <> as the @var{previous} entry to get + the first one; returns <> when you've already got the last one. A <> is a canonical archive symbol. The only @@ -216,17 +229,19 @@ DESCRIPTION */ symindex -DEFUN(bfd_get_next_mapent,(abfd, prev, entry), - bfd *abfd AND - symindex prev AND - carsym **entry) +bfd_get_next_mapent (abfd, prev, entry) + bfd *abfd; + symindex prev; + carsym **entry; { - if (!bfd_has_map (abfd)) { - bfd_error = invalid_operation; - return BFD_NO_MORE_SYMBOLS; - } - - if (prev == BFD_NO_MORE_SYMBOLS) prev = 0; + if (!bfd_has_map (abfd)) + { + bfd_set_error (bfd_error_invalid_operation); + return BFD_NO_MORE_SYMBOLS; + } + + if (prev == BFD_NO_MORE_SYMBOLS) + prev = 0; else if (++prev >= bfd_ardata (abfd)->symdef_count) return BFD_NO_MORE_SYMBOLS; @@ -242,10 +257,10 @@ _bfd_create_empty_archive_element_shell (obfd) { bfd *nbfd; - nbfd = new_bfd_contained_in(obfd); + nbfd = _bfd_new_bfd_contained_in (obfd); if (nbfd == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } return nbfd; @@ -259,14 +274,14 @@ SYNOPSIS boolean bfd_set_archive_head(bfd *output, bfd *new_head); DESCRIPTION - Used whilst processing archives. Sets the head of the chain of - BFDs contained in an archive to @var{new_head}. + Set the head of the chain of + BFDs contained in the archive @var{output} to @var{new_head}. */ boolean -DEFUN(bfd_set_archive_head,(output_archive, new_head), - bfd *output_archive AND - bfd *new_head) +bfd_set_archive_head (output_archive, new_head) + bfd *output_archive; + bfd *new_head; { output_archive->archive_head = new_head; @@ -274,7 +289,7 @@ DEFUN(bfd_set_archive_head,(output_archive, new_head), } bfd * -look_for_bfd_in_cache (arch_bfd, filepos) +_bfd_look_for_bfd_in_cache (arch_bfd, filepos) bfd *arch_bfd; file_ptr filepos; { @@ -282,48 +297,52 @@ look_for_bfd_in_cache (arch_bfd, filepos) for (current = bfd_ardata (arch_bfd)->cache; current != NULL; current = current->next) - if (current->ptr == filepos) return current->arelt; + if (current->ptr == filepos) + return current->arelt; return NULL; } /* Kind of stupid to call cons for each one, but we don't do too many */ boolean -add_bfd_to_cache (arch_bfd, filepos, new_elt) +_bfd_add_bfd_to_archive_cache (arch_bfd, filepos, new_elt) bfd *arch_bfd, *new_elt; file_ptr filepos; { - struct ar_cache *new_cache = (struct ar_cache *) - bfd_zalloc(arch_bfd, sizeof (struct ar_cache)); + struct ar_cache *new_cache = ((struct ar_cache *) + bfd_zalloc (arch_bfd, + sizeof (struct ar_cache))); - if (new_cache == NULL) { - bfd_error = no_memory; - return false; - } + if (new_cache == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } new_cache->ptr = filepos; new_cache->arelt = new_elt; - new_cache->next = (struct ar_cache *)NULL; + new_cache->next = (struct ar_cache *) NULL; if (bfd_ardata (arch_bfd)->cache == NULL) bfd_ardata (arch_bfd)->cache = new_cache; - else { - struct ar_cache *current = bfd_ardata (arch_bfd)->cache; + else + { + struct ar_cache *current = bfd_ardata (arch_bfd)->cache; + + while (current->next != NULL) + current = current->next; + current->next = new_cache; + } - for (; current->next != NULL; current = current->next); - current->next = new_cache; - } - return true; } - - /* The name begins with space. Hence the rest of the name is an index into the string table. */ -char * + +static char * get_extended_arelt_filename (arch, name) bfd *arch; - char *name; + const char *name; { unsigned long index = 0; @@ -331,14 +350,15 @@ get_extended_arelt_filename (arch, name) the next region, but I'm too lazy. */ errno = 0; /* Skip first char, which is '/' in SVR4 or ' ' in some other variants. */ - index = strtol (name+1, NULL, 10); - if (errno != 0) { - bfd_error = malformed_archive; + index = strtol (name + 1, NULL, 10); + if (errno != 0) + { + bfd_set_error (bfd_error_malformed_archive); return NULL; } return bfd_ardata (arch)->extended_names + index; -} +} /* This functions reads an arch header and returns an areltdata pointer, or NULL on error. @@ -350,154 +370,165 @@ get_extended_arelt_filename (arch, name) */ struct areltdata * -snarf_ar_hdr (abfd) +_bfd_snarf_ar_hdr (abfd) bfd *abfd; { #ifndef errno extern int errno; #endif - struct ar_hdr hdr; - char *hdrp = (char *) &hdr; - unsigned int parsed_size; - struct areltdata *ared; - char *filename = NULL; - unsigned int namelen = 0; - unsigned int allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr); - char *allocptr = 0; + struct ar_hdr hdr; + char *hdrp = (char *) &hdr; + unsigned int parsed_size; + struct areltdata *ared; + char *filename = NULL; + unsigned int namelen = 0; + unsigned int allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr); + char *allocptr = 0; - if (bfd_read ((PTR)hdrp, 1, sizeof (struct ar_hdr), abfd) - != sizeof (struct ar_hdr)) { - bfd_error = no_more_archived_files; - return NULL; + if (bfd_read ((PTR) hdrp, 1, sizeof (struct ar_hdr), abfd) + != sizeof (struct ar_hdr)) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_no_more_archived_files); + return NULL; } - if (strncmp ((hdr.ar_fmag), ARFMAG, 2)) { - bfd_error = malformed_archive; - return NULL; + if (strncmp (hdr.ar_fmag, ARFMAG, 2)) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; } - errno = 0; - parsed_size = strtol (hdr.ar_size, NULL, 10); - if (errno != 0) { - bfd_error = malformed_archive; - return NULL; + errno = 0; + parsed_size = strtol (hdr.ar_size, NULL, 10); + if (errno != 0) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; } - /* extract the filename from the archive - there are two ways to - specify an extendend name table, either the first char of the - name is a space, or it's a slash. */ - if ((hdr.ar_name[0] == '/' - || (hdr.ar_name[0] == ' ' - && memchr (hdr.ar_name, '/', ar_maxnamelen(abfd)) == NULL)) - && bfd_ardata (abfd)->extended_names != NULL) { - filename = get_extended_arelt_filename (abfd, hdr.ar_name); - if (filename == NULL) { - bfd_error = malformed_archive; - return NULL; - } - } - /* BSD4.4-style long filename. - Only implemented for reading, so far! */ - else if (hdr.ar_name[0] == '#' && hdr.ar_name[1] == '1' - && hdr.ar_name[2] == '/' && isdigit(hdr.ar_name[3])) - { - /* BSD-4.4 extended name */ - namelen = atoi (&hdr.ar_name[3]); - allocsize += namelen + 1; - parsed_size -= namelen; - - allocptr = bfd_zalloc(abfd, allocsize); - if (allocptr == NULL) { - bfd_error = no_memory; - return NULL; - } - filename = allocptr - + (sizeof (struct areltdata) + sizeof (struct ar_hdr)); - if (bfd_read (filename, 1, namelen, abfd) != namelen) { - bfd_error = no_more_archived_files; - return NULL; - } - filename[namelen] = '\0'; - } - else + /* Extract the filename from the archive - there are two ways to + specify an extendend name table, either the first char of the + name is a space, or it's a slash. */ + if ((hdr.ar_name[0] == '/' + || (hdr.ar_name[0] == ' ' + && memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)) == NULL)) + && bfd_ardata (abfd)->extended_names != NULL) + { + filename = get_extended_arelt_filename (abfd, hdr.ar_name); + if (filename == NULL) { - /* We judge the end of the name by looking for '/' or ' '. - Note: The SYSV format (terminated by '/') allows embedded - spaces, so only look for ' ' if we don't find '/'. */ + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } + } + /* BSD4.4-style long filename. + Only implemented for reading, so far! */ + else if (hdr.ar_name[0] == '#' && hdr.ar_name[1] == '1' + && hdr.ar_name[2] == '/' && isdigit (hdr.ar_name[3])) + { + /* BSD-4.4 extended name */ + namelen = atoi (&hdr.ar_name[3]); + allocsize += namelen + 1; + parsed_size -= namelen; - namelen = 0; - while (hdr.ar_name[namelen] != '\0' && - hdr.ar_name[namelen] != '/') { + allocptr = bfd_zalloc (abfd, allocsize); + if (allocptr == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + filename = (allocptr + + sizeof (struct areltdata) + + sizeof (struct ar_hdr)); + if (bfd_read (filename, 1, namelen, abfd) != namelen) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_no_more_archived_files); + return NULL; + } + filename[namelen] = '\0'; + } + else + { + /* We judge the end of the name by looking for '/' or ' '. + Note: The SYSV format (terminated by '/') allows embedded + spaces, so only look for ' ' if we don't find '/'. */ + + namelen = 0; + while (hdr.ar_name[namelen] != '\0' && + hdr.ar_name[namelen] != '/') + { + namelen++; + if (namelen == (unsigned) ar_maxnamelen (abfd)) + { + namelen = 0; + while (hdr.ar_name[namelen] != ' ' + && namelen < (unsigned) ar_maxnamelen (abfd)) namelen++; - if (namelen == (unsigned)ar_maxnamelen(abfd)) { - namelen = 0; - while (hdr.ar_name[namelen] != ' ' - && namelen < (unsigned)ar_maxnamelen(abfd)) { - namelen++; - } - break; - } + break; } - - allocsize += namelen + 1; } - if (!allocptr) { - allocptr = bfd_zalloc(abfd, allocsize); - if (allocptr == NULL) { - bfd_error = no_memory; - return NULL; - } + allocsize += namelen + 1; } - ared = (struct areltdata *) allocptr; - - ared->arch_header = allocptr + sizeof (struct areltdata); - memcpy ((char *) ared->arch_header, (char *) &hdr, sizeof (struct ar_hdr)); - ared->parsed_size = parsed_size; - - if (filename != NULL) ared->filename = filename; - else { - ared->filename = allocptr + (sizeof (struct areltdata) + - sizeof (struct ar_hdr)); - if (namelen) - memcpy (ared->filename, hdr.ar_name, namelen); - ared->filename[namelen] = '\0'; + if (!allocptr) + { + allocptr = bfd_zalloc (abfd, allocsize); + if (allocptr == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } } - - return ared; + + ared = (struct areltdata *) allocptr; + + ared->arch_header = allocptr + sizeof (struct areltdata); + memcpy ((char *) ared->arch_header, (char *) &hdr, sizeof (struct ar_hdr)); + ared->parsed_size = parsed_size; + + if (filename != NULL) + ared->filename = filename; + else + { + ared->filename = allocptr + (sizeof (struct areltdata) + + sizeof (struct ar_hdr)); + if (namelen) + memcpy (ared->filename, hdr.ar_name, namelen); + ared->filename[namelen] = '\0'; + } + + return ared; } /* This is an internal function; it's mainly used when indexing through the archive symbol table, but also used to get the next - element, since it handles the bookkeeping so nicely for us. -*/ + element, since it handles the bookkeeping so nicely for us. */ bfd * -get_elt_at_filepos (archive, filepos) +_bfd_get_elt_at_filepos (archive, filepos) bfd *archive; file_ptr filepos; { struct areltdata *new_areldata; bfd *n_nfd; - n_nfd = look_for_bfd_in_cache (archive, filepos); + n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos); if (n_nfd) return n_nfd; if (0 > bfd_seek (archive, filepos, SEEK_SET)) - { - bfd_error = system_call_error; - return NULL; - } - - if ((new_areldata = snarf_ar_hdr (archive)) == NULL) return NULL; - + + if ((new_areldata = _bfd_snarf_ar_hdr (archive)) == NULL) + return NULL; + n_nfd = _bfd_create_empty_archive_element_shell (archive); if (n_nfd == NULL) { - bfd_release (archive, (PTR)new_areldata); + bfd_release (archive, (PTR) new_areldata); return NULL; } @@ -505,12 +536,12 @@ get_elt_at_filepos (archive, filepos) n_nfd->arelt_data = (PTR) new_areldata; n_nfd->filename = new_areldata->filename; - if (add_bfd_to_cache (archive, filepos, n_nfd)) + if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd)) return n_nfd; /* huh? */ - bfd_release (archive, (PTR)n_nfd); - bfd_release (archive, (PTR)new_areldata); + bfd_release (archive, (PTR) n_nfd); + bfd_release (archive, (PTR) new_areldata); return NULL; } @@ -519,22 +550,23 @@ FUNCTION bfd_get_elt_at_index SYNOPSIS - bfd *bfd_get_elt_at_index(bfd * archive, int index); + bfd *bfd_get_elt_at_index(bfd *archive, int index); DESCRIPTION - Return the bfd which is referenced by the symbol indexed by <>. - <> should have been returned by <> (q.v.). + Return the BFD which is referenced by the symbol in @var{archive} + indexed by @var{index}. @var{index} should have been returned by + <> (q.v.). */ bfd * -DEFUN(bfd_get_elt_at_index,(abfd, index), - bfd *abfd AND - int index) +bfd_get_elt_at_index (abfd, index) + bfd *abfd; + int index; { - bfd *result = - get_elt_at_filepos - (abfd, (bfd_ardata (abfd)->symdefs + index)->file_offset); - return result; + carsym *entry; + + entry = bfd_ardata (abfd)->symdefs + index; + return _bfd_get_elt_at_filepos (abfd, entry->file_offset); } /* @@ -542,12 +574,12 @@ FUNCTION bfd_openr_next_archived_file SYNOPSIS - bfd* bfd_openr_next_archived_file(bfd *archive, bfd *previous); + bfd *bfd_openr_next_archived_file(bfd *archive, bfd *previous); DESCRIPTION - Initially provided a BFD containing an archive and NULL, opens - an inpout BFD on the first contained element and returns that. - Subsequent calls to bfd_openr_next_archived_file should pass + Provided a BFD, @var{archive}, containing an archive and NULL, open + an input BFD on the first contained element and returns that. + Subsequent calls should pass the archive and the previous return value to return a created BFD to the next contained element. NULL is returned when there are no more. @@ -562,7 +594,7 @@ bfd_openr_next_archived_file (archive, last_file) if ((bfd_get_format (archive) != bfd_archive) || (archive->direction == write_direction)) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return NULL; } @@ -581,119 +613,165 @@ bfd_generic_openr_next_archived_file (archive, last_file) if (!last_file) filestart = bfd_ardata (archive)->first_file_filepos; - else { - unsigned int size = arelt_size(last_file); - /* Pad to an even boundary... - Note that last_file->origin can be odd in the case of - BSD-4.4-style element with a long odd size. */ - filestart = last_file->origin + size; - filestart += filestart % 2; - } + else + { + unsigned int size = arelt_size (last_file); + /* Pad to an even boundary... + Note that last_file->origin can be odd in the case of + BSD-4.4-style element with a long odd size. */ + filestart = last_file->origin + size; + filestart += filestart % 2; + } - return get_elt_at_filepos (archive, filestart); + return _bfd_get_elt_at_filepos (archive, filestart); } -bfd_target * +const bfd_target * bfd_generic_archive_p (abfd) bfd *abfd; { - char armag[SARMAG+1]; + char armag[SARMAG + 1]; - if (bfd_read ((PTR)armag, 1, SARMAG, abfd) != SARMAG) { - bfd_error = wrong_format; - return 0; - } + if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); + return NULL; + } #ifdef GNU960 - if (strncmp (armag, BFD_GNU960_ARMAG(abfd), SARMAG)) return 0; + if (strncmp (armag, BFD_GNU960_ARMAG (abfd), SARMAG) != 0) + return 0; #else - if (strncmp (armag, ARMAG, SARMAG) && - strncmp (armag, ARMAGB, SARMAG)) return 0; + if (strncmp (armag, ARMAG, SARMAG) != 0 && + strncmp (armag, ARMAGB, SARMAG) != 0) + return 0; #endif - - /* We are setting bfd_ardata(abfd) here, but since bfd_ardata involves a cast, we can't do it as the left operand of assignment. */ - abfd->tdata.aout_ar_data = (struct artdata *) bfd_zalloc(abfd,sizeof (struct artdata)); + abfd->tdata.aout_ar_data = ((struct artdata *) + bfd_zalloc (abfd, sizeof (struct artdata))); - if (bfd_ardata (abfd) == NULL) { - bfd_error = no_memory; - return 0; - } + if (bfd_ardata (abfd) == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } bfd_ardata (abfd)->first_file_filepos = SARMAG; - - if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))) { - bfd_release(abfd, bfd_ardata (abfd)); - abfd->tdata.aout_ar_data = NULL; - return 0; - } + bfd_ardata (abfd)->cache = NULL; + bfd_ardata (abfd)->archive_head = NULL; + bfd_ardata (abfd)->symdefs = NULL; + bfd_ardata (abfd)->extended_names = NULL; + bfd_ardata (abfd)->tdata = NULL; + + if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))) + { + bfd_release (abfd, bfd_ardata (abfd)); + abfd->tdata.aout_ar_data = NULL; + return NULL; + } + + if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) + { + bfd_release (abfd, bfd_ardata (abfd)); + abfd->tdata.aout_ar_data = NULL; + return NULL; + } - if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) { - bfd_release(abfd, bfd_ardata (abfd)); - abfd->tdata.aout_ar_data = NULL; - return 0; - } - return abfd->xvec; } +/* Some constants for a 32 bit BSD archive structure. We do not + support 64 bit archives presently; so far as I know, none actually + exist. Supporting them would require changing these constants, and + changing some bfd_h_get_32 to bfd_h_get_64. */ + +/* The size of an external symdef structure. */ +#define BSD_SYMDEF_SIZE 8 + +/* The offset from the start of a symdef structure to the file offset. */ +#define BSD_SYMDEF_OFFSET_SIZE 4 + +/* The size of the symdef count. */ +#define BSD_SYMDEF_COUNT_SIZE 4 + +/* The size of the string count. */ +#define BSD_STRING_COUNT_SIZE 4 + /* Returns false on error, true otherwise */ + static boolean -DEFUN (do_slurp_bsd_armap, (abfd), - bfd *abfd) +do_slurp_bsd_armap (abfd) + bfd *abfd; { struct areltdata *mapdata; - unsigned int counter = 0; - int *raw_armap, *rbase; + unsigned int counter; + bfd_byte *raw_armap, *rbase; struct artdata *ardata = bfd_ardata (abfd); char *stringbase; unsigned int parsed_size; + carsym *set; - mapdata = snarf_ar_hdr (abfd); - if (mapdata == NULL) return false; + mapdata = _bfd_snarf_ar_hdr (abfd); + if (mapdata == NULL) + return false; parsed_size = mapdata->parsed_size; - bfd_release (abfd, (PTR)mapdata); /* Don't need it any more. */ - - raw_armap = (int *) bfd_zalloc(abfd, parsed_size); - if (raw_armap == NULL) { - bfd_error = no_memory; + bfd_release (abfd, (PTR) mapdata); /* Don't need it any more. */ + + raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size); + if (raw_armap == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); return false; - } - - if (bfd_read ((PTR)raw_armap, 1, parsed_size, abfd) != parsed_size) { - bfd_error = malformed_archive; + } + + if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); byebye: - bfd_release (abfd, (PTR)raw_armap); + bfd_release (abfd, (PTR) raw_armap); return false; - } - - ardata->symdef_count = - bfd_h_get_32(abfd, (PTR)raw_armap) / sizeof (struct symdef); - - if (ardata->symdef_count * sizeof (struct symdef) - > parsed_size - sizeof (*raw_armap)) { + } + + ardata->symdef_count = bfd_h_get_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE; + + if (ardata->symdef_count * BSD_SYMDEF_SIZE > + parsed_size - BSD_SYMDEF_COUNT_SIZE) + { /* Probably we're using the wrong byte ordering. */ - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); goto byebye; - } - + } + ardata->cache = 0; - rbase = raw_armap+1; - ardata->symdefs = (carsym *) rbase; - stringbase = ((char *) (ardata->symdefs + ardata->symdef_count)) + 4; - - for (;counter < ardata->symdef_count; counter++) { - struct symdef *sym = ((struct symdef *) rbase) + counter; - sym->s.name = bfd_h_get_32(abfd, (PTR)(&(sym->s.string_offset))) + stringbase; - sym->file_offset = bfd_h_get_32(abfd, (PTR)( &(sym->file_offset))); - } - + rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE; + stringbase = ((char *) rbase + + ardata->symdef_count * BSD_SYMDEF_SIZE + + BSD_STRING_COUNT_SIZE); + ardata->symdefs = (carsym *) bfd_alloc (abfd, + (ardata->symdef_count + * sizeof (carsym))); + if (!ardata->symdefs) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + for (counter = 0, set = ardata->symdefs; + counter < ardata->symdef_count; + counter++, set++, rbase += BSD_SYMDEF_SIZE) + { + set->name = bfd_h_get_32 (abfd, rbase) + stringbase; + set->file_offset = bfd_h_get_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE); + } + ardata->first_file_filepos = bfd_tell (abfd); /* Pad to an even boundary if you have to */ - ardata->first_file_filepos += (ardata-> first_file_filepos) %2; + ardata->first_file_filepos += (ardata->first_file_filepos) % 2; /* FIXME, we should provide some way to free raw_ardata when we are done using the strings from it. For now, it seems to be allocated on an obstack anyway... */ @@ -703,8 +781,8 @@ DEFUN (do_slurp_bsd_armap, (abfd), /* Returns false on error, true otherwise */ static boolean -DEFUN (do_slurp_coff_armap, (abfd), - bfd *abfd) +do_slurp_coff_armap (abfd) + bfd *abfd; { struct areltdata *mapdata; int *raw_armap, *rawptr; @@ -713,25 +791,27 @@ DEFUN (do_slurp_coff_armap, (abfd), unsigned int stringsize; unsigned int parsed_size; carsym *carsyms; - unsigned int nsymz; /* Number of symbols in armap. */ - - bfd_vma (*swap) PARAMS ((bfd_byte*)); - char int_buf[sizeof(long)]; + unsigned int nsymz; /* Number of symbols in armap. */ + bfd_vma (*swap) PARAMS ((const bfd_byte *)); + char int_buf[sizeof (long)]; unsigned int carsym_size, ptrsize, i; - - mapdata = snarf_ar_hdr (abfd); - if (mapdata == NULL) return false; - parsed_size = mapdata->parsed_size; - bfd_release (abfd, (PTR)mapdata); /* Don't need it any more. */ - if (bfd_read ((PTR)int_buf, 1, 4, abfd) != 4) { - bfd_error = malformed_archive; + mapdata = _bfd_snarf_ar_hdr (abfd); + if (mapdata == NULL) return false; - } + parsed_size = mapdata->parsed_size; + bfd_release (abfd, (PTR) mapdata); /* Don't need it any more. */ + + if (bfd_read ((PTR) int_buf, 1, 4, abfd) != 4) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); + return false; + } /* It seems that all numeric information in a coff archive is always in big endian format, nomatter the host or target. */ swap = bfd_getb32; - nsymz = bfd_getb32((PTR)int_buf); + nsymz = bfd_getb32 ((PTR) int_buf); stringsize = parsed_size - (4 * nsymz) - 4; #if 1 @@ -739,64 +819,70 @@ DEFUN (do_slurp_coff_armap, (abfd), fault - the i960 little endian coff sometimes has big and sometimes little, because our tools changed. Here's a horrible hack to clean up the crap. */ - - if (stringsize > 0xfffff) { + + if (stringsize > 0xfffff) + { /* This looks dangerous, let's do it the other way around */ - nsymz = bfd_getl32((PTR)int_buf); + nsymz = bfd_getl32 ((PTR) int_buf); stringsize = parsed_size - (4 * nsymz) - 4; swap = bfd_getl32; - } + } #endif - /* The coff armap must be read sequentially. So we construct a bsd-style - one in core all at once, for simplicity. */ - + /* The coff armap must be read sequentially. So we construct a + bsd-style one in core all at once, for simplicity. */ + carsym_size = (nsymz * sizeof (carsym)); ptrsize = (4 * nsymz); - ardata->symdefs = (carsym *) bfd_zalloc(abfd, carsym_size + stringsize + 1); - if (ardata->symdefs == NULL) { - bfd_error = no_memory; + ardata->symdefs = (carsym *) bfd_zalloc (abfd, carsym_size + stringsize + 1); + if (ardata->symdefs == NULL) + { + bfd_set_error (bfd_error_no_memory); return false; - } + } carsyms = ardata->symdefs; stringbase = ((char *) ardata->symdefs) + carsym_size; /* Allocate and read in the raw offsets. */ - raw_armap = (int *) bfd_alloc(abfd, ptrsize); - if (raw_armap == NULL) { - bfd_error = no_memory; + raw_armap = (int *) bfd_alloc (abfd, ptrsize); + if (raw_armap == NULL) + { + bfd_set_error (bfd_error_no_memory); goto release_symdefs; - } - if (bfd_read ((PTR)raw_armap, 1, ptrsize, abfd) != ptrsize - || bfd_read ((PTR)stringbase, 1, stringsize, abfd) != stringsize) { - bfd_error = malformed_archive; - goto release_raw_armap; - } + } + if (bfd_read ((PTR) raw_armap, 1, ptrsize, abfd) != ptrsize + || bfd_read ((PTR) stringbase, 1, stringsize, abfd) != stringsize) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); + goto release_raw_armap; + } /* OK, build the carsyms */ - for (i = 0; i < nsymz; i++) { + for (i = 0; i < nsymz; i++) + { rawptr = raw_armap + i; - carsyms->file_offset = swap((PTR)rawptr); + carsyms->file_offset = swap ((PTR) rawptr); carsyms->name = stringbase; - while (*stringbase++) ; + stringbase += strlen (stringbase) + 1; carsyms++; - } + } *stringbase = 0; ardata->symdef_count = nsymz; ardata->first_file_filepos = bfd_tell (abfd); /* Pad to an even boundary if you have to */ - ardata->first_file_filepos += (ardata->first_file_filepos) %2; + ardata->first_file_filepos += (ardata->first_file_filepos) % 2; bfd_has_map (abfd) = true; - bfd_release (abfd, (PTR)raw_armap); + bfd_release (abfd, (PTR) raw_armap); return true; - release_raw_armap: - bfd_release (abfd, (PTR)raw_armap); - release_symdefs: - bfd_release (abfd, (PTR)(ardata)->symdefs); +release_raw_armap: + bfd_release (abfd, (PTR) raw_armap); +release_symdefs: + bfd_release (abfd, (PTR) (ardata)->symdefs); return false; } @@ -808,16 +894,18 @@ bfd_slurp_armap (abfd) bfd *abfd; { char nextname[17]; - int i = bfd_read ((PTR)nextname, 1, 16, abfd); - + int i = bfd_read ((PTR) nextname, 1, 16, abfd); + if (i == 0) - return true; + return true; if (i != 16) - return false; + return false; - bfd_seek (abfd, (file_ptr) -16, SEEK_CUR); + if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0) + return false; - if (!strncmp (nextname, "__.SYMDEF ", 16)) + if (!strncmp (nextname, "__.SYMDEF ", 16) + || !strncmp (nextname, "__.SYMDEF/ ", 16)) /* old Linux archives */ return do_slurp_bsd_armap (abfd); else if (!strncmp (nextname, "/ ", 16)) return do_slurp_coff_armap (abfd); @@ -828,20 +916,24 @@ bfd_slurp_armap (abfd) /* Returns false on error, true otherwise */ /* flavor 2 of a bsd armap, similar to bfd_slurp_bsd_armap except the - header is in a slightly different order and the map name is '/'. + header is in a slightly different order and the map name is '/'. This flavour is used by hp300hpux. */ + +#define HPUX_SYMDEF_COUNT_SIZE 2 + boolean -bfd_slurp_bsd_armap_f2 (abfd) +bfd_slurp_bsd_armap_f2 (abfd) bfd *abfd; { struct areltdata *mapdata; char nextname[17]; - unsigned int counter = 0; - int *raw_armap, *rbase; + unsigned int counter; + bfd_byte *raw_armap, *rbase; struct artdata *ardata = bfd_ardata (abfd); char *stringbase; unsigned int stringsize; - int i = bfd_read ((PTR)nextname, 1, 16, abfd); + carsym *set; + int i = bfd_read ((PTR) nextname, 1, 16, abfd); if (i == 0) return true; @@ -849,9 +941,11 @@ bfd_slurp_bsd_armap_f2 (abfd) return false; /* The archive has at least 16 bytes in it */ - bfd_seek (abfd, -16L, SEEK_CUR); + if (bfd_seek (abfd, -16L, SEEK_CUR) != 0) + return false; - if (!strncmp (nextname, "__.SYMDEF ", 16)) + if (!strncmp (nextname, "__.SYMDEF ", 16) + || !strncmp (nextname, "__.SYMDEF/ ", 16)) /* old Linux archives */ return do_slurp_bsd_armap (abfd); if (strncmp (nextname, "/ ", 16)) @@ -860,55 +954,67 @@ bfd_slurp_bsd_armap_f2 (abfd) return true; } - mapdata = snarf_ar_hdr (abfd); - if (mapdata == NULL) return false; + mapdata = _bfd_snarf_ar_hdr (abfd); + if (mapdata == NULL) + return false; - raw_armap = (int *) bfd_zalloc(abfd,mapdata->parsed_size); + raw_armap = (bfd_byte *) bfd_zalloc (abfd, mapdata->parsed_size); if (raw_armap == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); byebye: - bfd_release (abfd, (PTR)mapdata); + bfd_release (abfd, (PTR) mapdata); return false; } - if (bfd_read ((PTR)raw_armap, 1, mapdata->parsed_size, abfd) != + if (bfd_read ((PTR) raw_armap, 1, mapdata->parsed_size, abfd) != mapdata->parsed_size) { - bfd_error = malformed_archive; + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); byebyebye: - bfd_release (abfd, (PTR)raw_armap); + bfd_release (abfd, (PTR) raw_armap); goto byebye; } - ardata->symdef_count = bfd_h_get_16(abfd, (PTR)raw_armap); + ardata->symdef_count = bfd_h_get_16 (abfd, (PTR) raw_armap); - if (ardata->symdef_count * sizeof (struct symdef) - > mapdata->parsed_size - sizeof (*raw_armap)) + if (ardata->symdef_count * BSD_SYMDEF_SIZE + > mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE) { /* Probably we're using the wrong byte ordering. */ - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); goto byebyebye; } ardata->cache = 0; - stringsize = bfd_h_get_32(abfd, (PTR)(((char*)raw_armap)+2)); + stringsize = bfd_h_get_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE); /* skip sym count and string sz */ - rbase = (int*)(((char*)raw_armap) + 6); - stringbase = (char *) rbase; - ardata->symdefs = (carsym *)(((char*) rbase) + stringsize); - - for (;counter < ardata->symdef_count; counter++) + stringbase = ((char *) raw_armap + + HPUX_SYMDEF_COUNT_SIZE + + BSD_STRING_COUNT_SIZE); + rbase = (bfd_byte *) stringbase + stringsize; + ardata->symdefs = (carsym *) bfd_alloc (abfd, + (ardata->symdef_count + * BSD_SYMDEF_SIZE)); + if (!ardata->symdefs) { - struct symdef *sym = ((struct symdef *) ardata->symdefs) + counter; - sym->s.name = bfd_h_get_32(abfd, (PTR)(&(sym->s.string_offset))) + stringbase; - sym->file_offset = bfd_h_get_32(abfd, (PTR)( &(sym->file_offset))); + bfd_set_error (bfd_error_no_memory); + return false; + } + + for (counter = 0, set = ardata->symdefs; + counter < ardata->symdef_count; + counter++, set++, rbase += BSD_SYMDEF_SIZE) + { + set->name = bfd_h_get_32 (abfd, rbase) + stringbase; + set->file_offset = bfd_h_get_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE); } ardata->first_file_filepos = bfd_tell (abfd); /* Pad to an even boundary if you have to */ - ardata->first_file_filepos += (ardata-> first_file_filepos) %2; + ardata->first_file_filepos += (ardata->first_file_filepos) % 2; /* FIXME, we should provide some way to free raw_ardata when we are done using the strings from it. For now, it seems to be allocated on an obstack anyway... */ @@ -936,57 +1042,64 @@ _bfd_slurp_extended_name_table (abfd) /* FIXME: Formatting sucks here, and in case of failure of BFD_READ, we probably don't want to return true. */ - if (bfd_read ((PTR)nextname, 1, 16, abfd) == 16) { + if (bfd_read ((PTR) nextname, 1, 16, abfd) == 16) + { - bfd_seek (abfd, (file_ptr) -16, SEEK_CUR); + if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0) + return false; - if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 && - strncmp (nextname, "// ", 16) != 0) + if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 && + strncmp (nextname, "// ", 16) != 0) { - bfd_ardata (abfd)->extended_names = NULL; - return true; - } + bfd_ardata (abfd)->extended_names = NULL; + return true; + } - namedata = snarf_ar_hdr (abfd); - if (namedata == NULL) return false; - - bfd_ardata (abfd)->extended_names = bfd_zalloc(abfd,namedata->parsed_size); - if (bfd_ardata (abfd)->extended_names == NULL) { - bfd_error = no_memory; - byebye: - bfd_release (abfd, (PTR)namedata); - return false; - } + namedata = _bfd_snarf_ar_hdr (abfd); + if (namedata == NULL) + return false; - if (bfd_read ((PTR)bfd_ardata (abfd)->extended_names, 1, - namedata->parsed_size, abfd) != namedata->parsed_size) { - bfd_error = malformed_archive; - bfd_release (abfd, (PTR)(bfd_ardata (abfd)->extended_names)); - bfd_ardata (abfd)->extended_names = NULL; - goto byebye; - } + bfd_ardata (abfd)->extended_names = + bfd_zalloc (abfd, namedata->parsed_size); + if (bfd_ardata (abfd)->extended_names == NULL) + { + bfd_set_error (bfd_error_no_memory); + byebye: + bfd_release (abfd, (PTR) namedata); + return false; + } - /* Since the archive is supposed to be printable if it contains - text, the entries in the list are newline-padded, not null - padded. In SVR4-style archives, the names also have a - trailing '/'. We'll fix both problems here.. */ + if (bfd_read ((PTR) bfd_ardata (abfd)->extended_names, 1, + namedata->parsed_size, abfd) != namedata->parsed_size) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); + bfd_release (abfd, (PTR) (bfd_ardata (abfd)->extended_names)); + bfd_ardata (abfd)->extended_names = NULL; + goto byebye; + } + + /* Since the archive is supposed to be printable if it contains + text, the entries in the list are newline-padded, not null + padded. In SVR4-style archives, the names also have a + trailing '/'. We'll fix both problems here.. */ { char *temp = bfd_ardata (abfd)->extended_names; char *limit = temp + namedata->parsed_size; for (; temp < limit; ++temp) - if (*temp == '\n') + if (*temp == '\012') temp[temp[-1] == '/' ? -1 : 0] = '\0'; } - - /* Pad to an even boundary if you have to */ - bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd); - bfd_ardata (abfd)->first_file_filepos += - (bfd_ardata (abfd)->first_file_filepos) %2; - /* FIXME, we can't release namedata here because it was allocated - below extended_names on the obstack... */ - /* bfd_release (abfd, namedata); */ - } + /* Pad to an even boundary if you have to */ + bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd); + bfd_ardata (abfd)->first_file_filepos += + (bfd_ardata (abfd)->first_file_filepos) % 2; + + /* FIXME, we can't release namedata here because it was allocated + below extended_names on the obstack... */ + /* bfd_release (abfd, namedata); */ + } return true; } @@ -994,65 +1107,68 @@ _bfd_slurp_extended_name_table (abfd) /* Return a copy of the stuff in the filename between any :]> and a semicolon */ -static CONST char * -DEFUN(normalize,(file), - CONST char *file) +static const char * +normalize (file) + const char *file; { CONST char *first; CONST char *last; char *copy; - first = file + strlen(file)-1; - last = first+1; + first = file + strlen (file) - 1; + last = first + 1; - while (first != file) - { - if (*first == ';') - last = first; - if (*first == ':' || *first == ']' ||*first == '>') - { - first++; - break; + while (first != file) + { + if (*first == ';') + last = first; + if (*first == ':' || *first == ']' || *first == '>') + { + first++; + break; + } + first--; } - first --; - } - - copy = bfd_xmalloc(last - first + 1); - memcpy(copy, first, last-first); - copy[last-first] = 0; + + copy = malloc (last - first + 1); + if (!copy) + return copy; + + memcpy (copy, first, last - first); + copy[last - first] = 0; return copy; } #else -static CONST char * -DEFUN (normalize, (file), - CONST char *file) +static const char * +normalize (file) + const char *file; { - CONST char * filename = strrchr(file, '/'); + CONST char *filename = strrchr (file, '/'); - if (filename != (char *)NULL) { - filename ++; - } - else { - filename = file; - } + if (filename != (char *) NULL) + filename++; + else + filename = file; return filename; } #endif -/* Follows archive_head and produces an extended name table if necessary. - Returns (in tabloc) a pointer to an extended name table, and in tablen - the length of the table. If it makes an entry it clobbers the filename - so that the element may be written without further massage. - Returns true if it ran successfully, false if something went wrong. - A successful return may still involve a zero-length tablen! - */ -boolean -DEFUN (bfd_construct_extended_name_table, (abfd, tabloc, tablen), - bfd *abfd AND - char **tabloc AND - unsigned int *tablen) + +/* Follows archive_head and produces an extended name table if + necessary. Returns (in tabloc) a pointer to an extended name + table, and in tablen the length of the table. If it makes an entry + it clobbers the filename so that the element may be written without + further massage. Returns true if it ran successfully, false if + something went wrong. A successful return may still involve a + zero-length tablen! */ + +static boolean +bfd_construct_extended_name_table (abfd, tabloc, tablen) + bfd *abfd; + char **tabloc; + unsigned int *tablen; { unsigned int maxname = abfd->xvec->ar_max_namelen; unsigned int total_namelen = 0; @@ -1060,103 +1176,127 @@ DEFUN (bfd_construct_extended_name_table, (abfd, tabloc, tablen), char *strptr; *tablen = 0; - + /* Figure out how long the table should be */ - for (current = abfd->archive_head; current != NULL; current = current->next){ - unsigned int thislen = strlen (normalize(current->filename)); - if (thislen > maxname) total_namelen += thislen + 1; /* leave room for \n */ - } + for (current = abfd->archive_head; current != NULL; current = current->next) + { + CONST char *normal = normalize (current->filename); + unsigned int thislen; - if (total_namelen == 0) return true; + if (!normal) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + thislen = strlen (normal); + if (thislen > maxname) + total_namelen += thislen + 1; /* leave room for \n */ + } - *tabloc = bfd_zalloc (abfd,total_namelen); - if (*tabloc == NULL) { - bfd_error = no_memory; - return false; - } + if (total_namelen == 0) + return true; + + *tabloc = bfd_zalloc (abfd, total_namelen); + if (*tabloc == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } *tablen = total_namelen; strptr = *tabloc; for (current = abfd->archive_head; current != NULL; current = - current->next) { - CONST char *normal =normalize( current->filename); - unsigned int thislen = strlen (normal); - if (thislen > maxname) { - /* Works for now; may need to be re-engineered if we encounter an oddball - archive format and want to generalise this hack. */ - struct ar_hdr *hdr = arch_hdr(current); - strcpy (strptr, normal); - strptr[thislen] = '\n'; - hdr->ar_name[0] = ' '; - /* We know there will always be enough room (one of the few cases - where you may safely use sprintf). */ - sprintf ((hdr->ar_name) + 1, "%-d", (unsigned) (strptr - *tabloc)); - /* Kinda Kludgy. We should just use the returned value of sprintf - but not all implementations get this right */ + current->next) + { + CONST char *normal = normalize (current->filename); + unsigned int thislen; + + if (!normal) { - char *temp = hdr->ar_name +2; - for (; temp < hdr->ar_name + maxname; temp++) - if (*temp == '\0') *temp = ' '; + bfd_set_error (bfd_error_no_memory); + return false; + } + thislen = strlen (normal); + if (thislen > maxname) + { + /* Works for now; may need to be re-engineered if we + encounter an oddball archive format and want to + generalise this hack. */ + struct ar_hdr *hdr = arch_hdr (current); + strcpy (strptr, normal); + strptr[thislen] = '\012'; + hdr->ar_name[0] = ar_padchar (current); + /* We know there will always be enough room (one of the few + cases where you may safely use sprintf). */ + sprintf ((hdr->ar_name) + 1, "%-d", (unsigned) (strptr - *tabloc)); + /* Kinda Kludgy. We should just use the returned value of + sprintf but not all implementations get this right */ + { + char *temp = hdr->ar_name + 2; + for (; temp < hdr->ar_name + maxname; temp++) + if (*temp == '\0') + *temp = ' '; + } + strptr += thislen + 1; } - strptr += thislen + 1; } - } return true; } /** A couple of functions for creating ar_hdrs */ -/* Takes a filename, returns an arelt_data for it, or NULL if it can't make one. - The filename must refer to a filename in the filesystem. - The filename field of the ar_hdr will NOT be initialized -*/ +/* Takes a filename, returns an arelt_data for it, or NULL if it can't + make one. The filename must refer to a filename in the filesystem. + The filename field of the ar_hdr will NOT be initialized */ -struct areltdata * -DEFUN(bfd_ar_hdr_from_filesystem, (abfd,filename), - bfd* abfd AND - CONST char *filename) +static struct areltdata * +bfd_ar_hdr_from_filesystem (abfd, filename) + bfd *abfd; + const char *filename; { struct stat status; struct areltdata *ared; struct ar_hdr *hdr; char *temp, *temp1; + if (stat (filename, &status) != 0) + { + bfd_set_error (bfd_error_system_call); + return NULL; + } - if (stat (filename, &status) != 0) { - bfd_error = system_call_error; - return NULL; - } - - ared = (struct areltdata *) bfd_zalloc(abfd, sizeof (struct ar_hdr) + - sizeof (struct areltdata)); - if (ared == NULL) { - bfd_error = no_memory; - return NULL; - } + ared = (struct areltdata *) bfd_zalloc (abfd, sizeof (struct ar_hdr) + + sizeof (struct areltdata)); + if (ared == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata)); /* ar headers are space padded, not null padded! */ - temp = (char *) hdr; - temp1 = temp + sizeof (struct ar_hdr) - 2; - for (; temp < temp1; *(temp++) = ' '); + memset ((PTR) hdr, ' ', sizeof (struct ar_hdr)); + strncpy (hdr->ar_fmag, ARFMAG, 2); - + /* Goddamned sprintf doesn't permit MAXIMUM field lengths */ - sprintf ((hdr->ar_date), "%-12ld", status.st_mtime); - sprintf ((hdr->ar_uid), "%d", status.st_uid); - sprintf ((hdr->ar_gid), "%d", status.st_gid); - sprintf ((hdr->ar_mode), "%-8o", (unsigned) status.st_mode); - sprintf ((hdr->ar_size), "%-10ld", status.st_size); + sprintf ((hdr->ar_date), "%-12ld", (long) status.st_mtime); + sprintf ((hdr->ar_uid), "%ld", (long) status.st_uid); + sprintf ((hdr->ar_gid), "%ld", (long) status.st_gid); + sprintf ((hdr->ar_mode), "%-8o", (unsigned int) status.st_mode); + sprintf ((hdr->ar_size), "%-10ld", (long) status.st_size); /* Correct for a lossage in sprintf whereby it null-terminates. I cannot understand how these C losers could design such a ramshackle bunch of IO operations */ temp = (char *) hdr; temp1 = temp + sizeof (struct ar_hdr) - 2; - for (; temp < temp1; temp++) { - if (*temp == '\0') *temp = ' '; - } + for (; temp < temp1; temp++) + { + if (*temp == '\0') + *temp = ' '; + } strncpy (hdr->ar_fmag, ARFMAG, 2); ared->parsed_size = status.st_size; ared->arch_header = (char *) hdr; @@ -1165,19 +1305,18 @@ DEFUN(bfd_ar_hdr_from_filesystem, (abfd,filename), } /* This is magic required by the "ar" program. Since it's - undocumented, it's undocumented. You may think that it would - take a strong stomach to write this, and it does, but it takes - even a stronger stomach to try to code around such a thing! -*/ + undocumented, it's undocumented. You may think that it would take + a strong stomach to write this, and it does, but it takes even a + stronger stomach to try to code around such a thing! */ struct ar_hdr * -DEFUN(bfd_special_undocumented_glue, (abfd, filename), - bfd *abfd AND - char *filename) +bfd_special_undocumented_glue (abfd, filename) + bfd *abfd; + char *filename; { struct areltdata *ar_elt = bfd_ar_hdr_from_filesystem (abfd, filename); if (ar_elt == NULL) - return NULL; + return NULL; return (struct ar_hdr *) ar_elt->arch_header; } @@ -1190,18 +1329,19 @@ bfd_generic_stat_arch_elt (abfd, buf) { struct ar_hdr *hdr; char *aloser; - - if (abfd->arelt_data == NULL) { - bfd_error = invalid_operation; - return -1; - } - + + if (abfd->arelt_data == NULL) + { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } + hdr = arch_hdr (abfd); #define foo(arelt, stelt, size) \ buf->stelt = strtol (hdr->arelt, &aloser, size); \ if (aloser == hdr->arelt) return -1; - + foo (ar_date, st_mtime, 10); foo (ar_uid, st_uid, 10); foo (ar_gid, st_gid, 10); @@ -1222,10 +1362,10 @@ bfd_dont_truncate_arname (abfd, pathname, arhdr) Fortunately ic960 users will never use that option. Fixing this is very hard; fortunately I know how to do it and will do so once intel's release is out the door. */ - + struct ar_hdr *hdr = (struct ar_hdr *) arhdr; int length; - CONST char *filename = normalize(pathname); + CONST char *filename = normalize (pathname); int maxlen = ar_maxnamelen (abfd); length = strlen (filename); @@ -1233,9 +1373,8 @@ bfd_dont_truncate_arname (abfd, pathname, arhdr) if (length <= maxlen) memcpy (hdr->ar_name, filename, length); - if (length < maxlen) (hdr->ar_name)[length] = ar_padchar (abfd); - return; - + if (length < maxlen) + (hdr->ar_name)[length] = ar_padchar (abfd); } void @@ -1249,7 +1388,6 @@ bfd_bsd_truncate_arname (abfd, pathname, arhdr) CONST char *filename = strrchr (pathname, '/'); int maxlen = ar_maxnamelen (abfd); - if (filename == NULL) filename = pathname; else @@ -1259,23 +1397,26 @@ bfd_bsd_truncate_arname (abfd, pathname, arhdr) if (length <= maxlen) memcpy (hdr->ar_name, filename, length); - else { - /* pathname: meet procrustes */ - memcpy (hdr->ar_name, filename, maxlen); - length = maxlen; - } + else + { + /* pathname: meet procrustes */ + memcpy (hdr->ar_name, filename, maxlen); + length = maxlen; + } - if (length < maxlen) (hdr->ar_name)[length] = ar_padchar (abfd); + if (length < maxlen) + (hdr->ar_name)[length] = ar_padchar (abfd); } /* Store name into ar header. Truncates the name to fit. 1> strip pathname to be just the basename. 2> if it's short enuf to fit, stuff it in. 3> If it doesn't end with .o, truncate it to fit - 4> truncate it before the .o, append .o, stuff THAT in. -*/ + 4> truncate it before the .o, append .o, stuff THAT in. */ + +/* This is what gnu ar does. It's better but incompatible with the + bsd ar. */ -/* This is what gnu ar does. It's better but incompatible with the bsd ar. */ void bfd_gnu_truncate_arname (abfd, pathname, arhdr) bfd *abfd; @@ -1286,7 +1427,7 @@ bfd_gnu_truncate_arname (abfd, pathname, arhdr) int length; CONST char *filename = strrchr (pathname, '/'); int maxlen = ar_maxnamelen (abfd); - + if (filename == NULL) filename = pathname; else @@ -1296,20 +1437,23 @@ bfd_gnu_truncate_arname (abfd, pathname, arhdr) if (length <= maxlen) memcpy (hdr->ar_name, filename, length); - else { /* pathname: meet procrustes */ - memcpy (hdr->ar_name, filename, maxlen); - if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) { - hdr->ar_name[maxlen - 2] = '.'; - hdr->ar_name[maxlen - 1] = 'o'; + else + { /* pathname: meet procrustes */ + memcpy (hdr->ar_name, filename, maxlen); + if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) + { + hdr->ar_name[maxlen - 2] = '.'; + hdr->ar_name[maxlen - 1] = 'o'; + } + length = maxlen; } - length = maxlen; - } - if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd); + if (length < 16) + (hdr->ar_name)[length] = ar_padchar (abfd); } - /* The BFD is open for write and has its format set to bfd_archive */ + boolean _bfd_write_archive_contents (arch) bfd *arch; @@ -1319,231 +1463,305 @@ _bfd_write_archive_contents (arch) unsigned int elength = 0; boolean makemap = bfd_has_map (arch); boolean hasobjects = false; /* if no .o's, don't bother to make a map */ + bfd_size_type wrote; unsigned int i; int tries; /* Verify the viability of all entries; if any of them live in the filesystem (as opposed to living in an archive open for input) - then construct a fresh ar_hdr for them. - */ - for (current = arch->archive_head; current; current = current->next) { - if (bfd_write_p (current)) { - bfd_error = invalid_operation; - return false; - } - if (!current->arelt_data) { - current->arelt_data = - (PTR) bfd_ar_hdr_from_filesystem (arch, current->filename); - if (!current->arelt_data) return false; + then construct a fresh ar_hdr for them. */ + for (current = arch->archive_head; current; current = current->next) + { + if (bfd_write_p (current)) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + if (!current->arelt_data) + { + current->arelt_data = + (PTR) bfd_ar_hdr_from_filesystem (arch, current->filename); + if (!current->arelt_data) + return false; - /* Put in the file name */ - - BFD_SEND (arch, _bfd_truncate_arname,(arch, - current->filename, - (char *) arch_hdr(current))); + /* Put in the file name */ + BFD_SEND (arch, _bfd_truncate_arname, (arch, + current->filename, + (char *) arch_hdr (current))); + } - - } - - if (makemap) { /* don't bother if we won't make a map! */ - if ((bfd_check_format (current, bfd_object)) + if (makemap && ! hasobjects) + { /* don't bother if we won't make a map! */ + if ((bfd_check_format (current, bfd_object)) #if 0 /* FIXME -- these are not set correctly */ - && ((bfd_get_file_flags (current) & HAS_SYMS)) + && ((bfd_get_file_flags (current) & HAS_SYMS)) #endif - ) - hasobjects = true; + ) + hasobjects = true; + } } - } if (!bfd_construct_extended_name_table (arch, &etable, &elength)) return false; - bfd_seek (arch, (file_ptr) 0, SEEK_SET); + if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0) + return false; #ifdef GNU960 - bfd_write (BFD_GNU960_ARMAG(arch), 1, SARMAG, arch); + wrote = bfd_write (BFD_GNU960_ARMAG (arch), 1, SARMAG, arch); #else - bfd_write (ARMAG, 1, SARMAG, arch); + wrote = bfd_write (ARMAG, 1, SARMAG, arch); #endif + if (wrote != SARMAG) + return false; - if (makemap && hasobjects) { - - if (compute_and_write_armap (arch, elength) != true) { - return false; - } - } - - if (elength != 0) { - struct ar_hdr hdr; - - memset ((char *)(&hdr), 0, sizeof (struct ar_hdr)); - sprintf (&(hdr.ar_name[0]), "ARFILENAMES/"); - sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength); - hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n'; - for (i = 0; i < sizeof (struct ar_hdr); i++) - if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' '; - bfd_write ((char *)&hdr, 1, sizeof (struct ar_hdr), arch); - bfd_write (etable, 1, elength, arch); - if ((elength % 2) == 1) bfd_write ("\n", 1, 1, arch); - - } - - for (current = arch->archive_head; current; current = current->next) { - char buffer[DEFAULT_BUFFERSIZE]; - unsigned int remaining = arelt_size (current); - struct ar_hdr *hdr = arch_hdr(current); - /* write ar header */ - - if (bfd_write ((char *)hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) { - syserr: - bfd_error = system_call_error; + if (makemap && hasobjects) + { + if (compute_and_write_armap (arch, elength) != true) return false; - } - if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0) goto syserr; - while (remaining) + } + + if (elength != 0) + { + struct ar_hdr hdr; + + memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); + if (ar_padchar (arch) == '/') + sprintf (&(hdr.ar_name[0]), "//"); + else + sprintf (&(hdr.ar_name[0]), "ARFILENAMES/"); + sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength); + strncpy (hdr.ar_fmag, ARFMAG, 2); + for (i = 0; i < sizeof (struct ar_hdr); i++) + if (((char *) (&hdr))[i] == '\0') + (((char *) (&hdr))[i]) = ' '; + if ((bfd_write ((char *) &hdr, 1, sizeof (struct ar_hdr), arch) + != sizeof (struct ar_hdr)) + || bfd_write (etable, 1, elength, arch) != elength) + return false; + if ((elength % 2) == 1) + { + if (bfd_write ("\012", 1, 1, arch) != 1) + return false; + } + } + + for (current = arch->archive_head; current; current = current->next) + { + char buffer[DEFAULT_BUFFERSIZE]; + unsigned int remaining = arelt_size (current); + struct ar_hdr *hdr = arch_hdr (current); + + /* write ar header */ + if (bfd_write ((char *) hdr, 1, sizeof (*hdr), arch) != sizeof (*hdr)) + return false; + if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0) + return false; + while (remaining) { unsigned int amt = DEFAULT_BUFFERSIZE; - if (amt > remaining) { + if (amt > remaining) amt = remaining; - } errno = 0; - if (bfd_read (buffer, amt, 1, current) != amt) { - if (errno) goto syserr; - /* Looks like a truncated archive. */ - bfd_error = malformed_archive; + if (bfd_read (buffer, amt, 1, current) != amt) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); return false; - } - if (bfd_write (buffer, amt, 1, arch) != amt) goto syserr; + } + if (bfd_write (buffer, amt, 1, arch) != amt) + return false; remaining -= amt; } - if ((arelt_size (current) % 2) == 1) bfd_write ("\n", 1, 1, arch); - } + if ((arelt_size (current) % 2) == 1) + { + if (bfd_write ("\012", 1, 1, arch) != 1) + return false; + } + } - /* Verify the timestamp in the archive file. If it would - not be accepted by the linker, rewrite it until it would be. - If anything odd happens, break out and just return. - (The Berkeley linker checks the timestamp and refuses to read the + /* Verify the timestamp in the archive file. If it would not be + accepted by the linker, rewrite it until it would be. If + anything odd happens, break out and just return. (The Berkeley + linker checks the timestamp and refuses to read the table-of-contents if it is >60 seconds less than the file's modified-time. That painful hack requires this painful hack. */ tries = 1; - do { - /* FIXME! This kludge is to avoid adding a member to the xvec, - while generating a small patch for Adobe. FIXME! The - update_armap_timestamp function call should be in the xvec, - thus: + do + { + /* FIXME! This kludge is to avoid adding a member to the xvec, + while generating a small patch for Adobe. FIXME! The + update_armap_timestamp function call should be in the xvec, + thus: if (bfd_update_armap_timestamp (arch) == true) break; ^ - Instead, we check whether in a BSD archive, and call directly. */ + Instead, we check whether in a BSD archive, and call + directly. */ - if (arch->xvec->write_armap != bsd_write_armap) + if (arch->xvec->write_armap != bsd_write_armap) break; - if (bsd_update_armap_timestamp(arch) == true) /* FIXME!!! Vector it */ + if (bsd_update_armap_timestamp (arch) == true) /* FIXME!!! Vector it */ break; - if (tries > 0) + if (tries > 0) fprintf (stderr, - "Warning: writing archive was slow: rewriting timestamp\n"); - } while (++tries < 6 ); + "Warning: writing archive was slow: rewriting timestamp\n"); + } + while (++tries < 6); return true; } /* Note that the namidx for the first symbol is 0 */ -boolean +static boolean compute_and_write_armap (arch, elength) bfd *arch; unsigned int elength; { - bfd *current; - file_ptr elt_no = 0; - struct orl *map; - int orl_max = 15000; /* fine initial default */ - int orl_count = 0; - int stridx = 0; /* string index */ + char *first_name = NULL; + bfd *current; + file_ptr elt_no = 0; + struct orl *map = NULL; + int orl_max = 1024; /* fine initial default */ + int orl_count = 0; + int stridx = 0; /* string index */ + asymbol **syms = NULL; + long syms_max = 0; + boolean ret; - /* Dunno if this is the best place for this info... */ - if (elength != 0) elength += sizeof (struct ar_hdr); - elength += elength %2 ; + /* Dunno if this is the best place for this info... */ + if (elength != 0) + elength += sizeof (struct ar_hdr); + elength += elength % 2; - map = (struct orl *) bfd_zalloc (arch,orl_max * sizeof (struct orl)); - if (map == NULL) { - bfd_error = no_memory; - return false; - } + map = (struct orl *) malloc (orl_max * sizeof (struct orl)); + if (map == NULL) + goto no_memory_return; - /* Drop all the files called __.SYMDEF, we're going to make our - own */ - while (arch->archive_head && - strcmp(arch->archive_head->filename,"__.SYMDEF") == 0) + /* We put the symbol names on the arch obstack, and then discard + them when done. */ + first_name = bfd_alloc (arch, 1); + if (first_name == NULL) + goto no_memory_return; + + /* Drop all the files called __.SYMDEF, we're going to make our + own */ + while (arch->archive_head && + strcmp (arch->archive_head->filename, "__.SYMDEF") == 0) + arch->archive_head = arch->archive_head->next; + + /* Map over each element */ + for (current = arch->archive_head; + current != (bfd *) NULL; + current = current->next, elt_no++) { - arch->archive_head = arch->archive_head->next; - } - /* Map over each element */ - for (current = arch->archive_head; - current != (bfd *)NULL; - current = current->next, elt_no++) - { - if ((bfd_check_format (current, bfd_object) == true) - && ((bfd_get_file_flags (current) & HAS_SYMS))) { - asymbol **syms; - unsigned int storage; - unsigned int symcount; - unsigned int src_count; + if ((bfd_check_format (current, bfd_object) == true) + && ((bfd_get_file_flags (current) & HAS_SYMS))) + { + long storage; + long symcount; + long src_count; - storage = get_symtab_upper_bound (current); - if (storage != 0) { + storage = bfd_get_symtab_upper_bound (current); + if (storage < 0) + goto error_return; - syms = (asymbol **) bfd_zalloc (arch,storage); - if (syms == NULL) { - bfd_error = no_memory; /* FIXME -- memory leak */ - return false; - } - symcount = bfd_canonicalize_symtab (current, syms); + if (storage != 0) + { + if (storage > syms_max) + { + if (syms_max > 0) + free (syms); + syms_max = storage; + syms = (asymbol **) malloc ((size_t) syms_max); + if (syms == NULL) + goto no_memory_return; + } + symcount = bfd_canonicalize_symtab (current, syms); + if (symcount < 0) + goto error_return; + /* Now map over all the symbols, picking out the ones we want */ + for (src_count = 0; src_count < symcount; src_count++) + { + flagword flags = (syms[src_count])->flags; + asection *sec = syms[src_count]->section; - /* Now map over all the symbols, picking out the ones we want */ - for (src_count = 0; src_count flags; - asection *sec = - syms[src_count]->section; - - if ((flags & BSF_GLOBAL || - flags & BSF_WEAK || - flags & BSF_INDIRECT || - bfd_is_com_section (sec)) - && (sec != &bfd_und_section)) { + if ((flags & BSF_GLOBAL || + flags & BSF_WEAK || + flags & BSF_INDIRECT || + bfd_is_com_section (sec)) + && ! bfd_is_und_section (sec)) + { + size_t namelen; + struct orl *new_map; - /* This symbol will go into the archive header */ - if (orl_count == orl_max) - { - orl_max *= 2; - map = (struct orl *) bfd_realloc (arch, (char *) map, - orl_max * sizeof (struct orl)); - } + /* This symbol will go into the archive header */ + if (orl_count == orl_max) + { + orl_max *= 2; + new_map = ((struct orl *) + realloc ((PTR) map, + orl_max * sizeof (struct orl))); + if (new_map == (struct orl *) NULL) + goto no_memory_return; - (map[orl_count]).name = (char **) &((syms[src_count])->name); - (map[orl_count]).pos = (file_ptr) current; - (map[orl_count]).namidx = stridx; + map = new_map; + } - stridx += strlen ((syms[src_count])->name) + 1; - ++orl_count; - } - } + namelen = strlen (syms[src_count]->name); + map[orl_count].name = ((char **) + bfd_alloc (arch, + sizeof (char *))); + if (map[orl_count].name == NULL) + goto no_memory_return; + *(map[orl_count].name) = bfd_alloc (arch, namelen + 1); + if (*(map[orl_count].name) == NULL) + goto no_memory_return; + strcpy (*(map[orl_count].name), syms[src_count]->name); + (map[orl_count]).pos = (file_ptr) current; + (map[orl_count]).namidx = stridx; + + stridx += namelen + 1; + ++orl_count; } + } } - } - /* OK, now we have collected all the data, let's write them out */ - if (!BFD_SEND (arch, write_armap, - (arch, elength, map, orl_count, stridx))) { - return false; + /* Now ask the BFD to free up any cached information, so we + don't fill all of memory with symbol tables. */ + if (! bfd_free_cached_info (current)) + goto error_return; } + } + /* OK, now we have collected all the data, let's write them out */ + ret = BFD_SEND (arch, write_armap, + (arch, elength, map, orl_count, stridx)); - return true; + if (syms_max > 0) + free (syms); + if (map != NULL) + free (map); + if (first_name != NULL) + bfd_release (arch, first_name); + + return ret; + + no_memory_return: + bfd_set_error (bfd_error_no_memory); + + error_return: + if (syms_max > 0) + free (syms); + if (map != NULL) + free (map); + if (first_name != NULL) + bfd_release (arch, first_name); + + return false; } boolean @@ -1571,58 +1789,75 @@ bsd_write_armap (arch, elength, map, orl_count, stridx) firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG; stat (arch->filename, &statbuf); - memset ((char *)(&hdr), 0, sizeof (struct ar_hdr)); + memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); sprintf (hdr.ar_name, RANLIBMAG); /* Remember the timestamp, to keep it holy. But fudge it a little. */ - bfd_ardata(arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET; - bfd_ardata(arch)->armap_datepos = SARMAG + - offsetof(struct ar_hdr, ar_date[0]); - sprintf (hdr.ar_date, "%ld", bfd_ardata(arch)->armap_timestamp); - sprintf (hdr.ar_uid, "%d", getuid()); - sprintf (hdr.ar_gid, "%d", getgid()); + bfd_ardata (arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET; + bfd_ardata (arch)->armap_datepos = (SARMAG + + offsetof (struct ar_hdr, ar_date[0])); + sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp); + sprintf (hdr.ar_uid, "%d", getuid ()); + sprintf (hdr.ar_gid, "%d", getgid ()); sprintf (hdr.ar_size, "%-10d", (int) mapsize); - hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n'; + strncpy (hdr.ar_fmag, ARFMAG, 2); for (i = 0; i < sizeof (struct ar_hdr); i++) - if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' '; - bfd_write ((char *)&hdr, 1, sizeof (struct ar_hdr), arch); - bfd_h_put_32(arch, (bfd_vma) ranlibsize, (PTR)&temp); - bfd_write (&temp, 1, sizeof (temp), arch); - - for (count = 0; count < orl_count; count++) { - struct symdef outs; - struct symdef *outp = &outs; - - if (((bfd *)(map[count]).pos) != last_elt) { - do { - firstreal += arelt_size (current) + sizeof (struct ar_hdr); - firstreal += firstreal % 2; - current = current->next; - } while (current != (bfd *)(map[count]).pos); - } /* if new archive element */ + if (((char *) (&hdr))[i] == '\0') + (((char *) (&hdr))[i]) = ' '; + if (bfd_write ((char *) &hdr, 1, sizeof (struct ar_hdr), arch) + != sizeof (struct ar_hdr)) + return false; + bfd_h_put_32 (arch, (bfd_vma) ranlibsize, (PTR) &temp); + if (bfd_write (&temp, 1, sizeof (temp), arch) != sizeof (temp)) + return false; - last_elt = current; - bfd_h_put_32(arch, ((map[count]).namidx),(PTR) &outs.s.string_offset); - bfd_h_put_32(arch, firstreal,(PTR) &outs.file_offset); - bfd_write ((char *)outp, 1, sizeof (outs), arch); - } + for (count = 0; count < orl_count; count++) + { + struct symdef outs; + struct symdef *outp = &outs; + + if (((bfd *) (map[count]).pos) != last_elt) + { + do + { + firstreal += arelt_size (current) + sizeof (struct ar_hdr); + firstreal += firstreal % 2; + current = current->next; + } + while (current != (bfd *) (map[count]).pos); + } /* if new archive element */ + + last_elt = current; + bfd_h_put_32 (arch, ((map[count]).namidx), (PTR) &outs.s.string_offset); + bfd_h_put_32 (arch, firstreal, (PTR) &outs.file_offset); + if (bfd_write ((char *) outp, 1, sizeof (outs), arch) != sizeof (outs)) + return false; + } /* now write the strings themselves */ - bfd_h_put_32(arch, stringsize, (PTR)&temp); - bfd_write ((PTR)&temp, 1, sizeof (temp), arch); + bfd_h_put_32 (arch, stringsize, (PTR) &temp); + if (bfd_write ((PTR) &temp, 1, sizeof (temp), arch) != sizeof (temp)) + return false; for (count = 0; count < orl_count; count++) - bfd_write (*((map[count]).name), 1, strlen (*((map[count]).name))+1, arch); + { + size_t len = strlen (*map[count].name) + 1; + + if (bfd_write (*map[count].name, 1, len, arch) != len) + return false; + } /* The spec sez this should be a newline. But in order to be bug-compatible for sun's ar we use a null. */ if (padit) - bfd_write("\0",1,1,arch); + { + if (bfd_write ("", 1, 1, arch) != 1) + return false; + } return true; } - /* At the end of archive file handling, update the timestamp in the - file, so the linker will accept it. + file, so the linker will accept it. Return true if the timestamp was OK, or an unusual problem happened. Return false if we updated the timestamp. */ @@ -1638,48 +1873,49 @@ bsd_update_armap_timestamp (arch) /* Flush writes, get last-write timestamp from file, and compare it to the timestamp IN the file. */ bfd_flush (arch); - if (bfd_stat (arch, &archstat) == -1) { - perror ("Reading archive file mod timestamp"); - return true; /* Can't read mod time for some reason */ - } - if (archstat.st_mtime <= bfd_ardata(arch)->armap_timestamp) + if (bfd_stat (arch, &archstat) == -1) + { + perror ("Reading archive file mod timestamp"); + return true; /* Can't read mod time for some reason */ + } + if (archstat.st_mtime <= bfd_ardata (arch)->armap_timestamp) return true; /* OK by the linker's rules */ /* Update the timestamp. */ - bfd_ardata(arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET; + bfd_ardata (arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET; /* Prepare an ASCII version suitable for writing. */ memset (hdr.ar_date, 0, sizeof (hdr.ar_date)); - sprintf (hdr.ar_date, "%ld", bfd_ardata(arch)->armap_timestamp); + sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp); for (i = 0; i < sizeof (hdr.ar_date); i++) - if (hdr.ar_date[i] == '\0') - (hdr.ar_date)[i] = ' '; + if (hdr.ar_date[i] == '\0') + (hdr.ar_date)[i] = ' '; /* Write it into the file. */ - bfd_seek (arch, bfd_ardata(arch)->armap_datepos, SEEK_SET); - if (bfd_write (hdr.ar_date, sizeof(hdr.ar_date), 1, arch) - != sizeof(hdr.ar_date)) { - perror ("Writing updated armap timestamp"); - return true; /* Some error while writing */ - } + if (bfd_seek (arch, bfd_ardata (arch)->armap_datepos, SEEK_SET) != 0 + || (bfd_write (hdr.ar_date, sizeof (hdr.ar_date), 1, arch) + != sizeof (hdr.ar_date))) + { + /* FIXME: bfd can't call perror. */ + perror ("Writing updated armap timestamp"); + return true; /* Some error while writing */ + } return false; /* We updated the timestamp successfully. */ } - /* A coff armap looks like : - lARMAG - struct ar_hdr with name = '/' - number of symbols - offset of file for symbol 0 - offset of file for symbol 1 + lARMAG + struct ar_hdr with name = '/' + number of symbols + offset of file for symbol 0 + offset of file for symbol 1 - offset of file for symbol n-1 - symbol name 0 - symbol name 1 - - symbol name n-1 + offset of file for symbol n-1 + symbol name 0 + symbol name 1 + symbol name n-1 */ boolean @@ -1690,81 +1926,91 @@ coff_write_armap (arch, elength, map, symbol_count, stridx) unsigned int symbol_count; int stridx; { - /* The size of the ranlib is the number of exported symbols in the - archive * the number of bytes in a int, + an int for the count */ + /* The size of the ranlib is the number of exported symbols in the + archive * the number of bytes in a int, + an int for the count */ + unsigned int ranlibsize = (symbol_count * 4) + 4; + unsigned int stringsize = stridx; + unsigned int mapsize = stringsize + ranlibsize; + file_ptr archive_member_file_ptr; + bfd *current = arch->archive_head; + int count; + struct ar_hdr hdr; + unsigned int i; + int padit = mapsize & 1; - unsigned int ranlibsize = (symbol_count * 4) + 4; - unsigned int stringsize = stridx; - unsigned int mapsize = stringsize + ranlibsize; - file_ptr archive_member_file_ptr; - bfd *current = arch->archive_head; - int count; - struct ar_hdr hdr; - unsigned int i; - int padit = mapsize & 1; - - if (padit) mapsize ++; + if (padit) + mapsize++; - /* work out where the first object file will go in the archive */ - archive_member_file_ptr = mapsize + elength + sizeof (struct ar_hdr) + SARMAG; + /* work out where the first object file will go in the archive */ + archive_member_file_ptr = (mapsize + + elength + + sizeof (struct ar_hdr) + + SARMAG); - memset ((char *)(&hdr), 0, sizeof (struct ar_hdr)); - hdr.ar_name[0] = '/'; - sprintf (hdr.ar_size, "%-10d", (int) mapsize); - sprintf (hdr.ar_date, "%ld", (long)time (NULL)); - /* This, at least, is what Intel coff sets the values to.: */ - sprintf ((hdr.ar_uid), "%d", 0); - sprintf ((hdr.ar_gid), "%d", 0); - sprintf ((hdr.ar_mode), "%-7o",(unsigned ) 0); - hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n'; + memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); + hdr.ar_name[0] = '/'; + sprintf (hdr.ar_size, "%-10d", (int) mapsize); + sprintf (hdr.ar_date, "%ld", (long) time (NULL)); + /* This, at least, is what Intel coff sets the values to.: */ + sprintf ((hdr.ar_uid), "%d", 0); + sprintf ((hdr.ar_gid), "%d", 0); + sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0); + strncpy (hdr.ar_fmag, ARFMAG, 2); - for (i = 0; i < sizeof (struct ar_hdr); i++) - if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' '; + for (i = 0; i < sizeof (struct ar_hdr); i++) + if (((char *) (&hdr))[i] == '\0') + (((char *) (&hdr))[i]) = ' '; - /* Write the ar header for this item and the number of symbols */ + /* Write the ar header for this item and the number of symbols */ - - bfd_write ((PTR)&hdr, 1, sizeof (struct ar_hdr), arch); + if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), arch) + != sizeof (struct ar_hdr)) + return false; - bfd_write_bigendian_4byte_int(arch, symbol_count); + bfd_write_bigendian_4byte_int (arch, symbol_count); - /* Two passes, first write the file offsets for each symbol - - remembering that each offset is on a two byte boundary. */ + /* Two passes, first write the file offsets for each symbol - + remembering that each offset is on a two byte boundary. */ - /* Write out the file offset for the file associated with each - symbol, and remember to keep the offsets padded out. */ + /* Write out the file offset for the file associated with each + symbol, and remember to keep the offsets padded out. */ - current = arch->archive_head; - count = 0; - while (current != (bfd *)NULL && count < symbol_count) { - /* For each symbol which is used defined in this object, write out - the object file's address in the archive */ - - while (((bfd *)(map[count]).pos) == current) { - bfd_write_bigendian_4byte_int(arch, archive_member_file_ptr); - count++; + current = arch->archive_head; + count = 0; + while (current != (bfd *) NULL && count < symbol_count) + { + /* For each symbol which is used defined in this object, write out + the object file's address in the archive */ + + while (((bfd *) (map[count]).pos) == current) + { + bfd_write_bigendian_4byte_int (arch, archive_member_file_ptr); + count++; } - /* Add size of this archive entry */ - archive_member_file_ptr += arelt_size (current) + sizeof (struct - ar_hdr); - /* remember aboout the even alignment */ - archive_member_file_ptr += archive_member_file_ptr % 2; - current = current->next; - } - - - - /* now write the strings themselves */ - for (count = 0; count < symbol_count; count++) { - bfd_write ((PTR)*((map[count]).name), - 1, - strlen (*((map[count]).name))+1, arch); - + /* Add size of this archive entry */ + archive_member_file_ptr += (arelt_size (current) + + sizeof (struct ar_hdr)); + /* remember aboout the even alignment */ + archive_member_file_ptr += archive_member_file_ptr % 2; + current = current->next; } - /* The spec sez this should be a newline. But in order to be - bug-compatible for arc960 we use a null. */ - if (padit) - bfd_write("\0",1,1,arch); - return true; + /* now write the strings themselves */ + for (count = 0; count < symbol_count; count++) + { + size_t len = strlen (*map[count].name) + 1; + + if (bfd_write (*map[count].name, 1, len, arch) != len) + return false; + } + + /* The spec sez this should be a newline. But in order to be + bug-compatible for arc960 we use a null. */ + if (padit) + { + if (bfd_write ("", 1, 1, arch) != 1) + return false; + } + + return true; } diff --git a/gnu/usr.bin/gdb/bfd/archures.c b/gnu/usr.bin/gdb/bfd/archures.c index 9697904bd733..1bed6379927f 100644 --- a/gnu/usr.bin/gdb/bfd/archures.c +++ b/gnu/usr.bin/gdb/bfd/archures.c @@ -1,8 +1,7 @@ /* BFD library support routines for architectures. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Hacked by John Gilmore and Steve Chamberlain of Cygnus Support. - This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify @@ -24,19 +23,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION Architectures - BFD's idea of an architecture is implimented in - <>. BFD keeps one atom in a BFD describing the - architecture of the data attached to the BFD; a pointer to a + BFD keeps one atom in a BFD describing the + architecture of the data attached to the BFD: a pointer to a <>. - Pointers to structures can be requested independently of a bfd + Pointers to structures can be requested independently of a BFD so that an architecture's information can be interrogated - without access to an open bfd. + without access to an open BFD. - The arch information is provided by each architecture package. - The set of default architectures is selected by the #define + The architecture information is provided by each architecture package. + The set of default architectures is selected by the macro <>. This is normally set up in the - <> file of your choice. If the name is not + @file{config/@var{target}.mt} file of your choice. If the name is not defined, then all the architectures supported are included. When BFD starts up, all the architectures are called with an @@ -44,6 +42,8 @@ SECTION insert as many items into the list of architectures as it wants to; generally this would be one for each machine and one for the default case (an item with a machine field of 0). + + BFD's idea of an architecture is implemented in @file{archures.c}. */ /* @@ -53,11 +53,11 @@ SUBSECTION DESCRIPTION This enum gives the object file's CPU architecture, in a - global sense --- i.e., what processor family does it belong to? - There is another field, which indicates what processor within + global sense---i.e., what processor family does it belong to? + Another field indicates which processor within the family is in use. The machine gives a number which - distingushes different versions of the architecture, - containing for example 2 and 3 for Intel i960 KA and i960 KB, + distinguishes different versions of the architecture, + containing, for example, 2 and 3 for Intel i960 KA and i960 KB, and 68020 and 68030 for Motorola 68020 and 68030. .enum bfd_architecture @@ -97,6 +97,7 @@ DESCRIPTION . bfd_arch_h8300, {* Hitachi H8/300 *} .#define bfd_mach_h8300 1 .#define bfd_mach_h8300h 2 +. bfd_arch_powerpc, {* PowerPC *} . bfd_arch_rs6000, {* IBM RS/6000 *} . bfd_arch_hppa, {* HP PA RISC *} . bfd_arch_z8k, {* Zilog Z8000 *} @@ -105,6 +106,7 @@ DESCRIPTION . bfd_arch_h8500, {* Hitachi H8/500 *} . bfd_arch_sh, {* Hitachi SH *} . bfd_arch_alpha, {* Dec Alpha *} +. bfd_arch_ns32k, {* National Semiconductors ns32000 *} . bfd_arch_last . }; @@ -166,13 +168,13 @@ SYNOPSIS DESCRIPTION Return a printable string representing the architecture and machine - from the pointer to the arch info structure + from the pointer to the architecture info structure. */ CONST char * -DEFUN(bfd_printable_name, (abfd), - bfd *abfd) +bfd_printable_name (abfd) + bfd *abfd; { return abfd->arch_info->printable_name; } @@ -184,19 +186,18 @@ FUNCTION bfd_scan_arch SYNOPSIS - bfd_arch_info_type *bfd_scan_arch(CONST char *); + bfd_arch_info_type *bfd_scan_arch(CONST char *string); DESCRIPTION - This routine is provided with a string and tries to work out - if bfd supports any cpu which could be described with the name - provided. The routine returns a pointer to an arch_info + Figure out if BFD supports any cpu which could be described with + the name @var{string}. Return a pointer to an <> structure if a machine is found, otherwise NULL. */ bfd_arch_info_type * -DEFUN(bfd_scan_arch,(string), - CONST char *string) +bfd_scan_arch (string) + CONST char *string; { struct bfd_arch_info *ap; @@ -223,18 +224,17 @@ SYNOPSIS CONST bfd *bbfd); DESCRIPTION - This routine is used to determine whether two BFDs' - architectures and achine types are compatible. It calculates + Determine whether two BFDs' + architectures and machine types are compatible. Calculates the lowest common denominator between the two architectures and machine types implied by the BFDs and returns a pointer to - an arch_info structure describing the compatible machine. + an <> structure describing the compatible machine. */ CONST bfd_arch_info_type * -DEFUN(bfd_arch_get_compatible,(abfd, bbfd), -CONST bfd *abfd AND -CONST bfd *bbfd) - +bfd_arch_get_compatible (abfd, bbfd) + CONST bfd *abfd; + CONST bfd *bbfd; { return abfd->arch_info->compatible(abfd->arch_info,bbfd->arch_info); } @@ -268,13 +268,16 @@ FUNCTION bfd_set_arch_info SYNOPSIS - void bfd_set_arch_info(bfd *, bfd_arch_info_type *); + void bfd_set_arch_info(bfd *abfd, bfd_arch_info_type *arg); +DESCRIPTION + Set the architecture info of @var{abfd} to @var{arg}. */ -void DEFUN(bfd_set_arch_info,(abfd, arg), -bfd *abfd AND -bfd_arch_info_type *arg) +void +bfd_set_arch_info (abfd, arg) + bfd *abfd; + bfd_arch_info_type *arg; { abfd->arch_info = arg; } @@ -289,15 +292,17 @@ SYNOPSIS unsigned long mach); DESCRIPTION - Set the architecture and machine type in a bfd. This finds the - correct pointer to structure and inserts it into the arch_info + Set the architecture and machine type in BFD @var{abfd} + to @var{arch} and @var{mach}. Find the correct + pointer to a structure and insert it into the <> pointer. */ -boolean DEFUN(bfd_default_set_arch_mach,(abfd, arch, mach), - bfd *abfd AND - enum bfd_architecture arch AND - unsigned long mach) +boolean +bfd_default_set_arch_mach (abfd, arch, mach) + bfd *abfd; + enum bfd_architecture arch; + unsigned long mach; { static struct bfd_arch_info *old_ptr = &bfd_default_arch_struct; boolean found = false; @@ -319,7 +324,7 @@ boolean DEFUN(bfd_default_set_arch_mach,(abfd, arch, mach), if (found==false) { /*looked for it and it wasn't there, so put in the default */ old_ptr = &bfd_default_arch_struct; - bfd_error = bad_value; + bfd_set_error (bfd_error_bad_value); } } else { @@ -333,9 +338,6 @@ boolean DEFUN(bfd_default_set_arch_mach,(abfd, arch, mach), } - - - /* FUNCTION bfd_get_arch @@ -344,12 +346,14 @@ SYNOPSIS enum bfd_architecture bfd_get_arch(bfd *abfd); DESCRIPTION - Returns the enumerated type which describes the supplied bfd's - architecture + Return the enumerated type which describes the BFD @var{abfd}'s + architecture. */ -enum bfd_architecture DEFUN(bfd_get_arch, (abfd), bfd *abfd) +enum bfd_architecture +bfd_get_arch (abfd) + bfd *abfd; { return abfd->arch_info->arch; } @@ -362,12 +366,13 @@ SYNOPSIS unsigned long bfd_get_mach(bfd *abfd); DESCRIPTION - Returns the long type which describes the supplied bfd's - machine + Return the long type which describes the BFD @var{abfd}'s + machine. */ unsigned long -DEFUN(bfd_get_mach, (abfd), bfd *abfd) +bfd_get_mach (abfd) + bfd *abfd; { return abfd->arch_info->mach; } @@ -380,14 +385,17 @@ SYNOPSIS unsigned int bfd_arch_bits_per_byte(bfd *abfd); DESCRIPTION - Returns the number of bits in one of the architectures bytes + Return the number of bits in one of the BFD @var{abfd}'s + architecture's bytes. */ -unsigned int DEFUN(bfd_arch_bits_per_byte, (abfd), bfd *abfd) - { - return abfd->arch_info->bits_per_byte; - } +unsigned int +bfd_arch_bits_per_byte (abfd) + bfd *abfd; +{ + return abfd->arch_info->bits_per_byte; +} /* FUNCTION @@ -397,13 +405,16 @@ SYNOPSIS unsigned int bfd_arch_bits_per_address(bfd *abfd); DESCRIPTION - Returns the number of bits in one of the architectures addresses + Return the number of bits in one of the BFD @var{abfd}'s + architecture's addresses. */ -unsigned int DEFUN(bfd_arch_bits_per_address, (abfd), bfd *abfd) - { - return abfd->arch_info->bits_per_address; - } +unsigned int +bfd_arch_bits_per_address (abfd) + bfd *abfd; +{ + return abfd->arch_info->bits_per_address; +} extern void bfd_a29k_arch PARAMS ((void)); @@ -416,12 +427,14 @@ extern void bfd_i960_arch PARAMS ((void)); extern void bfd_m68k_arch PARAMS ((void)); extern void bfd_m88k_arch PARAMS ((void)); extern void bfd_mips_arch PARAMS ((void)); +extern void bfd_powerpc_arch PARAMS ((void)); extern void bfd_rs6000_arch PARAMS ((void)); extern void bfd_sh_arch PARAMS ((void)); extern void bfd_sparc_arch PARAMS ((void)); extern void bfd_vax_arch PARAMS ((void)); extern void bfd_we32k_arch PARAMS ((void)); extern void bfd_z8k_arch PARAMS ((void)); +extern void bfd_ns32k_arch PARAMS ((void)); static void (*archures_init_table[]) PARAMS ((void)) = { @@ -438,12 +451,14 @@ static void (*archures_init_table[]) PARAMS ((void)) = bfd_m68k_arch, bfd_m88k_arch, bfd_mips_arch, + bfd_powerpc_arch, bfd_rs6000_arch, bfd_sh_arch, bfd_sparc_arch, bfd_vax_arch, bfd_we32k_arch, bfd_z8k_arch, + bfd_ns32k_arch, #endif 0 }; @@ -455,16 +470,16 @@ INTERNAL_FUNCTION bfd_arch_init SYNOPSIS - void bfd_arch_init(void); + void bfd_arch_init(void); DESCRIPTION - This routine initializes the architecture dispatch table by + Initialize the architecture dispatch table by calling all installed architecture packages and getting them to poke around. */ void -DEFUN_VOID(bfd_arch_init) +bfd_arch_init () { void (**ptable) PARAMS ((void)); for (ptable = archures_init_table; @@ -481,14 +496,15 @@ INTERNAL_FUNCTION bfd_arch_linkin SYNOPSIS - void bfd_arch_linkin(bfd_arch_info_type *); + void bfd_arch_linkin(bfd_arch_info_type *ptr); DESCRIPTION - Link the provided arch info structure into the list + Link the architecture info structure @var{ptr} into the list. */ -void DEFUN(bfd_arch_linkin,(ptr), - bfd_arch_info_type *ptr) +void +bfd_arch_linkin (ptr) + bfd_arch_info_type *ptr; { ptr->next = bfd_arch_info_list; bfd_arch_info_list = ptr; @@ -509,9 +525,9 @@ DESCRIPTION */ CONST bfd_arch_info_type * -DEFUN(bfd_default_compatible,(a,b), - CONST bfd_arch_info_type *a AND - CONST bfd_arch_info_type *b) +bfd_default_compatible (a,b) + CONST bfd_arch_info_type *a; + CONST bfd_arch_info_type *b; { if(a->arch != b->arch) return NULL; @@ -530,7 +546,7 @@ INTERNAL_FUNCTION bfd_default_scan SYNOPSIS - boolean bfd_default_scan(CONST struct bfd_arch_info *, CONST char *); + boolean bfd_default_scan(CONST struct bfd_arch_info *info, CONST char *string); DESCRIPTION The default function for working out whether this is an @@ -538,9 +554,9 @@ DESCRIPTION */ boolean -DEFUN(bfd_default_scan,(info, string), -CONST struct bfd_arch_info *info AND -CONST char *string) +bfd_default_scan (info, string) + CONST struct bfd_arch_info *info; + CONST char *string; { CONST char *ptr_src; CONST char *ptr_tst; @@ -647,21 +663,20 @@ CONST char *string) } - - /* FUNCTION bfd_get_arch_info - SYNOPSIS - bfd_arch_info_type * bfd_get_arch_info(bfd *); + bfd_arch_info_type * bfd_get_arch_info(bfd *abfd); +DESCRIPTION + Return the architecture info struct in @var{abfd}. */ bfd_arch_info_type * -DEFUN(bfd_get_arch_info,(abfd), -bfd *abfd) +bfd_get_arch_info (abfd) + bfd *abfd; { return abfd->arch_info; } @@ -678,16 +693,16 @@ SYNOPSIS long machine); DESCRIPTION - Look for the architecure info struct which matches the - arguments given. A machine of 0 will match the + Look for the architecure info structure which matches the + arguments @var{arch} and @var{machine}. A machine of 0 matches the machine/architecture structure which marks itself as the default. */ bfd_arch_info_type * -DEFUN(bfd_lookup_arch,(arch, machine), -enum bfd_architecture arch AND -long machine) +bfd_lookup_arch (arch, machine) + enum bfd_architecture arch; + long machine; { bfd_arch_info_type *ap; bfd_check_init(); @@ -704,26 +719,25 @@ long machine) } - /* FUNCTION bfd_printable_arch_mach SYNOPSIS - CONST char * bfd_printable_arch_mach + CONST char *bfd_printable_arch_mach (enum bfd_architecture arch, unsigned long machine); DESCRIPTION Return a printable string representing the architecture and machine type. - NB. The use of this routine is depreciated. + This routine is depreciated. */ CONST char * -DEFUN(bfd_printable_arch_mach,(arch, machine), - enum bfd_architecture arch AND - unsigned long machine) +bfd_printable_arch_mach (arch, machine) + enum bfd_architecture arch; + unsigned long machine; { bfd_arch_info_type *ap = bfd_lookup_arch(arch, machine); if(ap) return ap->printable_name; diff --git a/gnu/usr.bin/gdb/bfd/bfd.c b/gnu/usr.bin/gdb/bfd/bfd.c index a994cd170a00..77e43ec3266f 100644 --- a/gnu/usr.bin/gdb/bfd/bfd.c +++ b/gnu/usr.bin/gdb/bfd/bfd.c @@ -1,5 +1,5 @@ /* Generic BFD library interface and support routines. - Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -22,13 +22,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION <> - A BFD is has type <>; objects of this type are the - cornerstone of any application using <>. References - though the BFD and to data in the BFD give the entire BFD - functionality. + A BFD has type <>; objects of this type are the + cornerstone of any application using BFD. Using BFD + consists of making references though the BFD and to data in the BFD. - Here is the struct used to define the type <>. This - contains the major data about the file, and contains pointers + Here is the structure that defines the type <>. It + contains the major data about the file and pointers to the rest of the data. CODE_FRAGMENT @@ -39,7 +38,7 @@ CODE_FRAGMENT . CONST char *filename; . . {* A pointer to the target jump table. *} -. struct bfd_target *xvec; +. const struct bfd_target *xvec; . . {* To avoid dragging too many header files into every file that . includes `<>', IOSTREAM has been declared as a "char @@ -48,13 +47,14 @@ CODE_FRAGMENT . is the result of an fopen on the filename. *} . char *iostream; . -. {* Is the file being cached *} +. {* Is the file descriptor being cached? That is, can it be closed as +. needed, and re-opened when accessed later? *} . . boolean cacheable; . . {* Marks whether there was a default target specified when the -. BFD was opened. This is used to select what matching algorithm -. to use to chose the back end. *} +. BFD was opened. This is used to select which matching algorithm +. to use to choose the back end. *} . . boolean target_defaulted; . @@ -64,12 +64,11 @@ CODE_FRAGMENT . struct _bfd *lru_prev, *lru_next; . . {* When a file is closed by the caching routines, BFD retains -. state information on the file here: -. *} +. state information on the file here: *} . . file_ptr where; . -. {* and here:*} +. {* and here: (``once'' means at least once) *} . . boolean opened_once; . @@ -86,7 +85,7 @@ CODE_FRAGMENT . . int ifd; . -. {* The format which belongs to the BFD.*} +. {* The format which belongs to the BFD. (object, core, etc.) *} . . bfd_format format; . @@ -108,7 +107,7 @@ CODE_FRAGMENT . file_ptr origin; . . {* Remember when output has begun, to stop strange things -. happening. *} +. from happening. *} . boolean output_has_begun; . . {* Pointer to linked list of sections*} @@ -124,7 +123,7 @@ CODE_FRAGMENT . {* Used for input and output*} . unsigned int symcount; . -. {* Symbol table for output BFD*} +. {* Symbol table for output BFD (with symcount entries) *} . struct symbol_cache_entry **outsymbols; . . {* Pointer to structure which contains architecture information*} @@ -132,11 +131,18 @@ CODE_FRAGMENT . . {* Stuff only useful for archives:*} . PTR arelt_data; -. struct _bfd *my_archive; -. struct _bfd *next; -. struct _bfd *archive_head; +. struct _bfd *my_archive; {* The containing archive BFD. *} +. struct _bfd *next; {* The next BFD in the archive. *} +. struct _bfd *archive_head; {* The first BFD in the archive. *} . boolean has_armap; . +. {* A chain of BFD structures involved in a link. *} +. struct _bfd *link_next; +. +. {* A field used by _bfd_generic_link_add_archive_symbols. This will +. be used only for archive elements. *} +. int archive_pass; +. . {* Used by the back end to hold private data. *} . . union @@ -156,11 +162,13 @@ CODE_FRAGMENT . struct bout_data_struct *bout_data; . struct sun_core_struct *sun_core_data; . struct trad_core_struct *trad_core_data; -. struct hppa_data_struct *hppa_data; +. struct som_data_struct *som_data; . struct hpux_core_struct *hpux_core_data; +. struct hppabsd_core_struct *hppabsd_core_data; . struct sgi_core_struct *sgi_core_data; . struct lynx_core_struct *lynx_core_data; . struct osf_core_struct *osf_core_data; +. struct cisco_core_struct *cisco_core_data; . PTR any; . } tdata; . @@ -169,15 +177,13 @@ CODE_FRAGMENT . . {* Where all the allocated stuff under this BFD goes *} . struct obstack memory; -. -. {* Is this really needed in addition to usrdata? *} -. asymbol **ld_symbols; .}; . */ #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" #include "coff/internal.h" #include "coff/sym.h" @@ -186,31 +192,67 @@ CODE_FRAGMENT #undef obj_symbols #include "libelf.h" + +/* +SECTION + Error reporting + + Most BFD functions return nonzero on success (check their + individual documentation for precise semantics). On an error, + they call <> to set an error condition that callers + can check by calling <>. + If that returns <>, then check + <>. + + The easiest way to report a BFD error to the user is to + use <>. + +SUBSECTION + Type <> + + The values returned by <> are defined by the + enumerated type <>. + +CODE_FRAGMENT +. +.typedef enum bfd_error +.{ +. bfd_error_no_error = 0, +. bfd_error_system_call, +. bfd_error_invalid_target, +. bfd_error_wrong_format, +. bfd_error_invalid_operation, +. bfd_error_no_memory, +. bfd_error_no_symbols, +. bfd_error_no_more_archived_files, +. bfd_error_malformed_archive, +. bfd_error_file_not_recognized, +. bfd_error_file_ambiguously_recognized, +. bfd_error_no_contents, +. bfd_error_nonrepresentable_section, +. bfd_error_no_debug_section, +. bfd_error_bad_value, +. bfd_error_file_truncated, +. bfd_error_invalid_error_code +.} bfd_error_type; +. +*/ + #undef strerror extern char *strerror(); -/** Error handling - o - Most functions return nonzero on success (check doc for - precise semantics); 0 or NULL on error. - o - Internal errors are documented by the value of bfd_error. - If that is system_call_error then check errno. - o - The easiest way to report this to the user is to use bfd_perror. -*/ - -bfd_ec bfd_error = no_error; +static bfd_error_type bfd_error = bfd_error_no_error; CONST char *CONST bfd_errmsgs[] = { "No error", "System call error", - "Invalid target", + "Invalid bfd target", "File in wrong format", "Invalid operation", "Memory exhausted", "No symbols", - "No relocation info", "No more archived files", "Malformed archive", - "Symbol not found", "File format not recognized", "File format is ambiguous", "Section has no contents", @@ -221,130 +263,128 @@ CONST char *CONST bfd_errmsgs[] = { "#" }; -static -void -DEFUN(bfd_nonrepresentable_section,(abfd, name), - CONST bfd * CONST abfd AND - CONST char * CONST name) +/* +FUNCTION + bfd_get_error + +SYNOPSIS + bfd_error_type bfd_get_error (void); + +DESCRIPTION + Return the current BFD error condition. +*/ + +bfd_error_type +bfd_get_error () { - fprintf(stderr, - "bfd error writing file %s, format %s can't represent section %s\n", - abfd->filename, - abfd->xvec->name, - name); - exit(1); + return bfd_error; } -/*ARGSUSED*/ -static -void -DEFUN(bfd_undefined_symbol,(relent, seclet), - CONST arelent *relent AND - CONST struct bfd_seclet *seclet) +/* +FUNCTION + bfd_set_error + +SYNOPSIS + void bfd_set_error (bfd_error_type error_tag); + +DESCRIPTION + Set the BFD error condition to be @var{error_tag}. +*/ + +void +bfd_set_error (error_tag) + bfd_error_type error_tag; { - asymbol *symbol = *(relent->sym_ptr_ptr); - fprintf(stderr, "bfd error relocating, symbol %s is undefined\n", - symbol->name); - exit(1); -} -/*ARGSUSED*/ -static -void -DEFUN(bfd_reloc_value_truncated,(relent, seclet), - CONST arelent *relent AND - struct bfd_seclet *seclet) -{ - fprintf(stderr, "bfd error relocating, value truncated\n"); - exit(1); -} -/*ARGSUSED*/ -static -void -DEFUN(bfd_reloc_is_dangerous,(relent, seclet), - CONST arelent *relent AND - CONST struct bfd_seclet *seclet) -{ - fprintf(stderr, "bfd error relocating, dangerous\n"); - exit(1); + bfd_error = error_tag; } -bfd_error_vector_type bfd_error_vector = - { - bfd_nonrepresentable_section , - bfd_undefined_symbol, - bfd_reloc_value_truncated, - bfd_reloc_is_dangerous, - }; +/* +FUNCTION + bfd_errmsg +SYNOPSIS + CONST char *bfd_errmsg (bfd_error_type error_tag); + +DESCRIPTION + Return a string describing the error @var{error_tag}, or + the system error if @var{error_tag} is <>. +*/ CONST char * bfd_errmsg (error_tag) - bfd_ec error_tag; + bfd_error_type error_tag; { #ifndef errno extern int errno; #endif - if (error_tag == system_call_error) + if (error_tag == bfd_error_system_call) return strerror (errno); - if ((((int)error_tag <(int) no_error) || - ((int)error_tag > (int)invalid_error_code))) - error_tag = invalid_error_code;/* sanity check */ + if ((((int)error_tag <(int) bfd_error_no_error) || + ((int)error_tag > (int)bfd_error_invalid_error_code))) + error_tag = bfd_error_invalid_error_code;/* sanity check */ return bfd_errmsgs [(int)error_tag]; } -void -DEFUN (bfd_default_error_trap, (error_tag), - bfd_ec error_tag) -{ - fprintf(stderr, "bfd assert fail (%s)\n", bfd_errmsg(error_tag)); -} +/* +FUNCTION + bfd_perror -void (*bfd_error_trap) PARAMS ((bfd_ec)) = bfd_default_error_trap; -void (*bfd_error_nonrepresentabltrap) PARAMS ((bfd_ec)) = bfd_default_error_trap; +SYNOPSIS + void bfd_perror (CONST char *message); + +DESCRIPTION + Print to the standard error stream a string describing the + last BFD error that occurred, or the last system error if + the last BFD error was a system call failure. If @var{message} + is non-NULL and non-empty, the error string printed is preceded + by @var{message}, a colon, and a space. It is followed by a newline. +*/ void -DEFUN(bfd_perror,(message), - CONST char *message) +bfd_perror (message) + CONST char *message; { - if (bfd_error == system_call_error) + if (bfd_get_error () == bfd_error_system_call) perror((char *)message); /* must be system error then... */ else { if (message == NULL || *message == '\0') - fprintf (stderr, "%s\n", bfd_errmsg (bfd_error)); + fprintf (stderr, "%s\n", bfd_errmsg (bfd_get_error ())); else - fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_error)); + fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_get_error ())); } } - -/** Symbols */ - + +/* +SECTION + Symbols +*/ /* FUNCTION bfd_get_reloc_upper_bound SYNOPSIS - unsigned int bfd_get_reloc_upper_bound(bfd *abfd, asection *sect); + long bfd_get_reloc_upper_bound(bfd *abfd, asection *sect); DESCRIPTION - This function return the number of bytes required to store the - relocation information associated with section <> - attached to bfd <> + Return the number of bytes required to store the + relocation information associated with section @var{sect} + attached to bfd @var{abfd}. If an error occurs, return -1. */ -unsigned int -DEFUN(bfd_get_reloc_upper_bound,(abfd, asect), - bfd *abfd AND - sec_ptr asect) +long +bfd_get_reloc_upper_bound (abfd, asect) + bfd *abfd; + sec_ptr asect; { if (abfd->format != bfd_object) { - bfd_error = invalid_operation; - return 0; + bfd_set_error (bfd_error_invalid_operation); + return -1; } return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect)); @@ -355,84 +395,39 @@ FUNCTION bfd_canonicalize_reloc SYNOPSIS - unsigned int bfd_canonicalize_reloc + long bfd_canonicalize_reloc (bfd *abfd, asection *sec, arelent **loc, asymbol **syms); DESCRIPTION - This function calls the back end associated with the open - <> and translates the external form of the relocation - information attached to <> into the internal canonical - form. The table is placed into memory at <>, which has + Call the back end associated with the open BFD + @var{abfd} and translate the external form of the relocation + information attached to @var{sec} into the internal canonical + form. Place the table into memory at @var{loc}, which has been preallocated, usually by a call to - <>. + <>. Returns the number of relocs, or + -1 on error. - The <> table is also needed for horrible internal magic + The @var{syms} table is also needed for horrible internal magic reasons. */ -unsigned int -DEFUN(bfd_canonicalize_reloc,(abfd, asect, location, symbols), - bfd *abfd AND - sec_ptr asect AND - arelent **location AND - asymbol **symbols) -{ - if (abfd->format != bfd_object) { - bfd_error = invalid_operation; - return 0; - } - return BFD_SEND (abfd, _bfd_canonicalize_reloc, - (abfd, asect, location, symbols)); - } - - -/* -FUNCTION - bfd_set_file_flags - -SYNOPSIS - boolean bfd_set_file_flags(bfd *abfd, flagword flags); - -DESCRIPTION - This function attempts to set the flag word in the referenced - BFD structure to the value supplied. - - Possible errors are: - o wrong_format - The target bfd was not of object format. - o invalid_operation - The target bfd was open for reading. - o invalid_operation - - The flag word contained a bit which was not applicable to the - type of file. eg, an attempt was made to set the D_PAGED bit - on a bfd format which does not support demand paging - -*/ - -boolean -bfd_set_file_flags (abfd, flags) +long +bfd_canonicalize_reloc (abfd, asect, location, symbols) bfd *abfd; - flagword flags; + sec_ptr asect; + arelent **location; + asymbol **symbols; { if (abfd->format != bfd_object) { - bfd_error = wrong_format; - return false; + bfd_set_error (bfd_error_invalid_operation); + return -1; } - - if (bfd_read_p (abfd)) { - bfd_error = invalid_operation; - return false; - } - - bfd_get_file_flags (abfd) = flags; - if ((flags & bfd_applicable_file_flags (abfd)) != flags) { - bfd_error = invalid_operation; - return false; - } - -return true; + return BFD_SEND (abfd, _bfd_canonicalize_reloc, + (abfd, asect, location, symbols)); } /* @@ -444,8 +439,9 @@ SYNOPSIS (bfd *abfd, asection *sec, arelent **rel, unsigned int count) DESCRIPTION - This function sets the relocation pointer and count within a - section to the supplied values. + Set the relocation pointer and count within + section @var{sec} to the values @var{rel} and @var{count}. + The argument @var{abfd} is ignored. */ /*ARGSUSED*/ @@ -460,6 +456,50 @@ bfd_set_reloc (ignore_abfd, asect, location, count) asect->reloc_count = count; } +/* +FUNCTION + bfd_set_file_flags + +SYNOPSIS + boolean bfd_set_file_flags(bfd *abfd, flagword flags); + +DESCRIPTION + Set the flag word in the BFD @var{abfd} to the value @var{flags}. + + Possible errors are: + o <> - The target bfd was not of object format. + o <> - The target bfd was open for reading. + o <> - + The flag word contained a bit which was not applicable to the + type of file. E.g., an attempt was made to set the <> bit + on a BFD format which does not support demand paging. + +*/ + +boolean +bfd_set_file_flags (abfd, flags) + bfd *abfd; + flagword flags; +{ + if (abfd->format != bfd_object) { + bfd_set_error (bfd_error_wrong_format); + return false; + } + + if (bfd_read_p (abfd)) { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + + bfd_get_file_flags (abfd) = flags; + if ((flags & bfd_applicable_file_flags (abfd)) != flags) { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + +return true; +} + void bfd_assert(file, line) char *file; @@ -473,14 +513,14 @@ int line; FUNCTION bfd_set_start_address +SYNOPSIS + boolean bfd_set_start_address(bfd *abfd, bfd_vma vma); + DESCRIPTION - Marks the entry point of an output BFD. + Make @var{vma} the entry point of output BFD @var{abfd}. RETURNS Returns <> on success, <> otherwise. - -SYNOPSIS - boolean bfd_set_start_address(bfd *, bfd_vma); */ boolean @@ -495,14 +535,14 @@ bfd_vma vma; /* FUNCTION - The bfd_get_mtime function + bfd_get_mtime SYNOPSIS - long bfd_get_mtime(bfd *); + long bfd_get_mtime(bfd *abfd); DESCRIPTION - Return file modification time (as read from file system, or - from archive header for archive members). + Return the file modification time (as read from the file system, or + from the archive header for archive members). */ @@ -526,32 +566,32 @@ bfd_get_mtime (abfd) /* FUNCTION - The bfd_get_size function + bfd_get_size SYNOPSIS - long bfd_get_size(bfd *); + long bfd_get_size(bfd *abfd); DESCRIPTION - Return file size (as read from file system) for the file - associated with a bfd. + Return the file size (as read from file system) for the file + associated with BFD @var{abfd}. - Note that the initial motivation for, and use of, this routine is not - so we can get the exact size of the object the bfd applies to, since - that might not be generally possible (archive members for example?). - Although it would be ideal if someone could eventually modify + The initial motivation for, and use of, this routine is not + so we can get the exact size of the object the BFD applies to, since + that might not be generally possible (archive members for example). + It would be ideal if someone could eventually modify it so that such results were guaranteed. Instead, we want to ask questions like "is this NNN byte sized object I'm about to try read from file offset YYY reasonable?" - As as example of where we might want to do this, some object formats - use string tables for which the first sizeof(long) bytes of the table - contain the size of the table itself, including the size bytes. + As as example of where we might do this, some object formats + use string tables for which the first <> bytes of the + table contain the size of the table itself, including the size bytes. If an application tries to read what it thinks is one of these string tables, without some way to validate the size, and for some reason the size is wrong (byte swapping error, wrong location - for the string table, etc), the only clue is likely to be a read + for the string table, etc.), the only clue is likely to be a read error when it tries to read the table, or a "virtual memory - exhausted" error when it tries to allocated 15 bazillon bytes + exhausted" error when it tries to allocate 15 bazillon bytes of space for the 15 bazillon byte table it is about to read. This function at least allows us to answer the quesion, "is the size reasonable?". @@ -573,14 +613,14 @@ bfd_get_size (abfd) /* FUNCTION - The bfd_get_gp_size function + bfd_get_gp_size SYNOPSIS - int bfd_get_gp_size(bfd *); + int bfd_get_gp_size(bfd *abfd); DESCRIPTION - Get the maximum size of objects to be optimized using the GP - register under MIPS ECOFF. This is typically set by the -G + Return the maximum size of objects to be optimized using the GP + register under MIPS ECOFF. This is typically set by the <<-G>> argument to the compiler, assembler or linker. */ @@ -588,22 +628,27 @@ int bfd_get_gp_size (abfd) bfd *abfd; { - if (abfd->xvec->flavour == bfd_target_ecoff_flavour) - return ecoff_data (abfd)->gp_size; + if (abfd->format == bfd_object) + { + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + return ecoff_data (abfd)->gp_size; + else if (abfd->xvec->flavour == bfd_target_elf_flavour) + return elf_gp_size (abfd); + } return 0; } /* FUNCTION - The bfd_set_gp_size function + bfd_set_gp_size SYNOPSIS - void bfd_set_gp_size(bfd *, int); + void bfd_set_gp_size(bfd *abfd, int i); DESCRIPTION Set the maximum size of objects to be optimized using the GP register under ECOFF or MIPS ELF. This is typically set by - the -G argument to the compiler, assembler or linker. + the <<-G>> argument to the compiler, assembler or linker. */ void @@ -611,6 +656,9 @@ bfd_set_gp_size (abfd, i) bfd *abfd; int i; { + /* Don't try to set GP size on an archive or core file! */ + if (abfd->format != bfd_object) + return; if (abfd->xvec->flavour == bfd_target_ecoff_flavour) ecoff_data (abfd)->gp_size = i; else if (abfd->xvec->flavour == bfd_target_elf_flavour) @@ -621,27 +669,27 @@ bfd_set_gp_size (abfd, i) FUNCTION bfd_scan_vma +SYNOPSIS + bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base); + DESCRIPTION - Converts, like strtoul, a numerical expression as a - string into a bfd_vma integer, and returns that integer. - (Though without as many bells and whistles as strtoul.) - The expression is assumed to be unsigned (i.e. positive). - If given a base, it is used as the base for conversion. + Convert, like <>, a numerical expression + @var{string} into a <> integer, and return that integer. + (Though without as many bells and whistles as <>.) + The expression is assumed to be unsigned (i.e., positive). + If given a @var{base}, it is used as the base for conversion. A base of 0 causes the function to interpret the string in hex if a leading "0x" or "0X" is found, otherwise in octal if a leading zero is found, otherwise in decimal. Overflow is not detected. - -SYNOPSIS - bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base); */ bfd_vma -DEFUN(bfd_scan_vma,(string, end, base), - CONST char *string AND - CONST char **end AND - int base) +bfd_scan_vma (string, end, base) + CONST char *string; + CONST char **end; + int base; { bfd_vma value; int digit; @@ -691,12 +739,33 @@ DEFUN(bfd_scan_vma,(string, end, base), return value; } +/* +FUNCTION + bfd_copy_private_bfd_data + +SYNOPSIS + boolean bfd_copy_private_bfd_data(bfd *ibfd, bfd *obfd); + +DESCRIPTION + Copy private BFD information from the BFD @var{ibfd} to the + the BFD @var{obfd}. Return <> on success, <> on error. + Possible error returns are: + + o <> - + Not enough memory exists to create private data for @var{obfd}. + +.#define bfd_copy_private_bfd_data(ibfd, obfd) \ +. BFD_SEND (ibfd, _bfd_copy_private_bfd_data, \ +. (ibfd, obfd)) + +*/ + /* FUNCTION stuff DESCRIPTION - stuff which should be documented + Stuff which should be documented: .#define bfd_sizeof_headers(abfd, reloc) \ . BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) @@ -721,13 +790,36 @@ DESCRIPTION .#define bfd_set_arch_mach(abfd, arch, mach)\ . BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) . -.#define bfd_get_relocated_section_contents(abfd, seclet, data, relocateable) \ -. BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet, data, relocateable)) +.#define bfd_get_relocated_section_contents(abfd, link_info, link_order, data, relocateable, symbols) \ +. BFD_SEND (abfd, _bfd_get_relocated_section_contents, \ +. (abfd, link_info, link_order, data, relocateable, symbols)) . -.#define bfd_relax_section(abfd, section, symbols) \ -. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, symbols)) +.#define bfd_relax_section(abfd, section, link_info, again) \ +. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) +. +.#define bfd_link_hash_table_create(abfd) \ +. BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) +. +.#define bfd_link_add_symbols(abfd, info) \ +. BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) +. +.#define bfd_final_link(abfd, info) \ +. BFD_SEND (abfd, _bfd_final_link, (abfd, info)) +. +.#define bfd_free_cached_info(abfd) \ +. BFD_SEND (abfd, _bfd_free_cached_info, (abfd)) +. +.#define bfd_get_dynamic_symtab_upper_bound(abfd) \ +. BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd)) +. +.#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \ +. BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols)) +. +.#define bfd_get_dynamic_reloc_upper_bound(abfd) \ +. BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd)) +. +.#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \ +. BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms)) . -.#define bfd_seclet_link(abfd, data, relocateable) \ -. BFD_SEND (abfd, _bfd_seclet_link, (abfd, data, relocateable)) */ diff --git a/gnu/usr.bin/gdb/bfd/bfd.h b/gnu/usr.bin/gdb/bfd/bfd.h index fbe0f0f36ba4..e6159a776e9d 100644 --- a/gnu/usr.bin/gdb/bfd/bfd.h +++ b/gnu/usr.bin/gdb/bfd/bfd.h @@ -1,5 +1,5 @@ /* Main header file for the bfd library -- portable access to object files. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Contributed by Cygnus Support. ** NOTE: bfd.h and bfd-in2.h are GENERATED files. Don't change them; @@ -47,8 +47,8 @@ here. */ #include "ansidecl.h" #include "obstack.h" -#define BFD_VERSION "2.2" - +/* These two lines get substitutions done by commands in Makefile.in. */ +#define BFD_VERSION "cygnus-2.3" #define BFD_ARCH_SIZE 32 #if BFD_ARCH_SIZE >= 64 @@ -81,7 +81,13 @@ typedef struct _bfd bfd; force me to change it. */ /* typedef enum boolean {false, true} boolean; */ /* Yup, SVR4 has a "typedef enum boolean" in -fnf */ +/* It gets worse if the host also defines a true/false enum... -sts */ +#ifndef TRUE_FALSE_ALREADY_DEFINED typedef enum bfd_boolean {false, true} boolean; +#define BFD_TRUE_FALSE +#else +typedef enum bfd_boolean {bfd_false, bfd_true} boolean; +#endif /* A pointer to a position in a file. */ /* FIXME: This should be using off_t from . @@ -94,9 +100,9 @@ typedef enum bfd_boolean {false, true} boolean; typedef long int file_ptr; /* Support for different sizes of target format ints and addresses. If the - host implements 64-bit values, it defines HOST_64_BIT to be the appropriate + host implements 64-bit values, it defines BFD_HOST_64_BIT to be the appropriate type. Otherwise, this code will fall back on gcc's "long long" type if gcc - is being used. HOST_64_BIT must be defined in such a way as to be a valid + is being used. BFD_HOST_64_BIT must be defined in such a way as to be a valid type name by itself or with "unsigned" prefixed. It should be a signed type by itself. @@ -105,27 +111,31 @@ typedef long int file_ptr; #ifdef BFD64 -#if defined (__GNUC__) && !defined (HOST_64_BIT) -#define HOST_64_BIT long long -typedef HOST_64_BIT int64_type; -typedef unsigned HOST_64_BIT uint64_type; +#if defined (__GNUC__) && !defined (BFD_HOST_64_BIT) +#define BFD_HOST_64_BIT long long +typedef BFD_HOST_64_BIT int64_type; +typedef unsigned BFD_HOST_64_BIT uint64_type; #endif #if !defined (uint64_type) && defined (__GNUC__) #define uint64_type unsigned long long #define int64_type long long -#define uint64_typeLOW(x) (unsigned long)(((x) & 0xffffffff)) -#define uint64_typeHIGH(x) (unsigned long)(((x) >> 32) & 0xffffffff) +#endif +#ifndef uint64_typeLOW +#define uint64_typeLOW(x) ((unsigned long)(((x) & 0xffffffff))) +#define uint64_typeHIGH(x) ((unsigned long)(((x) >> 32) & 0xffffffff)) #endif -typedef unsigned HOST_64_BIT bfd_vma; -typedef HOST_64_BIT bfd_signed_vma; -typedef unsigned HOST_64_BIT bfd_size_type; -typedef unsigned HOST_64_BIT symvalue; +typedef unsigned BFD_HOST_64_BIT bfd_vma; +typedef BFD_HOST_64_BIT bfd_signed_vma; +typedef unsigned BFD_HOST_64_BIT bfd_size_type; +typedef unsigned BFD_HOST_64_BIT symvalue; +#ifndef fprintf_vma #define fprintf_vma(s,x) \ - fprintf(s,"%08x%08x", uint64_typeHIGH(x), uint64_typeLOW(x)) + fprintf(s,"%08lx%08lx", uint64_typeHIGH(x), uint64_typeLOW(x)) #define sprintf_vma(s,x) \ - sprintf(s,"%08x%08x", uint64_typeHIGH(x), uint64_typeLOW(x)) + sprintf(s,"%08lx%08lx", uint64_typeHIGH(x), uint64_typeLOW(x)) +#endif #else /* not BFD64 */ /* Represent a target address. Also used as a generic unsigned type @@ -160,37 +170,67 @@ typedef enum bfd_format { bfd_type_end} /* marks the end; don't use it! */ bfd_format; -/* Object file flag values */ +/* Values that may appear in the flags field of a BFD. These also + appear in the object_flags field of the bfd_target structure, where + they indicate the set of flags used by that backend (not all flags + are meaningful for all object file formats) (FIXME: at the moment, + the object_flags values have mostly just been copied from backend + to another, and are not necessarily correct). */ + +/* No flags. */ #define NO_FLAGS 0x00 + +/* BFD contains relocation entries. */ #define HAS_RELOC 0x01 + +/* BFD is directly executable. */ #define EXEC_P 0x02 + +/* BFD has line number information (basically used for F_LNNO in a + COFF header). */ #define HAS_LINENO 0x04 + +/* BFD has debugging information. */ #define HAS_DEBUG 0x08 + +/* BFD has symbols. */ #define HAS_SYMS 0x10 + +/* BFD has local symbols (basically used for F_LSYMS in a COFF + header). */ #define HAS_LOCALS 0x20 + +/* BFD is a dynamic object. */ #define DYNAMIC 0x40 + +/* Text section is write protected (if D_PAGED is not set, this is + like an a.out NMAGIC file) (the linker sets this by default, but + clears it for -r or -N). */ #define WP_TEXT 0x80 + +/* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the + linker sets this by default, but clears it for -r or -n or -N). */ #define D_PAGED 0x100 + +/* BFD is relaxable (this means that bfd_relax_section may be able to + do something). */ #define BFD_IS_RELAXABLE 0x200 + +/* This may be set before writing out a BFD to request using a + traditional format. For example, this is used to request that when + writing out an a.out object the symbols not be hashed to eliminate + duplicates. */ +#define BFD_TRADITIONAL_FORMAT 0x400 /* symbols and relocation */ +/* A count of carsyms (canonical archive symbols). */ typedef unsigned long symindex; #define BFD_NO_MORE_SYMBOLS ((symindex) ~0) -typedef enum bfd_symclass { - bfd_symclass_unknown = 0, - bfd_symclass_fcommon, /* fortran common symbols */ - bfd_symclass_global, /* global symbol, what a surprise */ - bfd_symclass_debugger, /* some debugger symbol */ - bfd_symclass_undefined /* none known */ - } symclass; - - -/* general purpose part of a symbol; - target specific parts will be found in libcoff.h, liba.out.h etc */ - +/* General purpose part of a symbol X; + target specific parts are in libcoff.h, libaout.h, etc. */ #define bfd_get_section(x) ((x)->section) #define bfd_get_output_section(x) ((x)->section->output_section) @@ -202,6 +242,7 @@ typedef enum bfd_symclass { #define bfd_asymbol_bfd(x) ((x)->the_bfd) #define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour) +/* A canonical archive symbol. */ /* This is a type pun with struct ranlib on purpose! */ typedef struct carsym { char *name; @@ -209,7 +250,8 @@ typedef struct carsym { } carsym; /* to make these you call a carsymogen */ -/* Used in generating armaps. Perhaps just a forward definition would do? */ +/* Used in generating armaps (archive tables of contents). + Perhaps just a forward definition would do? */ struct orl { /* output ranlib */ char **name; /* symbol name */ file_ptr pos; /* bfd* or file position */ @@ -222,7 +264,7 @@ struct orl { /* output ranlib */ typedef struct lineno_cache_entry { unsigned int line_number; /* Linenumber from start of function*/ union { - struct symbol_cache_entry *sym; /* Function name */ + struct symbol_cache_entry *sym; /* Function name */ unsigned long offset; /* Offset into section */ } u; } alent; @@ -253,46 +295,6 @@ typedef struct sec *sec_ptr; typedef struct stat stat_type; -/** Error handling */ - -typedef enum bfd_error { - no_error = 0, system_call_error, invalid_target, - wrong_format, invalid_operation, no_memory, - no_symbols, no_relocation_info, - no_more_archived_files, malformed_archive, - symbol_not_found, file_not_recognized, - file_ambiguously_recognized, no_contents, - bfd_error_nonrepresentable_section, - no_debug_section, bad_value, - - /* An input file is shorter than expected. */ - file_truncated, - - invalid_error_code} bfd_ec; - -extern bfd_ec bfd_error; -struct reloc_cache_entry; -struct bfd_seclet; - - -typedef struct bfd_error_vector { - void (* nonrepresentable_section ) PARAMS ((CONST bfd *CONST abfd, - CONST char *CONST name)); - void (* undefined_symbol) PARAMS ((CONST struct reloc_cache_entry *rel, - CONST struct bfd_seclet *sec)); - void (* reloc_value_truncated) PARAMS ((CONST struct - reloc_cache_entry *rel, - struct bfd_seclet *sec)); - - void (* reloc_dangerous) PARAMS ((CONST struct reloc_cache_entry *rel, - CONST struct bfd_seclet *sec)); - -} bfd_error_vector_type; - -CONST char *bfd_errmsg PARAMS ((bfd_ec error_tag)); -void bfd_perror PARAMS ((CONST char *message)); - - typedef enum bfd_print_symbol { bfd_print_symbol_name, @@ -300,24 +302,99 @@ typedef enum bfd_print_symbol bfd_print_symbol_all } bfd_print_symbol_type; - /* Information about a symbol that nm needs. */ typedef struct _symbol_info { symvalue value; - char type; /* */ + char type; CONST char *name; /* Symbol name. */ char stab_other; /* Unused. */ short stab_desc; /* Info for N_TYPE. */ CONST char *stab_name; } symbol_info; -/* The code that implements targets can initialize a jump table with this - macro. It must name all its routines the same way (a prefix plus - the standard routine suffix), or it must #define the routines that - are not so named, before calling JUMP_TABLE in the initializer. */ +/* Hash table routines. There is no way to free up a hash table. */ +/* An element in the hash table. Most uses will actually use a larger + structure, and an instance of this will be the first field. */ + +struct bfd_hash_entry +{ + /* Next entry for this hash code. */ + struct bfd_hash_entry *next; + /* String being hashed. */ + const char *string; + /* Hash code. This is the full hash code, not the index into the + table. */ + unsigned long hash; +}; + +/* A hash table. */ + +struct bfd_hash_table +{ + /* The hash array. */ + struct bfd_hash_entry **table; + /* The number of slots in the hash table. */ + unsigned int size; + /* A function used to create new elements in the hash table. The + first entry is itself a pointer to an element. When this + function is first invoked, this pointer will be NULL. However, + having the pointer permits a hierarchy of method functions to be + built each of which calls the function in the superclass. Thus + each function should be written to allocate a new block of memory + only if the argument is NULL. */ + struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *)); + /* An obstack for this hash table. */ + struct obstack memory; +}; + +/* Initialize a hash table. */ +extern boolean bfd_hash_table_init + PARAMS ((struct bfd_hash_table *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); + +/* Initialize a hash table specifying a size. */ +extern boolean bfd_hash_table_init_n + PARAMS ((struct bfd_hash_table *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *), + unsigned int size)); + +/* Free up a hash table. */ +extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *)); + +/* Look up a string in a hash table. If CREATE is true, a new entry + will be created for this string if one does not already exist. The + COPY argument must be true if this routine should copy the string + into newly allocated memory when adding an entry. */ +extern struct bfd_hash_entry *bfd_hash_lookup + PARAMS ((struct bfd_hash_table *, const char *, boolean create, + boolean copy)); + +/* Base method for creating a hash table entry. */ +extern struct bfd_hash_entry *bfd_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, + const char *)); + +/* Grab some space for a hash table entry. */ +extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *, + unsigned int)); + +/* Traverse a hash table in a random order, calling a function on each + element. If the function returns false, the traversal stops. The + INFO argument is passed to the function. */ +extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *, + boolean (*) (struct bfd_hash_entry *, + PTR), + PTR info)); + /* Semi-portable string concatenation in cpp. The CAT4 hack is to avoid a problem with some strict ANSI C preprocessors. The problem is, "32_" is not a valid preprocessing token, and we don't @@ -330,7 +407,7 @@ typedef struct _symbol_info #define CAT3(a,b,c) a##b##c #define CAT4(a,b,c,d) a##b##c##d #else -#ifdef __STDC__ +#if defined(__STDC__) || defined(ALMOST_STDC) #define CAT(a,b) a##b #define CAT3(a,b,c) a##b##c #define XCAT2(a,b) CAT(a,b) @@ -343,50 +420,17 @@ typedef struct _symbol_info #endif #endif -#define JUMP_TABLE(NAME)\ -CAT(NAME,_core_file_failing_command),\ -CAT(NAME,_core_file_failing_signal),\ -CAT(NAME,_core_file_matches_executable_p),\ -CAT(NAME,_slurp_armap),\ -CAT(NAME,_slurp_extended_name_table),\ -CAT(NAME,_truncate_arname),\ -CAT(NAME,_write_armap),\ -CAT(NAME,_close_and_cleanup),\ -CAT(NAME,_set_section_contents),\ -CAT(NAME,_get_section_contents),\ -CAT(NAME,_new_section_hook),\ -CAT(NAME,_get_symtab_upper_bound),\ -CAT(NAME,_get_symtab),\ -CAT(NAME,_get_reloc_upper_bound),\ -CAT(NAME,_canonicalize_reloc),\ -CAT(NAME,_make_empty_symbol),\ -CAT(NAME,_print_symbol),\ -CAT(NAME,_get_symbol_info),\ -CAT(NAME,_get_lineno),\ -CAT(NAME,_set_arch_mach),\ -CAT(NAME,_openr_next_archived_file),\ -CAT(NAME,_find_nearest_line),\ -CAT(NAME,_generic_stat_arch_elt),\ -CAT(NAME,_sizeof_headers),\ -CAT(NAME,_bfd_debug_info_start),\ -CAT(NAME,_bfd_debug_info_end),\ -CAT(NAME,_bfd_debug_info_accumulate),\ -CAT(NAME,_bfd_get_relocated_section_contents),\ -CAT(NAME,_bfd_relax_section),\ -CAT(NAME,_bfd_seclet_link),\ -CAT(NAME,_bfd_reloc_type_lookup),\ -CAT(NAME,_bfd_make_debug_symbol) - #define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table - /* User program access to BFD facilities */ /* Cast from const char * to char * so that caller can assign to a char * without a warning. */ #define bfd_get_filename(abfd) ((char *) (abfd)->filename) +#define bfd_get_cacheable(abfd) ((abfd)->cacheable) #define bfd_get_format(abfd) ((abfd)->format) #define bfd_get_target(abfd) ((abfd)->xvec->name) +#define bfd_get_flavour(abfd) ((abfd)->xvec->flavour) #define bfd_get_file_flags(abfd) ((abfd)->flags) #define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags) #define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags) @@ -403,33 +447,115 @@ CAT(NAME,_bfd_make_debug_symbol) #define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char) +#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (bool)), true) + /* Byte swapping routines. */ -bfd_vma bfd_getb64 PARAMS ((unsigned char *)); -bfd_vma bfd_getl64 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getb_signed_64 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getl_signed_64 PARAMS ((unsigned char *)); -bfd_vma bfd_getb32 PARAMS ((unsigned char *)); -bfd_vma bfd_getl32 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getb_signed_32 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getl_signed_32 PARAMS ((unsigned char *)); -bfd_vma bfd_getb16 PARAMS ((unsigned char *)); -bfd_vma bfd_getl16 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getb_signed_16 PARAMS ((unsigned char *)); -bfd_signed_vma bfd_getl_signed_16 PARAMS ((unsigned char *)); +bfd_vma bfd_getb64 PARAMS ((const unsigned char *)); +bfd_vma bfd_getl64 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getb_signed_64 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getl_signed_64 PARAMS ((const unsigned char *)); +bfd_vma bfd_getb32 PARAMS ((const unsigned char *)); +bfd_vma bfd_getl32 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getb_signed_32 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getl_signed_32 PARAMS ((const unsigned char *)); +bfd_vma bfd_getb16 PARAMS ((const unsigned char *)); +bfd_vma bfd_getl16 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getb_signed_16 PARAMS ((const unsigned char *)); +bfd_signed_vma bfd_getl_signed_16 PARAMS ((const unsigned char *)); void bfd_putb64 PARAMS ((bfd_vma, unsigned char *)); void bfd_putl64 PARAMS ((bfd_vma, unsigned char *)); void bfd_putb32 PARAMS ((bfd_vma, unsigned char *)); void bfd_putl32 PARAMS ((bfd_vma, unsigned char *)); void bfd_putb16 PARAMS ((bfd_vma, unsigned char *)); void bfd_putl16 PARAMS ((bfd_vma, unsigned char *)); + +/* Externally visible ECOFF routines. */ + +#if defined(__STDC__) || defined(ALMOST_STDC) +struct ecoff_debug_info; +struct ecoff_debug_swap; +struct ecoff_extr; +struct symbol_cache_entry; +struct bfd_link_info; +#endif +extern bfd_vma bfd_ecoff_get_gp_value PARAMS ((bfd * abfd)); +extern boolean bfd_ecoff_set_gp_value PARAMS ((bfd *abfd, bfd_vma gp_value)); +extern boolean bfd_ecoff_set_regmasks + PARAMS ((bfd *abfd, unsigned long gprmask, unsigned long fprmask, + unsigned long *cprmask)); +extern PTR bfd_ecoff_debug_init + PARAMS ((bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, + struct bfd_link_info *)); +extern void bfd_ecoff_debug_free + PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, + struct bfd_link_info *)); +extern boolean bfd_ecoff_debug_accumulate + PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, + bfd *input_bfd, struct ecoff_debug_info *input_debug, + const struct ecoff_debug_swap *input_swap, + struct bfd_link_info *)); +extern boolean bfd_ecoff_debug_accumulate_other + PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, bfd *input_bfd, + struct bfd_link_info *)); +extern boolean bfd_ecoff_debug_externals + PARAMS ((bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, + boolean relocateable, + boolean (*get_extr) (struct symbol_cache_entry *, + struct ecoff_extr *), + void (*set_index) (struct symbol_cache_entry *, + bfd_size_type))); +extern boolean bfd_ecoff_debug_one_external + PARAMS ((bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, + const char *name, struct ecoff_extr *esym)); +extern bfd_size_type bfd_ecoff_debug_size + PARAMS ((bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap)); +extern boolean bfd_ecoff_write_debug + PARAMS ((bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, file_ptr where)); +extern boolean bfd_ecoff_write_accumulated_debug + PARAMS ((PTR handle, bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, + struct bfd_link_info *info, file_ptr where)); + +/* Externally visible ELF routines. */ + +extern boolean bfd_elf32_record_link_assignment + PARAMS ((bfd *, struct bfd_link_info *, const char *)); +extern boolean bfd_elf64_record_link_assignment + PARAMS ((bfd *, struct bfd_link_info *, const char *)); +extern boolean bfd_elf32_size_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *, struct sec **)); +extern boolean bfd_elf64_size_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *, struct sec **)); +extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *)); + +/* SunOS shared library support routines for the linker. */ + +extern boolean bfd_sunos_record_link_assignment + PARAMS ((bfd *, struct bfd_link_info *, const char *)); +extern boolean bfd_sunos_size_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *, struct sec **, struct sec **, + struct sec **)); + +/* Linux shared library support routines for the linker. */ + +extern boolean bfd_linux_size_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); /* And more from the source. */ void bfd_init PARAMS ((void)); bfd * -bfd_openr PARAMS ((CONST char *filename, CONST char*target)); +bfd_openr PARAMS ((CONST char *filename, CONST char *target)); bfd * bfd_fdopenr PARAMS ((CONST char *filename, CONST char *target, int fd)); @@ -438,7 +564,7 @@ bfd * bfd_openw PARAMS ((CONST char *filename, CONST char *target)); boolean -bfd_close PARAMS ((bfd *)); +bfd_close PARAMS ((bfd *abfd)); boolean bfd_close_all_done PARAMS ((bfd *)); @@ -453,7 +579,7 @@ bfd_create PARAMS ((CONST char *filename, bfd *templ)); /* Byte swapping macros for user section data. */ #define bfd_put_8(abfd, val, ptr) \ - (*((unsigned char *)(ptr)) = (unsigned char)val) + (*((unsigned char *)(ptr)) = (unsigned char)(val)) #define bfd_put_signed_8 \ bfd_put_8 #define bfd_get_8(abfd, ptr) \ @@ -527,40 +653,40 @@ bfd_create PARAMS ((CONST char *filename, bfd *templ)); #define bfd_h_get_signed_64(abfd, ptr) \ BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr)) -typedef struct sec +typedef struct sec { - /* The name of the section, the name isn't a copy, the pointer is + /* The name of the section; the name isn't a copy, the pointer is the same as that passed to bfd_make_section. */ CONST char *name; - /* Which section is it 0.nth */ + /* Which section is it; 0..nth. */ - int index; + int index; /* The next section in the list belonging to the BFD, or NULL. */ struct sec *next; - /* The field flags contains attributes of the section. Some of + /* The field flags contains attributes of the section. Some flags are read in from the object file, and some are - synthesized from other information. */ + synthesized from other information. */ flagword flags; #define SEC_NO_FLAGS 0x000 - /* Tells the OS to allocate space for this section when loaded. - This would clear for a section containing debug information + /* Tells the OS to allocate space for this section when loading. + This is clear for a section containing debug information only. */ #define SEC_ALLOC 0x001 - + /* Tells the OS to load the section from the file when loading. - This would be clear for a .bss section */ + This is clear for a .bss section. */ #define SEC_LOAD 0x002 - /* The section contains data still to be relocated, so there will - be some relocation information too. */ + /* The section contains data still to be relocated, so there is + some relocation information too. */ #define SEC_RELOC 0x004 #if 0 /* Obsolete ? */ @@ -584,10 +710,10 @@ typedef struct sec type is used by the linker to create lists of constructors and destructors used by <>. When a back end sees a symbol which should be used in a constructor list, it creates a new - section for the type of name (eg <<__CTOR_LIST__>>), attaches - the symbol to it and builds a relocation. To build the lists + section for the type of name (e.g., <<__CTOR_LIST__>>), attaches + the symbol to it, and builds a relocation. To build the lists of constructors, all the linker has to do is catenate all the - sections called <<__CTOR_LIST__>> and relocte the data + sections called <<__CTOR_LIST__>> and relocate the data contained within - exactly the operations it would peform on standard data. */ #define SEC_CONSTRUCTOR 0x100 @@ -599,25 +725,30 @@ typedef struct sec #define SEC_CONSTRUCTOR_BSS 0x3100 /* The section has contents - a data section could be - <> | <>, a debug section could be + <> | <>; a debug section could be <> */ #define SEC_HAS_CONTENTS 0x200 - /* An instruction to the linker not to output sections - containing this flag even if they have information which - would normally be written. */ + /* An instruction to the linker to not output the section + even if it has information which would normally be written. */ #define SEC_NEVER_LOAD 0x400 - /* The section is a shared library section. The linker must leave - these completely alone, as the vma and size are used when - the executable is loaded. */ -#define SEC_SHARED_LIBRARY 0x800 + /* The section is a COFF shared library section. This flag is + only for the linker. If this type of section appears in + the input file, the linker must copy it to the output file + without changing the vma or size. FIXME: Although this + was originally intended to be general, it really is COFF + specific (and the flag was renamed to indicate this). It + might be cleaner to have some more general mechanism to + allow the back end to control what the linker does with + sections. */ +#define SEC_COFF_SHARED_LIBRARY 0x800 /* The section is a common section (symbols may be defined multiple times, the value of a symbol is the amount of space it requires, and the largest symbol value is the one used). Most targets have exactly one of these (which we - translate to bfd_com_section), but ECOFF has two. */ + translate to bfd_com_section_ptr), but ECOFF has two. */ #define SEC_IS_COMMON 0x8000 /* The section contains only debugging information. For @@ -626,6 +757,12 @@ typedef struct sec discarded. */ #define SEC_DEBUGGING 0x10000 + /* The contents of this section are held in memory pointed to + by the contents field. This is checked by + bfd_get_section_contents, and the data is retrieved from + memory if appropriate. */ +#define SEC_IN_MEMORY 0x20000 + /* End of section flags. */ /* The virtual memory address of the section - where it will be @@ -639,26 +776,26 @@ typedef struct sec boolean user_set_vma; /* The load address of the section - where it would be in a - rom image, really only used for writing section header + rom image; really only used for writing section header information. */ bfd_vma lma; /* The size of the section in bytes, as it will be output. - contains a value even if the section has no contents (eg, the + contains a value even if the section has no contents (e.g., the size of <<.bss>>). This will be filled in after relocation */ - bfd_size_type _cooked_size; + bfd_size_type _cooked_size; - /* The size on disk of the section in bytes originally. Normally this + /* The original size on disk of the section, in bytes. Normally this value is the same as the size, but if some relaxing has been done, then this value will be bigger. */ - bfd_size_type _raw_size; + bfd_size_type _raw_size; /* If this section is going to be output, then this value is the offset into the output section of the first byte in the input - section. Eg, if this was going to start at the 100th byte in + section. E.g., if this was going to start at the 100th byte in the output section, this value would be 100. */ bfd_vma output_offset; @@ -667,8 +804,8 @@ typedef struct sec struct sec *output_section; - /* The alignment requirement of the section, as an exponent - eg - 3 aligns to 2^3 (or 8) */ + /* The alignment requirement of the section, as an exponent of 2 - + e.g., 3 aligns to 2^3 (or 8). */ unsigned int alignment_power; @@ -691,8 +828,8 @@ typedef struct sec /* File position of section data */ - file_ptr filepos; - + file_ptr filepos; + /* File position of relocation info */ file_ptr rel_filepos; @@ -705,12 +842,14 @@ typedef struct sec PTR userdata; - struct lang_output_section *otheruserdata; + /* If the SEC_IN_MEMORY flag is set, this points to the actual + contents. */ + unsigned char *contents; /* Attached line number information */ alent *lineno; - + /* Number of line number records */ unsigned int lineno_count; @@ -720,7 +859,7 @@ typedef struct sec file_ptr moving_line_filepos; - /* what the section number is in the target world */ + /* What the section number is in the target world */ int target_index; @@ -737,35 +876,43 @@ typedef struct sec boolean reloc_done; /* A symbol which points at this section only */ - struct symbol_cache_entry *symbol; + struct symbol_cache_entry *symbol; struct symbol_cache_entry **symbol_ptr_ptr; - struct bfd_seclet *seclets_head; - struct bfd_seclet *seclets_tail; + struct bfd_link_order *link_order_head; + struct bfd_link_order *link_order_tail; } asection ; - /* These sections are global, and are managed by BFD. The application and target back end are not permitted to change the values in - these sections. */ + these sections. New code should use the section_ptr macros rather + than referring directly to the const sections. The const sections + may eventually vanish. */ #define BFD_ABS_SECTION_NAME "*ABS*" #define BFD_UND_SECTION_NAME "*UND*" #define BFD_COM_SECTION_NAME "*COM*" #define BFD_IND_SECTION_NAME "*IND*" /* the absolute section */ -extern asection bfd_abs_section; +extern const asection bfd_abs_section; +#define bfd_abs_section_ptr ((asection *) &bfd_abs_section) +#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr) /* Pointer to the undefined section */ -extern asection bfd_und_section; +extern const asection bfd_und_section; +#define bfd_und_section_ptr ((asection *) &bfd_und_section) +#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr) /* Pointer to the common section */ -extern asection bfd_com_section; +extern const asection bfd_com_section; +#define bfd_com_section_ptr ((asection *) &bfd_com_section) /* Pointer to the indirect section */ -extern asection bfd_ind_section; +extern const asection bfd_ind_section; +#define bfd_ind_section_ptr ((asection *) &bfd_ind_section) +#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr) -extern struct symbol_cache_entry *bfd_abs_symbol; -extern struct symbol_cache_entry *bfd_com_symbol; -extern struct symbol_cache_entry *bfd_und_symbol; -extern struct symbol_cache_entry *bfd_ind_symbol; +extern const struct symbol_cache_entry * const bfd_abs_symbol; +extern const struct symbol_cache_entry * const bfd_com_symbol; +extern const struct symbol_cache_entry * const bfd_und_symbol; +extern const struct symbol_cache_entry * const bfd_ind_symbol; #define bfd_get_section_size_before_reloc(section) \ (section->reloc_done ? (abort(),1): (section)->_raw_size) #define bfd_get_section_size_after_reloc(section) \ @@ -774,16 +921,16 @@ asection * bfd_get_section_by_name PARAMS ((bfd *abfd, CONST char *name)); asection * -bfd_make_section_old_way PARAMS ((bfd *, CONST char *name)); +bfd_make_section_old_way PARAMS ((bfd *abfd, CONST char *name)); asection * -bfd_make_section_anyway PARAMS ((bfd *, CONST char *name)); +bfd_make_section_anyway PARAMS ((bfd *abfd, CONST char *name)); asection * bfd_make_section PARAMS ((bfd *, CONST char *name)); boolean -bfd_set_section_flags PARAMS ((bfd *, asection *, flagword)); +bfd_set_section_flags PARAMS ((bfd *abfd, asection *sec, flagword flags)); void bfd_map_over_sections PARAMS ((bfd *abfd, @@ -793,21 +940,27 @@ bfd_map_over_sections PARAMS ((bfd *abfd, PTR obj)); boolean -bfd_set_section_size PARAMS ((bfd *, asection *, bfd_size_type val)); +bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val)); boolean bfd_set_section_contents - PARAMS ((bfd *abfd, + PARAMS ((bfd *abfd, asection *section, PTR data, file_ptr offset, bfd_size_type count)); boolean -bfd_get_section_contents +bfd_get_section_contents PARAMS ((bfd *abfd, asection *section, PTR location, file_ptr offset, bfd_size_type count)); +boolean +bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec, bfd *obfd, asection *osec)); + +#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \ + BFD_SEND (ibfd, _bfd_copy_private_section_data, \ + (ibfd, isection, obfd, osection)) enum bfd_architecture { bfd_arch_unknown, /* File arch not known */ @@ -845,6 +998,7 @@ enum bfd_architecture bfd_arch_h8300, /* Hitachi H8/300 */ #define bfd_mach_h8300 1 #define bfd_mach_h8300h 2 + bfd_arch_powerpc, /* PowerPC */ bfd_arch_rs6000, /* IBM RS/6000 */ bfd_arch_hppa, /* HP PA RISC */ bfd_arch_z8k, /* Zilog Z8000 */ @@ -853,6 +1007,7 @@ enum bfd_architecture bfd_arch_h8500, /* Hitachi H8/500 */ bfd_arch_sh, /* Hitachi SH */ bfd_arch_alpha, /* Dec Alpha */ + bfd_arch_ns32k, /* National Semiconductors ns32000 */ bfd_arch_last }; @@ -887,7 +1042,7 @@ CONST char * bfd_printable_name PARAMS ((bfd *abfd)); bfd_arch_info_type * -bfd_scan_arch PARAMS ((CONST char *)); +bfd_scan_arch PARAMS ((CONST char *string)); CONST bfd_arch_info_type * bfd_arch_get_compatible PARAMS (( @@ -895,7 +1050,7 @@ bfd_arch_get_compatible PARAMS (( CONST bfd *bbfd)); void -bfd_set_arch_info PARAMS ((bfd *, bfd_arch_info_type *)); +bfd_set_arch_info PARAMS ((bfd *abfd, bfd_arch_info_type *arg)); enum bfd_architecture bfd_get_arch PARAMS ((bfd *abfd)); @@ -910,7 +1065,7 @@ unsigned int bfd_arch_bits_per_address PARAMS ((bfd *abfd)); bfd_arch_info_type * -bfd_get_arch_info PARAMS ((bfd *)); +bfd_get_arch_info PARAMS ((bfd *abfd)); bfd_arch_info_type * bfd_lookup_arch @@ -918,11 +1073,11 @@ bfd_lookup_arch arch, long machine)); -CONST char * +CONST char * bfd_printable_arch_mach PARAMS ((enum bfd_architecture arch, unsigned long machine)); -typedef enum bfd_reloc_status +typedef enum bfd_reloc_status { /* No errors detected */ bfd_reloc_ok, @@ -936,10 +1091,10 @@ typedef enum bfd_reloc_status /* Used by special functions */ bfd_reloc_continue, - /* Unused */ + /* Unsupported relocation size requested. */ bfd_reloc_notsupported, - /* Unsupported relocation size requested. */ + /* Unused */ bfd_reloc_other, /* The symbol to relocate against was undefined. */ @@ -947,13 +1102,14 @@ typedef enum bfd_reloc_status /* The relocation was performed, but may not be ok - presently generated only when linking i960 coff files with i960 b.out - symbols. */ + symbols. If this type is returned, the error_message argument + to bfd_perform_relocation will be set. */ bfd_reloc_dangerous } bfd_reloc_status_type; -typedef struct reloc_cache_entry +typedef struct reloc_cache_entry { /* A pointer into the canonical table of pointers */ struct symbol_cache_entry **sym_ptr_ptr; @@ -962,10 +1118,10 @@ typedef struct reloc_cache_entry bfd_size_type address; /* addend for relocation value */ - bfd_vma addend; + bfd_vma addend; /* Pointer to how to perform the required relocation */ - CONST struct reloc_howto_struct *howto; + const struct reloc_howto_struct *howto; } arelent; enum complain_overflow @@ -986,13 +1142,16 @@ enum complain_overflow complain_overflow_unsigned }; -typedef CONST struct reloc_howto_struct -{ +typedef unsigned char bfd_byte; +typedef struct reloc_howto_struct reloc_howto_type; + +struct reloc_howto_struct +{ /* The type field has mainly a documetary use - the back end can - to what it wants with it, though the normally the back end's - external idea of what a reloc number would be would be stored - in this field. For example, the a PC relative word relocation - in a coff environment would have the type 023 - because that's + do what it wants with it, though normally the back end's + external idea of what a reloc number is stored + in this field. For example, a PC relative word relocation + in a coff environment has the type 023 - because that's what the outside world calls a R_PCRWORD reloc. */ unsigned int type; @@ -1001,16 +1160,8 @@ typedef CONST struct reloc_howto_struct unsigned int rightshift; /* The size of the item to be relocated. This is *not* a - power-of-two measure. - 0 : one byte - 1 : two bytes - 2 : four bytes - 3 : nothing done (unless special_function is nonzero) - 4 : eight bytes - -2 : two bytes, result should be subtracted from the - data instead of added - There is currently no trivial way to extract a "number of - bytes" from a howto pointer. */ + power-of-two measure. To get the number of bytes operated + on by a type of relocation, use bfd_get_reloc_size. */ int size; /* The number of bits in the item to be relocated. This is used @@ -1035,13 +1186,14 @@ typedef CONST struct reloc_howto_struct called rather than the normal function. This allows really strange relocation methods to be accomodated (e.g., i960 callj instructions). */ - bfd_reloc_status_type (*special_function) + bfd_reloc_status_type (*special_function) PARAMS ((bfd *abfd, arelent *reloc_entry, struct symbol_cache_entry *symbol, PTR data, - asection *input_section, - bfd *output_bfd)); + asection *input_section, + bfd *output_bfd, + char **error_message)); /* The textual name of the relocation type. */ char *name; @@ -1050,7 +1202,7 @@ typedef CONST struct reloc_howto_struct relocations rather than the data - this flag signals this.*/ boolean partial_inplace; - /* The src_mask is used to select what parts of the read in data + /* The src_mask selects which parts of the read in data are to be used in the relocation sum. E.g., if this was an 8 bit bit of data which we read and relocated, this would be 0x000000ff. When we have relocs which have an addend, such as @@ -1059,21 +1211,21 @@ typedef CONST struct reloc_howto_struct the mask would be 0x00000000. */ bfd_vma src_mask; - /* The dst_mask is what parts of the instruction are replaced + /* The dst_mask selects which parts of the instruction are replaced into the instruction. In most cases src_mask == dst_mask, except in the above special case, where dst_mask would be 0x000000ff, and src_mask would be 0x00000000. */ - bfd_vma dst_mask; + bfd_vma dst_mask; /* When some formats create PC relative instructions, they leave the value of the pc of the place being relocated in the offset slot of the instruction, so that a PC relative relocation can be made just by adding in an ordinary offset (e.g., sun3 a.out). Some formats leave the displacement part of an instruction - empty (e.g., m88k bcs), this flag signals the fact.*/ + empty (e.g., m88k bcs); this flag signals the fact.*/ boolean pcrel_offset; -} reloc_howto_type; +}; #define HOWTO(C, R,S,B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ {(unsigned)C,R,S,B, P, BI, O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC} #define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN) @@ -1088,8 +1240,9 @@ typedef CONST struct reloc_howto_struct relocation = symbol->value; \ } \ } \ -} -typedef unsigned char bfd_byte; +} +int +bfd_get_reloc_size PARAMS ((const reloc_howto_type *)); typedef struct relent_chain { arelent relent; @@ -1098,18 +1251,21 @@ typedef struct relent_chain { bfd_reloc_status_type bfd_perform_relocation - PARAMS ((bfd * abfd, + PARAMS ((bfd *abfd, arelent *reloc_entry, PTR data, asection *input_section, - bfd *output_bfd)); + bfd *output_bfd, + char **error_message)); -typedef enum bfd_reloc_code_real +typedef enum bfd_reloc_code_real { /* Basic absolute relocations */ BFD_RELOC_64, BFD_RELOC_32, - BFD_RELOC_16, + BFD_RELOC_26, + BFD_RELOC_16, + BFD_RELOC_14, BFD_RELOC_8, /* PC-relative relocations */ @@ -1134,6 +1290,10 @@ typedef enum bfd_reloc_code_real /* 32-bit pc-relative, shifted right 2 bits (i.e., 30-bit word displacement, e.g. for SPARC) */ BFD_RELOC_32_PCREL_S2, + /* signed 16-bit pc-relative, shifted right 2 bits (e.g. for MIPS) */ + BFD_RELOC_16_PCREL_S2, + /* this is used on the Alpha */ + BFD_RELOC_23_PCREL_S2, /* High 22 bits of 32-bit value, placed into lower 22 bits of target word; simple reloc. */ @@ -1141,6 +1301,13 @@ typedef enum bfd_reloc_code_real /* Low 10 bits. */ BFD_RELOC_LO10, + /* For systems that allocate a Global Pointer register, these are + displacements off that register. These relocation types are + handled specially, because the value the register will have is + decided relatively late. */ + BFD_RELOC_GPREL16, + BFD_RELOC_GPREL32, + /* Reloc types used for i960/b.out. */ BFD_RELOC_I960_CALLJ, @@ -1165,14 +1332,67 @@ typedef enum bfd_reloc_code_real BFD_RELOC_SPARC_BASE13, BFD_RELOC_SPARC_BASE22, + /* some relocations we're using for sparc v9 + -- subject to change */ + BFD_RELOC_SPARC_10, + BFD_RELOC_SPARC_11, +#define BFD_RELOC_SPARC_64 BFD_RELOC_64 + BFD_RELOC_SPARC_OLO10, + BFD_RELOC_SPARC_HH22, + BFD_RELOC_SPARC_HM10, + BFD_RELOC_SPARC_LM22, + BFD_RELOC_SPARC_PC_HH22, + BFD_RELOC_SPARC_PC_HM10, + BFD_RELOC_SPARC_PC_LM22, + BFD_RELOC_SPARC_WDISP16, + BFD_RELOC_SPARC_WDISP19, + BFD_RELOC_SPARC_GLOB_JMP, + BFD_RELOC_SPARC_LO7, + + /* Alpha ECOFF relocations. Some of these treat the symbol or "addend" + in some special way. */ + /* For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when + writing; when reading, it will be the absolute section symbol. The + addend is the displacement in bytes of the "lda" instruction from + the "ldah" instruction (which is at the address of this reloc). */ + BFD_RELOC_ALPHA_GPDISP_HI16, + /* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as + with GPDISP_HI16 relocs. The addend is ignored when writing the + relocations out, and is filled in with the file's GP value on + reading, for convenience. */ + BFD_RELOC_ALPHA_GPDISP_LO16, + + /* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference; + the assembler turns it into a LDQ instruction to load the address of + the symbol, and then fills in a register in the real instruction. + + The LITERAL reloc, at the LDQ instruction, refers to the .lita + section symbol. The addend is ignored when writing, but is filled + in with the file's GP value on reading, for convenience, as with the + GPDISP_LO16 reloc. + + The LITUSE reloc, on the instruction using the loaded address, gives + information to the linker that it might be able to use to optimize + away some literal section references. The symbol is ignored (read + as the absolute section symbol), and the "addend" indicates the type + of instruction using the register: + 1 - "memory" fmt insn + 2 - byte-manipulation (byte offset reg) + 3 - jsr (target of branch) + + The GNU linker currently doesn't do any of this optimizing. */ + BFD_RELOC_ALPHA_LITERAL, + BFD_RELOC_ALPHA_LITUSE, + + /* The HINT relocation indicates a value that should be filled into the + "hint" field of a jmp/jsr/ret instruction, for possible branch- + prediction logic which may be provided on some processors. */ + BFD_RELOC_ALPHA_HINT, /* Bits 27..2 of the relocation address shifted right 2 bits; simple reloc otherwise. */ BFD_RELOC_MIPS_JMP, - /* signed 16-bit pc-relative, shifted right 2 bits (e.g. for MIPS) */ - BFD_RELOC_16_PCREL_S2, - /* High 16 bits of 32-bit value; simple reloc. */ BFD_RELOC_HI16, /* High 16 bits of 32-bit value but the low 16 bits will be sign @@ -1182,106 +1402,21 @@ typedef enum bfd_reloc_code_real BFD_RELOC_HI16_S, /* Low 16 bits. */ BFD_RELOC_LO16, + /* Like BFD_RELOC_HI16_S, but PC relative. */ + BFD_RELOC_PCREL_HI16_S, + /* Like BFD_RELOC_LO16, but PC relative. */ + BFD_RELOC_PCREL_LO16, - /* 16 bit relocation relative to the global pointer. */ - BFD_RELOC_MIPS_GPREL, + /* relocation relative to the global pointer. */ +#define BFD_RELOC_MIPS_GPREL BFD_RELOC_GPREL16 - /* These are, so far, specific to HPPA processors. I'm not sure that some - don't duplicate other reloc types, such as BFD_RELOC_32 and _32_PCREL. - Also, many more were in the list I got that don't fit in well in the - model BFD uses, so I've omitted them for now. If we do make this reloc - type get used for code that really does implement the funky reloc types, - they'll have to be added to this list. */ - BFD_RELOC_HPPA_32, - BFD_RELOC_HPPA_11, - BFD_RELOC_HPPA_14, - BFD_RELOC_HPPA_17, + /* Relocation against a MIPS literal section. */ + BFD_RELOC_MIPS_LITERAL, - BFD_RELOC_HPPA_L21, - BFD_RELOC_HPPA_R11, - BFD_RELOC_HPPA_R14, - BFD_RELOC_HPPA_R17, - BFD_RELOC_HPPA_LS21, - BFD_RELOC_HPPA_RS11, - BFD_RELOC_HPPA_RS14, - BFD_RELOC_HPPA_RS17, - BFD_RELOC_HPPA_LD21, - BFD_RELOC_HPPA_RD11, - BFD_RELOC_HPPA_RD14, - BFD_RELOC_HPPA_RD17, - BFD_RELOC_HPPA_LR21, - BFD_RELOC_HPPA_RR14, - BFD_RELOC_HPPA_RR17, - - BFD_RELOC_HPPA_GOTOFF_11, - BFD_RELOC_HPPA_GOTOFF_14, - BFD_RELOC_HPPA_GOTOFF_L21, - BFD_RELOC_HPPA_GOTOFF_R11, - BFD_RELOC_HPPA_GOTOFF_R14, - BFD_RELOC_HPPA_GOTOFF_LS21, - BFD_RELOC_HPPA_GOTOFF_RS11, - BFD_RELOC_HPPA_GOTOFF_RS14, - BFD_RELOC_HPPA_GOTOFF_LD21, - BFD_RELOC_HPPA_GOTOFF_RD11, - BFD_RELOC_HPPA_GOTOFF_RD14, - BFD_RELOC_HPPA_GOTOFF_LR21, - BFD_RELOC_HPPA_GOTOFF_RR14, - - BFD_RELOC_HPPA_DLT_32, - BFD_RELOC_HPPA_DLT_11, - BFD_RELOC_HPPA_DLT_14, - BFD_RELOC_HPPA_DLT_L21, - BFD_RELOC_HPPA_DLT_R11, - BFD_RELOC_HPPA_DLT_R14, - - BFD_RELOC_HPPA_ABS_CALL_11, - BFD_RELOC_HPPA_ABS_CALL_14, - BFD_RELOC_HPPA_ABS_CALL_17, - BFD_RELOC_HPPA_ABS_CALL_L21, - BFD_RELOC_HPPA_ABS_CALL_R11, - BFD_RELOC_HPPA_ABS_CALL_R14, - BFD_RELOC_HPPA_ABS_CALL_R17, - BFD_RELOC_HPPA_ABS_CALL_LS21, - BFD_RELOC_HPPA_ABS_CALL_RS11, - BFD_RELOC_HPPA_ABS_CALL_RS14, - BFD_RELOC_HPPA_ABS_CALL_RS17, - BFD_RELOC_HPPA_ABS_CALL_LD21, - BFD_RELOC_HPPA_ABS_CALL_RD11, - BFD_RELOC_HPPA_ABS_CALL_RD14, - BFD_RELOC_HPPA_ABS_CALL_RD17, - BFD_RELOC_HPPA_ABS_CALL_LR21, - BFD_RELOC_HPPA_ABS_CALL_RR14, - BFD_RELOC_HPPA_ABS_CALL_RR17, - - BFD_RELOC_HPPA_PCREL_CALL_11, - BFD_RELOC_HPPA_PCREL_CALL_12, - BFD_RELOC_HPPA_PCREL_CALL_14, - BFD_RELOC_HPPA_PCREL_CALL_17, - BFD_RELOC_HPPA_PCREL_CALL_L21, - BFD_RELOC_HPPA_PCREL_CALL_R11, - BFD_RELOC_HPPA_PCREL_CALL_R14, - BFD_RELOC_HPPA_PCREL_CALL_R17, - BFD_RELOC_HPPA_PCREL_CALL_LS21, - BFD_RELOC_HPPA_PCREL_CALL_RS11, - BFD_RELOC_HPPA_PCREL_CALL_RS14, - BFD_RELOC_HPPA_PCREL_CALL_RS17, - BFD_RELOC_HPPA_PCREL_CALL_LD21, - BFD_RELOC_HPPA_PCREL_CALL_RD11, - BFD_RELOC_HPPA_PCREL_CALL_RD14, - BFD_RELOC_HPPA_PCREL_CALL_RD17, - BFD_RELOC_HPPA_PCREL_CALL_LR21, - BFD_RELOC_HPPA_PCREL_CALL_RR14, - BFD_RELOC_HPPA_PCREL_CALL_RR17, - - BFD_RELOC_HPPA_PLABEL_32, - BFD_RELOC_HPPA_PLABEL_11, - BFD_RELOC_HPPA_PLABEL_14, - BFD_RELOC_HPPA_PLABEL_L21, - BFD_RELOC_HPPA_PLABEL_R11, - BFD_RELOC_HPPA_PLABEL_R14, - - BFD_RELOC_HPPA_UNWIND_ENTRY, - BFD_RELOC_HPPA_UNWIND_ENTRIES, + /* MIPS ELF relocations. */ + BFD_RELOC_MIPS_GOT16, + BFD_RELOC_MIPS_CALL16, +#define BFD_RELOC_MIPS_GPREL32 BFD_RELOC_GPREL32 /* i386/elf relocations */ BFD_RELOC_386_GOT32, @@ -1293,15 +1428,38 @@ typedef enum bfd_reloc_code_real BFD_RELOC_386_GOTOFF, BFD_RELOC_386_GOTPC, + /* ns32k relocations */ + BFD_RELOC_NS32K_IMM_8, + BFD_RELOC_NS32K_IMM_16, + BFD_RELOC_NS32K_IMM_32, + BFD_RELOC_NS32K_IMM_8_PCREL, + BFD_RELOC_NS32K_IMM_16_PCREL, + BFD_RELOC_NS32K_IMM_32_PCREL, + BFD_RELOC_NS32K_DISP_8, + BFD_RELOC_NS32K_DISP_16, + BFD_RELOC_NS32K_DISP_32, + BFD_RELOC_NS32K_DISP_8_PCREL, + BFD_RELOC_NS32K_DISP_16_PCREL, + BFD_RELOC_NS32K_DISP_32_PCREL, + + /* PowerPC/POWER (RS/6000) relocs. */ + /* 26 bit relative branch. Low two bits must be zero. High 24 + bits installed in bits 6 through 29 of instruction. */ + BFD_RELOC_PPC_B26, + /* 26 bit absolute branch, like BFD_RELOC_PPC_B26 but absolute. */ + BFD_RELOC_PPC_BA26, + /* 16 bit TOC relative reference. */ + BFD_RELOC_PPC_TOC16, + /* this must be the highest numeric value */ BFD_RELOC_UNUSED } bfd_reloc_code_real_type; -CONST struct reloc_howto_struct * +const struct reloc_howto_struct * bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); -typedef struct symbol_cache_entry +typedef struct symbol_cache_entry { /* A pointer to the BFD which owns the symbol. This information is necessary so that a back end can work out what additional @@ -1315,7 +1473,7 @@ typedef struct symbol_cache_entry struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */ - /* The text of the symbol. The name is left alone, and not copied - the + /* The text of the symbol. The name is left alone, and not copied; the application may not alter it. */ CONST char *name; @@ -1336,7 +1494,7 @@ typedef struct symbol_cache_entry value is the offset into the section of the data. */ #define BSF_GLOBAL 0x02 - /* The symbol has global scope, and is exported. The value is + /* The symbol has global scope and is exported. The value is the offset into the section of the data. */ #define BSF_EXPORT BSF_GLOBAL /* no real difference */ @@ -1397,9 +1555,12 @@ typedef struct symbol_cache_entry for ELF STT_FILE symbols. */ #define BSF_FILE 0x4000 + /* Symbol is from dynamic linking information. */ +#define BSF_DYNAMIC 0x8000 + flagword flags; - /* A pointer to the section to which this symbol is + /* A pointer to the section to which this symbol is relative. This will always be non NULL, there are special sections for undefined and absolute symbols */ struct sec *section; @@ -1409,13 +1570,18 @@ typedef struct symbol_cache_entry PTR udata; } asymbol; -#define get_symtab_upper_bound(abfd) \ - BFD_SEND (abfd, _get_symtab_upper_bound, (abfd)) +#define bfd_get_symtab_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd)) +boolean +bfd_is_local_label PARAMS ((bfd *abfd, asymbol *sym)); + +#define bfd_is_local_label(abfd, sym) \ + BFD_SEND (abfd, _bfd_is_local_label,(abfd, sym)) #define bfd_canonicalize_symtab(abfd, location) \ BFD_SEND (abfd, _bfd_canonicalize_symtab,\ (abfd, location)) boolean -bfd_set_symtab PARAMS ((bfd *, asymbol **, unsigned int )); +bfd_set_symtab PARAMS ((bfd *abfd, asymbol **location, unsigned int count)); void bfd_print_symbol_vandf PARAMS ((PTR file, asymbol *symbol)); @@ -1436,7 +1602,7 @@ struct _bfd CONST char *filename; /* A pointer to the target jump table. */ - struct bfd_target *xvec; + const struct bfd_target *xvec; /* To avoid dragging too many header files into every file that includes `<>', IOSTREAM has been declared as a "char @@ -1445,13 +1611,14 @@ struct _bfd is the result of an fopen on the filename. */ char *iostream; - /* Is the file being cached */ + /* Is the file descriptor being cached? That is, can it be closed as + needed, and re-opened when accessed later? */ boolean cacheable; /* Marks whether there was a default target specified when the - BFD was opened. This is used to select what matching algorithm - to use to chose the back end. */ + BFD was opened. This is used to select which matching algorithm + to use to choose the back end. */ boolean target_defaulted; @@ -1461,12 +1628,11 @@ struct _bfd struct _bfd *lru_prev, *lru_next; /* When a file is closed by the caching routines, BFD retains - state information on the file here: - */ + state information on the file here: */ file_ptr where; - /* and here:*/ + /* and here: (``once'' means at least once) */ boolean opened_once; @@ -1483,7 +1649,7 @@ struct _bfd int ifd; - /* The format which belongs to the BFD.*/ + /* The format which belongs to the BFD. (object, core, etc.) */ bfd_format format; @@ -1505,7 +1671,7 @@ struct _bfd file_ptr origin; /* Remember when output has begun, to stop strange things - happening. */ + from happening. */ boolean output_has_begun; /* Pointer to linked list of sections*/ @@ -1521,7 +1687,7 @@ struct _bfd /* Used for input and output*/ unsigned int symcount; - /* Symbol table for output BFD*/ + /* Symbol table for output BFD (with symcount entries) */ struct symbol_cache_entry **outsymbols; /* Pointer to structure which contains architecture information*/ @@ -1529,11 +1695,18 @@ struct _bfd /* Stuff only useful for archives:*/ PTR arelt_data; - struct _bfd *my_archive; - struct _bfd *next; - struct _bfd *archive_head; + struct _bfd *my_archive; /* The containing archive BFD. */ + struct _bfd *next; /* The next BFD in the archive. */ + struct _bfd *archive_head; /* The first BFD in the archive. */ boolean has_armap; + /* A chain of BFD structures involved in a link. */ + struct _bfd *link_next; + + /* A field used by _bfd_generic_link_add_archive_symbols. This will + be used only for archive elements. */ + int archive_pass; + /* Used by the back end to hold private data. */ union @@ -1553,11 +1726,13 @@ struct _bfd struct bout_data_struct *bout_data; struct sun_core_struct *sun_core_data; struct trad_core_struct *trad_core_data; - struct hppa_data_struct *hppa_data; + struct som_data_struct *som_data; struct hpux_core_struct *hpux_core_data; + struct hppabsd_core_struct *hppabsd_core_data; struct sgi_core_struct *sgi_core_data; struct lynx_core_struct *lynx_core_data; struct osf_core_struct *osf_core_data; + struct cisco_core_struct *cisco_core_data; PTR any; } tdata; @@ -1566,24 +1741,51 @@ struct _bfd /* Where all the allocated stuff under this BFD goes */ struct obstack memory; - - /* Is this really needed in addition to usrdata? */ - asymbol **ld_symbols; }; -unsigned int +typedef enum bfd_error +{ + bfd_error_no_error = 0, + bfd_error_system_call, + bfd_error_invalid_target, + bfd_error_wrong_format, + bfd_error_invalid_operation, + bfd_error_no_memory, + bfd_error_no_symbols, + bfd_error_no_more_archived_files, + bfd_error_malformed_archive, + bfd_error_file_not_recognized, + bfd_error_file_ambiguously_recognized, + bfd_error_no_contents, + bfd_error_nonrepresentable_section, + bfd_error_no_debug_section, + bfd_error_bad_value, + bfd_error_file_truncated, + bfd_error_invalid_error_code +} bfd_error_type; + +bfd_error_type +bfd_get_error PARAMS ((void)); + +void +bfd_set_error PARAMS ((bfd_error_type error_tag)); + +CONST char * +bfd_errmsg PARAMS ((bfd_error_type error_tag)); + +void +bfd_perror PARAMS ((CONST char *message)); + +long bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect)); -unsigned int +long bfd_canonicalize_reloc PARAMS ((bfd *abfd, asection *sec, arelent **loc, asymbol **syms)); -boolean -bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags)); - void bfd_set_reloc PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count) @@ -1591,23 +1793,32 @@ bfd_set_reloc ); boolean -bfd_set_start_address PARAMS ((bfd *, bfd_vma)); +bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags)); + +boolean +bfd_set_start_address PARAMS ((bfd *abfd, bfd_vma vma)); long -bfd_get_mtime PARAMS ((bfd *)); +bfd_get_mtime PARAMS ((bfd *abfd)); long -bfd_get_size PARAMS ((bfd *)); +bfd_get_size PARAMS ((bfd *abfd)); int -bfd_get_gp_size PARAMS ((bfd *)); +bfd_get_gp_size PARAMS ((bfd *abfd)); void -bfd_set_gp_size PARAMS ((bfd *, int)); +bfd_set_gp_size PARAMS ((bfd *abfd, int i)); bfd_vma bfd_scan_vma PARAMS ((CONST char *string, CONST char **end, int base)); +boolean +bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd)); + +#define bfd_copy_private_bfd_data(ibfd, obfd) \ + BFD_SEND (ibfd, _bfd_copy_private_bfd_data, \ + (ibfd, obfd)) #define bfd_sizeof_headers(abfd, reloc) \ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) @@ -1631,31 +1842,54 @@ bfd_scan_vma PARAMS ((CONST char *string, CONST char **end, int base)); #define bfd_set_arch_mach(abfd, arch, mach)\ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) -#define bfd_get_relocated_section_contents(abfd, seclet, data, relocateable) \ - BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet, data, relocateable)) +#define bfd_get_relocated_section_contents(abfd, link_info, link_order, data, relocateable, symbols) \ + BFD_SEND (abfd, _bfd_get_relocated_section_contents, \ + (abfd, link_info, link_order, data, relocateable, symbols)) -#define bfd_relax_section(abfd, section, symbols) \ - BFD_SEND (abfd, _bfd_relax_section, (abfd, section, symbols)) +#define bfd_relax_section(abfd, section, link_info, again) \ + BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) + +#define bfd_link_hash_table_create(abfd) \ + BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) + +#define bfd_link_add_symbols(abfd, info) \ + BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) + +#define bfd_final_link(abfd, info) \ + BFD_SEND (abfd, _bfd_final_link, (abfd, info)) + +#define bfd_free_cached_info(abfd) \ + BFD_SEND (abfd, _bfd_free_cached_info, (abfd)) + +#define bfd_get_dynamic_symtab_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd)) + +#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \ + BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols)) + +#define bfd_get_dynamic_reloc_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd)) + +#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \ + BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms)) -#define bfd_seclet_link(abfd, data, relocateable) \ - BFD_SEND (abfd, _bfd_seclet_link, (abfd, data, relocateable)) symindex -bfd_get_next_mapent PARAMS ((bfd *, symindex previous, carsym ** sym)); +bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym)); boolean bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head)); bfd * -bfd_get_elt_at_index PARAMS ((bfd * archive, int index)); +bfd_get_elt_at_index PARAMS ((bfd *archive, int index)); -bfd* +bfd * bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous)); CONST char * -bfd_core_file_failing_command PARAMS ((bfd *)); +bfd_core_file_failing_command PARAMS ((bfd *abfd)); int -bfd_core_file_failing_signal PARAMS ((bfd *)); +bfd_core_file_failing_signal PARAMS ((bfd *abfd)); boolean core_file_matches_executable_p @@ -1663,23 +1897,45 @@ core_file_matches_executable_p #define BFD_SEND(bfd, message, arglist) \ ((*((bfd)->xvec->message)) arglist) + +#ifdef DEBUG_BFD_SEND +#undef BFD_SEND +#define BFD_SEND(bfd, message, arglist) \ + (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ + ((*((bfd)->xvec->message)) arglist) : \ + (bfd_assert (__FILE__,__LINE__), NULL)) +#endif #define BFD_SEND_FMT(bfd, message, arglist) \ (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) + +#ifdef DEBUG_BFD_SEND +#undef BFD_SEND_FMT +#define BFD_SEND_FMT(bfd, message, arglist) \ + (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ + (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) : \ + (bfd_assert (__FILE__,__LINE__), NULL)) +#endif +enum bfd_flavour { + bfd_target_unknown_flavour, + bfd_target_aout_flavour, + bfd_target_coff_flavour, + bfd_target_ecoff_flavour, + bfd_target_elf_flavour, + bfd_target_ieee_flavour, + bfd_target_nlm_flavour, + bfd_target_oasys_flavour, + bfd_target_tekhex_flavour, + bfd_target_srec_flavour, + bfd_target_som_flavour, + bfd_target_os9k_flavour}; + + /* Forward declaration. */ +typedef struct bfd_link_info _bfd_link_info; + typedef struct bfd_target { char *name; - enum target_flavour { - bfd_target_unknown_flavour, - bfd_target_aout_flavour, - bfd_target_coff_flavour, - bfd_target_ecoff_flavour, - bfd_target_elf_flavour, - bfd_target_ieee_flavour, - bfd_target_nlm_flavour, - bfd_target_oasys_flavour, - bfd_target_tekhex_flavour, - bfd_target_srec_flavour, - bfd_target_hppa_flavour} flavour; + enum bfd_flavour flavour; boolean byteorder_big_p; boolean header_byteorder_big_p; flagword object_flags; @@ -1688,30 +1944,73 @@ typedef struct bfd_target char ar_pad_char; unsigned short ar_max_namelen; unsigned int align_power_min; - bfd_vma (*bfd_getx64) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *)); void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *)); - bfd_vma (*bfd_getx32) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *)); void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *)); - bfd_vma (*bfd_getx16) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *)); void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *)); - bfd_vma (*bfd_h_getx64) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *)); void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *)); - bfd_vma (*bfd_h_getx32) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *)); void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *)); - bfd_vma (*bfd_h_getx16) PARAMS ((bfd_byte *)); - bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((bfd_byte *)); + bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *)); + bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *)); void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *)); - struct bfd_target * (*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *)); + const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *)); boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *)); boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *)); + + /* Generic entry points. */ +#define BFD_JUMP_TABLE_GENERIC(NAME)\ +CAT(NAME,_close_and_cleanup),\ +CAT(NAME,_bfd_free_cached_info),\ +CAT(NAME,_new_section_hook),\ +CAT(NAME,_get_section_contents) + /* Called when the BFD is being closed to do any necessary cleanup. */ + boolean (*_close_and_cleanup) PARAMS ((bfd *)); + /* Ask the BFD to free all cached information. */ + boolean (*_bfd_free_cached_info) PARAMS ((bfd *)); + /* Called when a new section is created. */ + boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr)); + /* Read the contents of a section. */ + boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, + file_ptr, bfd_size_type)); + + /* Entry points to copy private data. */ +#define BFD_JUMP_TABLE_COPY(NAME)\ +CAT(NAME,_bfd_copy_private_bfd_data),\ +CAT(NAME,_bfd_copy_private_section_data) + /* Called to copy BFD general private data from one object file + to another. */ + boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *)); + /* Called to copy BFD private section data from one object file + to another. */ + boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr, + bfd *, sec_ptr)); + + /* Core file entry points. */ +#define BFD_JUMP_TABLE_CORE(NAME)\ +CAT(NAME,_core_file_failing_command),\ +CAT(NAME,_core_file_failing_signal),\ +CAT(NAME,_core_file_matches_executable_p) char * (*_core_file_failing_command) PARAMS ((bfd *)); int (*_core_file_failing_signal) PARAMS ((bfd *)); boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *)); + + /* Archive entry points. */ +#define BFD_JUMP_TABLE_ARCHIVE(NAME)\ +CAT(NAME,_slurp_armap),\ +CAT(NAME,_slurp_extended_name_table),\ +CAT(NAME,_truncate_arname),\ +CAT(NAME,_write_armap),\ +CAT(NAME,_openr_next_archived_file),\ +CAT(NAME,_generic_stat_arch_elt) boolean (*_bfd_slurp_armap) PARAMS ((bfd *)); boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *)); void (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *)); @@ -1720,18 +2019,23 @@ typedef struct bfd_target struct orl *map, unsigned int orl_count, int stridx)); - boolean (*_close_and_cleanup) PARAMS ((bfd *)); - boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR, - file_ptr, bfd_size_type)); - boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, - file_ptr, bfd_size_type)); - boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr)); - unsigned int (*_get_symtab_upper_bound) PARAMS ((bfd *)); - unsigned int (*_bfd_canonicalize_symtab) PARAMS ((bfd *, - struct symbol_cache_entry **)); - unsigned int (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr)); - unsigned int (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, - struct symbol_cache_entry **)); + bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); + int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); + + /* Entry points used for symbols. */ +#define BFD_JUMP_TABLE_SYMBOLS(NAME)\ +CAT(NAME,_get_symtab_upper_bound),\ +CAT(NAME,_get_symtab),\ +CAT(NAME,_make_empty_symbol),\ +CAT(NAME,_print_symbol),\ +CAT(NAME,_get_symbol_info),\ +CAT(NAME,_bfd_is_local_label),\ +CAT(NAME,_get_lineno),\ +CAT(NAME,_find_nearest_line),\ +CAT(NAME,_bfd_make_debug_symbol) + long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *)); + long (*_bfd_canonicalize_symtab) PARAMS ((bfd *, + struct symbol_cache_entry **)); struct symbol_cache_entry * (*_bfd_make_empty_symbol) PARAMS ((bfd *)); void (*_bfd_print_symbol) PARAMS ((bfd *, PTR, @@ -1742,40 +2046,13 @@ typedef struct bfd_target struct symbol_cache_entry *, symbol_info *)); #define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e)) + boolean (*_bfd_is_local_label) PARAMS ((bfd *, asymbol *)); + alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *)); - - boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture, - unsigned long)); - - bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); - boolean (*_bfd_find_nearest_line) PARAMS ((bfd *abfd, struct sec *section, struct symbol_cache_entry **symbols, bfd_vma offset, CONST char **file, CONST char **func, unsigned int *line)); - - int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); - - int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean)); - - void (*_bfd_debug_info_start) PARAMS ((bfd *)); - void (*_bfd_debug_info_end) PARAMS ((bfd *)); - void (*_bfd_debug_info_accumulate) PARAMS ((bfd *, struct sec *)); - - bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *, - struct bfd_seclet *, bfd_byte *data, - boolean relocateable)); - - boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *, - struct symbol_cache_entry **)); - - boolean (*_bfd_seclet_link) PARAMS ((bfd *, PTR data, - boolean relocateable)); - /* See documentation on reloc types. */ - CONST struct reloc_howto_struct * - (*reloc_type_lookup) PARAMS ((bfd *abfd, - bfd_reloc_code_real_type code)); - /* Back-door to allow format-aware applications to create debug symbols while using BFD for everything else. Currently used by the assembler when creating COFF files. */ @@ -1783,21 +2060,92 @@ typedef struct bfd_target bfd *abfd, void *ptr, unsigned long size)); + + /* Routines for relocs. */ +#define BFD_JUMP_TABLE_RELOCS(NAME)\ +CAT(NAME,_get_reloc_upper_bound),\ +CAT(NAME,_canonicalize_reloc),\ +CAT(NAME,_bfd_reloc_type_lookup) + long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr)); + long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, + struct symbol_cache_entry **)); + /* See documentation on reloc types. */ + CONST struct reloc_howto_struct * + (*reloc_type_lookup) PARAMS ((bfd *abfd, + bfd_reloc_code_real_type code)); + + /* Routines used when writing an object file. */ +#define BFD_JUMP_TABLE_WRITE(NAME)\ +CAT(NAME,_set_arch_mach),\ +CAT(NAME,_set_section_contents) + boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture, + unsigned long)); + boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR, + file_ptr, bfd_size_type)); + + /* Routines used by the linker. */ +#define BFD_JUMP_TABLE_LINK(NAME)\ +CAT(NAME,_sizeof_headers),\ +CAT(NAME,_bfd_get_relocated_section_contents),\ +CAT(NAME,_bfd_relax_section),\ +CAT(NAME,_bfd_link_hash_table_create),\ +CAT(NAME,_bfd_link_add_symbols),\ +CAT(NAME,_bfd_final_link) + int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean)); + bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *, + struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *data, boolean relocateable, + struct symbol_cache_entry **)); + + boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *, + struct bfd_link_info *, boolean *again)); + + /* Create a hash table for the linker. Different backends store + different information in this table. */ + struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *)); + + /* Add symbols from this object file into the hash table. */ + boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *)); + + /* Do a link based on the link_order structures attached to each + section of the BFD. */ + boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *)); + + /* Routines to handle dynamic symbols and relocs. */ +#define BFD_JUMP_TABLE_DYNAMIC(NAME)\ +CAT(NAME,_get_dynamic_symtab_upper_bound),\ +CAT(NAME,_canonicalize_dynamic_symtab),\ +CAT(NAME,_get_dynamic_reloc_upper_bound),\ +CAT(NAME,_canonicalize_dynamic_reloc) + /* Get the amount of memory required to hold the dynamic symbols. */ + long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *)); + /* Read in the dynamic symbols. */ + long (*_bfd_canonicalize_dynamic_symtab) + PARAMS ((bfd *, struct symbol_cache_entry **)); + /* Get the amount of memory required to hold the dynamic relocs. */ + long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *)); + /* Read in the dynamic relocs. */ + long (*_bfd_canonicalize_dynamic_reloc) + PARAMS ((bfd *, arelent **, struct symbol_cache_entry **)); + PTR backend_data; } bfd_target; -bfd_target * -bfd_find_target PARAMS ((CONST char *, bfd *)); +const bfd_target * +bfd_find_target PARAMS ((CONST char *target_name, bfd *abfd)); -CONST char ** +const char ** bfd_target_list PARAMS ((void)); boolean bfd_check_format PARAMS ((bfd *abfd, bfd_format format)); boolean -bfd_set_format PARAMS ((bfd *, bfd_format)); +bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching)); + +boolean +bfd_set_format PARAMS ((bfd *abfd, bfd_format format)); CONST char * -bfd_format_string PARAMS ((bfd_format)); +bfd_format_string PARAMS ((bfd_format format)); #endif diff --git a/gnu/usr.bin/gdb/bfd/cache.c b/gnu/usr.bin/gdb/bfd/cache.c index f8cfd19fed5c..a26c3ce57672 100644 --- a/gnu/usr.bin/gdb/bfd/cache.c +++ b/gnu/usr.bin/gdb/bfd/cache.c @@ -1,5 +1,5 @@ /* BFD library -- caching of file descriptors. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1994 Free Software Foundation, Inc. Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com). This file is part of BFD, the Binary File Descriptor library. @@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* SECTION - File Caching + File caching The file caching mechanism is embedded within BFD and allows the application to open as many BFDs as it wants without @@ -28,7 +28,7 @@ SECTION limit (often as low as 20 open files). The module in <> maintains a least recently used list of <> files, and exports the name - <> which runs around and makes sure that + <>, which runs around and makes sure that the required BFD is open. If not, then it chooses a file to close, closes it and opens the one wanted, returning its file handle. @@ -39,6 +39,11 @@ SECTION #include "sysdep.h" #include "libbfd.h" +static void insert PARAMS ((bfd *)); +static void snip PARAMS ((bfd *)); +static boolean close_one PARAMS ((void)); +static boolean bfd_cache_delete PARAMS ((bfd *)); + /* INTERNAL_FUNCTION BFD_CACHE_MAX_OPEN macro @@ -51,18 +56,10 @@ DESCRIPTION */ - -static boolean -bfd_cache_delete PARAMS ((bfd *)); - -/* Number of bfds on the chain. All such bfds have their file open; - if it closed, they get snipd()d from the chain. */ +/* The number of BFD files we have open. */ static int open_files; -static bfd *cache_sentinel; /* Chain of BFDs with active fds we've - opened */ - /* INTERNAL_FUNCTION bfd_last_cache @@ -79,233 +76,268 @@ DESCRIPTION bfd *bfd_last_cache; /* - * INTERNAL_FUNCTION - * bfd_cache_lookup - * - * DESCRIPTION - * Checks to see if the required BFD is the same as the last one - * looked up. If so then it can use the iostream in the BFD with - * impunity, since it can't have changed since the last lookup, - * otherwise it has to perform the complicated lookup function - * - * .#define bfd_cache_lookup(x) \ - * . ((x)==bfd_last_cache? \ - * . (FILE*)(bfd_last_cache->iostream): \ - * . bfd_cache_lookup_worker(x)) - * - * + INTERNAL_FUNCTION + bfd_cache_lookup + + DESCRIPTION + Check to see if the required BFD is the same as the last one + looked up. If so, then it can use the stream in the BFD with + impunity, since it can't have changed since the last lookup; + otherwise, it has to perform the complicated lookup function. + + .#define bfd_cache_lookup(x) \ + . ((x)==bfd_last_cache? \ + . (FILE*)(bfd_last_cache->iostream): \ + . bfd_cache_lookup_worker(x)) + + */ -static void -DEFUN_VOID(close_one) +/* Insert a BFD into the cache. */ + +static INLINE void +insert (abfd) + bfd *abfd; { - bfd *kill = cache_sentinel; - if (kill == 0) /* Nothing in the cache */ - return ; - - /* We can only close files that want to play this game. */ - while (!kill->cacheable) { - kill = kill->lru_prev; - if (kill == cache_sentinel) /* Nobody wants to play */ - return ; + if (bfd_last_cache == NULL) + { + abfd->lru_next = abfd; + abfd->lru_prev = abfd; } - - kill->where = ftell((FILE *)(kill->iostream)); - (void) bfd_cache_delete(kill); + else + { + abfd->lru_next = bfd_last_cache; + abfd->lru_prev = bfd_last_cache->lru_prev; + abfd->lru_prev->lru_next = abfd; + abfd->lru_next->lru_prev = abfd; + } + bfd_last_cache = abfd; } -/* Cuts the BFD abfd out of the chain in the cache */ -static void -DEFUN(snip,(abfd), - bfd *abfd) +/* Remove a BFD from the cache. */ + +static INLINE void +snip (abfd) + bfd *abfd; { abfd->lru_prev->lru_next = abfd->lru_next; - abfd->lru_next->lru_prev = abfd->lru_prev; - if (cache_sentinel == abfd) cache_sentinel = (bfd *)NULL; + abfd->lru_next->lru_prev = abfd->lru_prev; + if (abfd == bfd_last_cache) + { + bfd_last_cache = abfd->lru_next; + if (abfd == bfd_last_cache) + bfd_last_cache = NULL; + } } +/* We need to open a new file, and the cache is full. Find the least + recently used cacheable BFD and close it. */ + static boolean -DEFUN(bfd_cache_delete,(abfd), - bfd *abfd) +close_one () +{ + register bfd *kill; + + if (bfd_last_cache == NULL) + kill = NULL; + else + { + for (kill = bfd_last_cache->lru_prev; + ! kill->cacheable; + kill = kill->lru_prev) + { + if (kill == bfd_last_cache) + { + kill = NULL; + break; + } + } + } + + if (kill == NULL) + { + /* There are no open cacheable BFD's. */ + return true; + } + + kill->where = ftell ((FILE *) kill->iostream); + + return bfd_cache_delete (kill); +} + +/* Close a BFD and remove it from the cache. */ + +static boolean +bfd_cache_delete (abfd) + bfd *abfd; { boolean ret; - if (fclose ((FILE *)(abfd->iostream)) == 0) + if (fclose ((FILE *) abfd->iostream) == 0) ret = true; else { ret = false; - bfd_error = system_call_error; + bfd_set_error (bfd_error_system_call); } + snip (abfd); + abfd->iostream = NULL; - open_files--; - bfd_last_cache = 0; + --open_files; + return ret; } - -static bfd * -DEFUN(insert,(x,y), - bfd *x AND - bfd *y) -{ - if (y) { - x->lru_next = y; - x->lru_prev = y->lru_prev; - y->lru_prev->lru_next = x; - y->lru_prev = x; - - } - else { - x->lru_prev = x; - x->lru_next = x; - } - return x; -} - - -/* Initialize a BFD by putting it on the cache LRU. */ - -void -DEFUN(bfd_cache_init,(abfd), - bfd *abfd) + +/* +INTERNAL_FUNCTION + bfd_cache_init + +SYNOPSIS + boolean bfd_cache_init (bfd *abfd); + +DESCRIPTION + Add a newly opened BFD to the cache. +*/ + +boolean +bfd_cache_init (abfd) + bfd *abfd; { + BFD_ASSERT (abfd->iostream != NULL); if (open_files >= BFD_CACHE_MAX_OPEN) - close_one (); - cache_sentinel = insert(abfd, cache_sentinel); + { + if (! close_one ()) + return false; + } + insert (abfd); ++open_files; + return true; } - /* INTERNAL_FUNCTION bfd_cache_close -DESCRIPTION - Remove the BFD from the cache. If the attached file is open, - then close it too. - SYNOPSIS - boolean bfd_cache_close (bfd *); + boolean bfd_cache_close (bfd *abfd); + +DESCRIPTION + Remove the BFD @var{abfd} from the cache. If the attached file is open, + then close it too. RETURNS <> is returned if closing the file fails, <> is returned if all is well. */ + boolean -DEFUN(bfd_cache_close,(abfd), - bfd *abfd) +bfd_cache_close (abfd) + bfd *abfd; { - /* If this file is open then remove from the chain */ - if (abfd->iostream) - { - return bfd_cache_delete(abfd); - } - else - { - return true; - } + if (abfd->iostream == NULL) + return true; + + return bfd_cache_delete (abfd); } /* INTERNAL_FUNCTION bfd_open_file -DESCRIPTION - Call the OS to open a file for this BFD. Returns the FILE * - (possibly null) that results from this operation. Sets up the - BFD so that future accesses know the file is open. If the FILE - * returned is null, then there is won't have been put in the - cache, so it won't have to be removed from it. - SYNOPSIS - FILE* bfd_open_file(bfd *); + FILE* bfd_open_file(bfd *abfd); + +DESCRIPTION + Call the OS to open a file for @var{abfd}. Return the <> + (possibly <>) that results from this operation. Set up the + BFD so that future accesses know the file is open. If the <> + returned is <>, then it won't have been put in the + cache, so it won't have to be removed from it. */ FILE * -DEFUN(bfd_open_file, (abfd), - bfd *abfd) +bfd_open_file (abfd) + bfd *abfd; { abfd->cacheable = true; /* Allow it to be closed later. */ - if(open_files >= BFD_CACHE_MAX_OPEN) { - close_one(); - } - - switch (abfd->direction) { - case read_direction: - case no_direction: - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RB); - break; - case both_direction: - case write_direction: - if (abfd->opened_once == true) { - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RUB); - if (!abfd->iostream) { - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WUB); - } - } else { - /*open for creat */ - abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB); - abfd->opened_once = true; + if (open_files >= BFD_CACHE_MAX_OPEN) + { + if (! close_one ()) + return NULL; } - break; - } - if (abfd->iostream) { - bfd_cache_init (abfd); - } + switch (abfd->direction) + { + case read_direction: + case no_direction: + abfd->iostream = (char *) fopen (abfd->filename, FOPEN_RB); + break; + case both_direction: + case write_direction: + if (abfd->opened_once == true) + { + abfd->iostream = (char *) fopen (abfd->filename, FOPEN_RUB); + if (abfd->iostream == NULL) + abfd->iostream = (char *) fopen (abfd->filename, FOPEN_WUB); + } + else + { + /*open for creat */ + abfd->iostream = (char *) fopen (abfd->filename, FOPEN_WB); + abfd->opened_once = true; + } + break; + } - return (FILE *)(abfd->iostream); + if (abfd->iostream != NULL) + { + if (! bfd_cache_init (abfd)) + return NULL; + } + + return (FILE *) abfd->iostream; } /* INTERNAL_FUNCTION bfd_cache_lookup_worker +SYNOPSIS + FILE *bfd_cache_lookup_worker(bfd *abfd); + DESCRIPTION Called when the macro <> fails to find a - quick answer. Finds a file descriptor for this BFD. If - necessary, it open it. If there are already more than - BFD_CACHE_MAX_OPEN files open, it trys to close one first, to + quick answer. Find a file descriptor for @var{abfd}. If + necessary, it open it. If there are already more than + <> files open, it tries to close one first, to avoid running out of file descriptors. - -SYNOPSIS - FILE *bfd_cache_lookup_worker(bfd *); - */ FILE * -DEFUN(bfd_cache_lookup_worker,(abfd), - bfd *abfd) +bfd_cache_lookup_worker (abfd) + bfd *abfd; { if (abfd->my_archive) - { - abfd = abfd->my_archive; - } - /* Is this file already open .. if so then quick exit */ - if (abfd->iostream) - { - if (abfd != cache_sentinel) { - /* Place onto head of lru chain */ + abfd = abfd->my_archive; + + if (abfd->iostream != NULL) + { + /* Move the file to the start of the cache. */ + if (abfd != bfd_last_cache) + { snip (abfd); - cache_sentinel = insert(abfd, cache_sentinel); + insert (abfd); } - } - /* This is a BFD without a stream - - so it must have been closed or never opened. - find an empty cache entry and use it. */ - else - { + } + else + { + if (bfd_open_file (abfd) == NULL) + return NULL; + if (fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0) + return NULL; + } - if (open_files >= BFD_CACHE_MAX_OPEN) - { - close_one(); - } - - BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ; - fseek((FILE *)(abfd->iostream), abfd->where, false); - } - bfd_last_cache = abfd; - return (FILE *)(abfd->iostream); + return (FILE *) abfd->iostream; } diff --git a/gnu/usr.bin/gdb/bfd/coffgen.c b/gnu/usr.bin/gdb/bfd/coffgen.c index 94cc225d098c..f0c05c7f8b90 100644 --- a/gnu/usr.bin/gdb/bfd/coffgen.c +++ b/gnu/usr.bin/gdb/bfd/coffgen.c @@ -1,5 +1,5 @@ /* Support for the generic parts of COFF, for BFD. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -39,18 +39,25 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "sysdep.h" #include "libbfd.h" #include "coff/internal.h" -#include "seclet.h" #include "libcoff.h" +static boolean coff_write_symbol PARAMS ((bfd *, asymbol *, + combined_entry_type *, + unsigned int *)); +static boolean coff_write_alien_symbol PARAMS ((bfd *, asymbol *, + unsigned int *)); +static boolean coff_write_native_symbol PARAMS ((bfd *, coff_symbol_type *, + unsigned int *)); + static asection bfd_debug_section = { "*DEBUG*" }; /* Take a section header read from a coff file (in HOST byte order), and make a BFD "section" out of it. This is used by ECOFF. */ static boolean -DEFUN(make_a_section_from_file,(abfd, hdr, target_index), - bfd *abfd AND - struct internal_scnhdr *hdr AND - unsigned int target_index) +make_a_section_from_file (abfd, hdr, target_index) + bfd *abfd; + struct internal_scnhdr *hdr; + unsigned int target_index; { asection *return_section; char *name; @@ -58,7 +65,7 @@ DEFUN(make_a_section_from_file,(abfd, hdr, target_index), /* Assorted wastage to null-terminate the name, thanks AT&T! */ name = bfd_alloc(abfd, sizeof (hdr->s_name)+1); if (name == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } strncpy(name, (char *) &hdr->s_name[0], sizeof (hdr->s_name)); @@ -98,7 +105,7 @@ DEFUN(make_a_section_from_file,(abfd, hdr, target_index), /* At least on i386-coff, the line number count for a shared library section must be ignored. */ - if ((return_section->flags & SEC_SHARED_LIBRARY) != 0) + if ((return_section->flags & SEC_COFF_SHARED_LIBRARY) != 0) return_section->lineno_count = 0; if (hdr->s_nreloc != 0) @@ -112,13 +119,12 @@ DEFUN(make_a_section_from_file,(abfd, hdr, target_index), /* Read in a COFF object and make it into a BFD. This is used by ECOFF as well. */ -static -bfd_target * -DEFUN(coff_real_object_p,(abfd, nscns, internal_f, internal_a), - bfd *abfd AND - unsigned nscns AND - struct internal_filehdr *internal_f AND - struct internal_aouthdr *internal_a) +static const bfd_target * +coff_real_object_p (abfd, nscns, internal_f, internal_a) + bfd *abfd; + unsigned nscns; + struct internal_filehdr *internal_f; + struct internal_aouthdr *internal_a; { PTR tdata; size_t readsize; /* length of file_info */ @@ -133,6 +139,11 @@ DEFUN(coff_real_object_p,(abfd, nscns, internal_f, internal_a), scnhsz = bfd_coff_scnhsz (abfd); readsize = nscns * scnhsz; external_sections = (char *)bfd_alloc(abfd, readsize); + if (!external_sections) + { + bfd_set_error (bfd_error_no_memory); + goto fail; + } if (bfd_read((PTR)external_sections, 1, readsize, abfd) != readsize) { goto fail; @@ -163,6 +174,9 @@ DEFUN(coff_real_object_p,(abfd, nscns, internal_f, internal_a), if (!(internal_f->f_flags & F_LSYMS)) abfd->flags |= HAS_LOCALS; + /* FIXME: How can we set D_PAGED correctly? */ + if ((internal_f->f_flags & F_EXEC) != 0) + abfd->flags |= D_PAGED; bfd_get_symcount(abfd) = internal_f->f_nsyms; if (internal_f->f_nsyms) @@ -176,15 +190,15 @@ DEFUN(coff_real_object_p,(abfd, nscns, internal_f, internal_a), return abfd->xvec; fail: bfd_release(abfd, tdata); - return (bfd_target *)NULL; + return (const bfd_target *)NULL; } -/* Turn a COFF file into a BFD, but fail with wrong_format if it is +/* Turn a COFF file into a BFD, but fail with bfd_error_wrong_format if it is not a COFF file. This is also used by ECOFF. */ -bfd_target * -DEFUN(coff_object_p,(abfd), - bfd *abfd) +const bfd_target * +coff_object_p (abfd) + bfd *abfd; { unsigned int filhsz; unsigned int aoutsz; @@ -193,8 +207,6 @@ DEFUN(coff_object_p,(abfd), struct internal_filehdr internal_f; struct internal_aouthdr internal_a; - bfd_error = system_call_error; - /* figure out how much to read */ filhsz = bfd_coff_filhsz (abfd); aoutsz = bfd_coff_aoutsz (abfd); @@ -203,12 +215,16 @@ DEFUN(coff_object_p,(abfd), if (filehdr == NULL) return 0; if (bfd_read(filehdr, 1, filhsz, abfd) != filhsz) - return 0; + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); + return 0; + } bfd_coff_swap_filehdr_in(abfd, filehdr, &internal_f); bfd_release (abfd, filehdr); if (bfd_coff_bad_format_hook (abfd, &internal_f) == false) { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return 0; } nscns =internal_f.f_nscns; @@ -226,7 +242,9 @@ DEFUN(coff_object_p,(abfd), } /* Seek past the opt hdr stuff */ - bfd_seek(abfd, (file_ptr) (internal_f.f_opthdr + filhsz), SEEK_SET); + if (bfd_seek(abfd, (file_ptr) (internal_f.f_opthdr + filhsz), SEEK_SET) + != 0) + return NULL; return coff_real_object_p(abfd, nscns, &internal_f, (internal_f.f_opthdr != 0 @@ -236,20 +254,20 @@ DEFUN(coff_object_p,(abfd), /* Get the BFD section from a COFF symbol section number. */ -struct sec * -DEFUN(coff_section_from_bfd_index,(abfd, index), - bfd *abfd AND - int index) +asection * +coff_section_from_bfd_index (abfd, index) + bfd *abfd; + int index; { struct sec *answer = abfd->sections; if (index == N_ABS) { - return &bfd_abs_section; + return bfd_abs_section_ptr; } if (index == N_UNDEF) { - return &bfd_und_section; + return bfd_und_section_ptr; } if(index == N_DEBUG) { @@ -262,18 +280,20 @@ DEFUN(coff_section_from_bfd_index,(abfd, index), return answer; answer = answer->next; } - BFD_ASSERT(0); - return &bfd_und_section; /* For gcc -W and lint. Never executed. */ + + /* We should not reach this point, but the SCO 3.2v4 /lib/libc_s.a + has a bad symbol table in biglitpow.o. */ + return bfd_und_section_ptr; } /* Get the upper bound of a COFF symbol table. */ -unsigned int +long coff_get_symtab_upper_bound(abfd) bfd *abfd; { if (!bfd_coff_slurp_symbol_table(abfd)) - return 0; + return -1; return (bfd_get_symcount(abfd) + 1) * (sizeof(coff_symbol_type *)); } @@ -281,16 +301,16 @@ bfd *abfd; /* Canonicalize a COFF symbol table. */ -unsigned int -DEFUN(coff_get_symtab, (abfd, alocation), - bfd *abfd AND - asymbol **alocation) +long +coff_get_symtab (abfd, alocation) + bfd *abfd; + asymbol **alocation; { unsigned int counter = 0; coff_symbol_type *symbase; coff_symbol_type **location = (coff_symbol_type **) (alocation); if (!bfd_coff_slurp_symbol_table(abfd)) - return 0; + return -1; symbase = obj_symbols(abfd); while (counter < bfd_get_symcount(abfd)) @@ -317,8 +337,8 @@ DEFUN(coff_get_symtab, (abfd, alocation), /* Set lineno_count for the output sections of a COFF file. */ int -DEFUN(coff_count_linenumbers,(abfd), - bfd *abfd) +coff_count_linenumbers (abfd) + bfd *abfd; { unsigned int limit = bfd_get_symcount(abfd); unsigned int i; @@ -360,10 +380,11 @@ DEFUN(coff_count_linenumbers,(abfd), /* Takes a bfd and a symbol, returns a pointer to the coff specific area of the symbol if there is one. */ +/*ARGSUSED*/ coff_symbol_type * -DEFUN(coff_symbol_from,(ignore_abfd, symbol), - bfd *ignore_abfd AND - asymbol *symbol) +coff_symbol_from (ignore_abfd, symbol) + bfd *ignore_abfd; + asymbol *symbol; { if (bfd_asymbol_flavour(symbol) != bfd_target_coff_flavour) return (coff_symbol_type *)NULL; @@ -375,9 +396,9 @@ DEFUN(coff_symbol_from,(ignore_abfd, symbol), } static void -DEFUN(fixup_symbol_value,(coff_symbol_ptr, syment), -coff_symbol_type *coff_symbol_ptr AND -struct internal_syment *syment) +fixup_symbol_value (coff_symbol_ptr, syment) + coff_symbol_type *coff_symbol_ptr; + struct internal_syment *syment; { /* Normalize the symbol flags */ @@ -389,7 +410,7 @@ struct internal_syment *syment) else if (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING) { syment->n_value = coff_symbol_ptr->symbol.value; } - else if (coff_symbol_ptr->symbol.section == & bfd_und_section) { + else if (bfd_is_und_section (coff_symbol_ptr->symbol.section)) { syment->n_scnum = N_UNDEF; syment->n_value = 0; } @@ -420,9 +441,9 @@ struct internal_syment *syment) do that here too. */ -void -DEFUN(coff_renumber_symbols,(bfd_ptr), - bfd *bfd_ptr) +boolean +coff_renumber_symbols (bfd_ptr) + bfd *bfd_ptr; { unsigned int symbol_count = bfd_get_symcount(bfd_ptr); asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols; @@ -444,12 +465,17 @@ DEFUN(coff_renumber_symbols,(bfd_ptr), newsyms = (asymbol **) bfd_alloc_by_size_t (bfd_ptr, sizeof (asymbol *) * (symbol_count + 1)); + if (!newsyms) + { + bfd_set_error (bfd_error_no_memory); + return false; + } bfd_ptr->outsymbols = newsyms; for (i = 0; i < symbol_count; i++) - if (symbol_ptr_ptr[i]->section != &bfd_und_section) + if (! bfd_is_und_section (symbol_ptr_ptr[i]->section)) *newsyms++ = symbol_ptr_ptr[i]; for (i = 0; i < symbol_count; i++) - if (symbol_ptr_ptr[i]->section == &bfd_und_section) + if (bfd_is_und_section (symbol_ptr_ptr[i]->section)) *newsyms++ = symbol_ptr_ptr[i]; *newsyms = (asymbol *) NULL; symbol_ptr_ptr = bfd_ptr->outsymbols; @@ -485,6 +511,7 @@ DEFUN(coff_renumber_symbols,(bfd_ptr), } } obj_conv_table_size (bfd_ptr) = native_index; + return true; } /* @@ -493,48 +520,65 @@ DEFUN(coff_renumber_symbols,(bfd_ptr), */ void -DEFUN(coff_mangle_symbols,(bfd_ptr), - bfd *bfd_ptr) +coff_mangle_symbols (bfd_ptr) + bfd *bfd_ptr; { - unsigned int symbol_count = bfd_get_symcount(bfd_ptr); + unsigned int symbol_count = bfd_get_symcount (bfd_ptr); asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols; unsigned int symbol_index; for (symbol_index = 0; symbol_index < symbol_count; symbol_index++) - { - coff_symbol_type *coff_symbol_ptr = - coff_symbol_from(bfd_ptr, symbol_ptr_ptr[symbol_index]); + { + coff_symbol_type *coff_symbol_ptr = + coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]); - if (coff_symbol_ptr && coff_symbol_ptr->native) { + if (coff_symbol_ptr && coff_symbol_ptr->native) + { int i; combined_entry_type *s = coff_symbol_ptr->native; - for (i = 0; i < s->u.syment.n_numaux ; i++) { - combined_entry_type *a = s + i + 1; - if (a->fix_tag) { - a->u.auxent.x_sym.x_tagndx.l = - a->u.auxent.x_sym.x_tagndx.p->offset; - a->fix_tag = 0; + if (s->fix_value) + { + /* FIXME: We should use a union here. */ + s->u.syment.n_value = + ((combined_entry_type *) s->u.syment.n_value)->offset; + s->fix_value = 0; } - if (a->fix_end) { - a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l = - a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p->offset; - a->fix_end = 0; - + for (i = 0; i < s->u.syment.n_numaux ; i++) + { + combined_entry_type *a = s + i + 1; + if (a->fix_tag) + { + a->u.auxent.x_sym.x_tagndx.l = + a->u.auxent.x_sym.x_tagndx.p->offset; + a->fix_tag = 0; + } + if (a->fix_end) + { + a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l = + a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p->offset; + a->fix_end = 0; + } + if (a->fix_scnlen) + { + a->u.auxent.x_csect.x_scnlen.l = + a->u.auxent.x_csect.x_scnlen.p->offset; + a->fix_scnlen = 0; + } } - - } } - } + } } -static int string_size; +static bfd_size_type string_size; +static bfd_size_type debug_string_size; +static asection *debug_string_section; static void -DEFUN(coff_fix_symbol_name,(abfd, symbol, native), - bfd *abfd AND - asymbol *symbol AND - combined_entry_type *native) +coff_fix_symbol_name (abfd, symbol, native) + bfd *abfd; + asymbol *symbol; + combined_entry_type *native; { unsigned int name_length; union internal_auxent *auxent; @@ -569,64 +613,108 @@ DEFUN(coff_fix_symbol_name,(abfd, symbol, native), } } else - { /* NOT A C_FILE SYMBOL */ - if (name_length <= SYMNMLEN) { + { /* NOT A C_FILE SYMBOL */ + if (name_length <= SYMNMLEN) + { /* This name will fit into the symbol neatly */ strncpy(native->u.syment._n._n_name, symbol->name, SYMNMLEN); } - else { + else if (! bfd_coff_symname_in_debug (abfd, &native->u.syment)) + { native->u.syment._n._n_n._n_offset = string_size + 4; native->u.syment._n._n_n._n_zeroes = 0; string_size += name_length + 1; } - } + else + { + long filepos; + bfd_byte buf[2]; + + /* This name should be written into the .debug section. For + some reason each name is preceded by a two byte length + and also followed by a null byte. FIXME: We assume that + the .debug section has already been created, and that it + is large enough. */ + if (debug_string_section == (asection *) NULL) + debug_string_section = bfd_get_section_by_name (abfd, ".debug"); + filepos = bfd_tell (abfd); + bfd_put_16 (abfd, name_length + 1, buf); + if (! bfd_set_section_contents (abfd, + debug_string_section, + (PTR) buf, + (file_ptr) debug_string_size, + (bfd_size_type) 2) + || ! bfd_set_section_contents (abfd, + debug_string_section, + (PTR) symbol->name, + (file_ptr) debug_string_size + 2, + (bfd_size_type) name_length + 1)) + abort (); + if (bfd_seek (abfd, filepos, SEEK_SET) != 0) + abort (); + native->u.syment._n._n_n._n_offset = debug_string_size + 2; + native->u.syment._n._n_n._n_zeroes = 0; + debug_string_size += name_length + 3; + } + } } -#define set_index(symbol, idx) ((symbol)->udata =(PTR) (idx)) +/* We need to keep track of the symbol index so that when we write out + the relocs we can get the index for a symbol. This method is a + hack. FIXME. */ -static unsigned int -DEFUN(coff_write_symbol,(abfd, symbol, native, written), -bfd *abfd AND -asymbol *symbol AND -combined_entry_type *native AND -unsigned int written) +#define set_index(symbol, idx) ((symbol)->udata = (PTR) (idx)) + +/* Write a symbol out to a COFF file. */ + +static boolean +coff_write_symbol (abfd, symbol, native, written) + bfd *abfd; + asymbol *symbol; + combined_entry_type *native; + unsigned int *written; { - unsigned int numaux = native->u.syment.n_numaux; - int type = native->u.syment.n_type; - int class = native->u.syment.n_sclass; + unsigned int numaux = native->u.syment.n_numaux; + int type = native->u.syment.n_type; + int class = native->u.syment.n_sclass; PTR buf; bfd_size_type symesz; - /* @@ bfd_debug_section isn't accessible outside this file, but we know - that C_FILE symbols belong there. So move them. */ + /* @@ bfd_debug_section isn't accessible outside this file, but we + know that C_FILE symbols belong there. So move them. */ if (native->u.syment.n_sclass == C_FILE) symbol->section = &bfd_debug_section; - if (symbol->section == &bfd_abs_section) - { - native->u.syment.n_scnum = N_ABS; - } + if (bfd_is_abs_section (symbol->section)) + { + native->u.syment.n_scnum = N_ABS; + } else if (symbol->section == &bfd_debug_section) - { - native->u.syment.n_scnum = N_DEBUG; - } - else if (symbol->section == &bfd_und_section) - { - native->u.syment.n_scnum = N_UNDEF; - } + { + native->u.syment.n_scnum = N_DEBUG; + } + else if (bfd_is_und_section (symbol->section)) + { + native->u.syment.n_scnum = N_UNDEF; + } else - { - native->u.syment.n_scnum = - symbol->section->output_section->target_index; - } + { + native->u.syment.n_scnum = + symbol->section->output_section->target_index; + } - - coff_fix_symbol_name(abfd, symbol, native); + coff_fix_symbol_name (abfd, symbol, native); symesz = bfd_coff_symesz (abfd); buf = bfd_alloc (abfd, symesz); - bfd_coff_swap_sym_out(abfd, &native->u.syment, buf); - bfd_write(buf, 1, symesz, abfd); + if (!buf) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + bfd_coff_swap_sym_out (abfd, &native->u.syment, buf); + if (bfd_write (buf, 1, symesz, abfd) != symesz) + return false; bfd_release (abfd, buf); if (native->u.syment.n_numaux > 0) @@ -636,221 +724,279 @@ unsigned int written) auxesz = bfd_coff_auxesz (abfd); buf = bfd_alloc (abfd, auxesz); + if (!buf) + { + bfd_set_error (bfd_error_no_memory); + return false; + } for (j = 0; j < native->u.syment.n_numaux; j++) { - bfd_coff_swap_aux_out(abfd, - &((native + j + 1)->u.auxent), - type, - class, - buf); - bfd_write(buf, 1, auxesz, abfd); + bfd_coff_swap_aux_out (abfd, + &((native + j + 1)->u.auxent), + type, + class, + j, + native->u.syment.n_numaux, + buf); + if (bfd_write (buf, 1, auxesz, abfd)!= auxesz) + return false; } bfd_release (abfd, buf); } - /* - Reuse somewhere in the symbol to keep the index - */ - set_index(symbol, written); - return written + 1 + numaux; + + /* Store the index for use when we write out the relocs. */ + set_index (symbol, *written); + + *written += numaux + 1; + return true; } +/* Write out a symbol to a COFF file that does not come from a COFF + file originally. This symbol may have been created by the linker, + or we may be linking a non COFF file to a COFF file. */ -static unsigned int -DEFUN(coff_write_alien_symbol,(abfd, symbol, written), - bfd *abfd AND - asymbol *symbol AND - unsigned int written) +static boolean +coff_write_alien_symbol (abfd, symbol, written) + bfd *abfd; + asymbol *symbol; + unsigned int *written; { - /* - This symbol has been created by the loader, or come from a non - coff format. It has no native element to inherit, make our - own - */ combined_entry_type *native; combined_entry_type dummy; + native = &dummy; native->u.syment.n_type = T_NULL; native->u.syment.n_flags = 0; - if (symbol->section == &bfd_und_section) - { - native->u.syment.n_scnum = N_UNDEF; - native->u.syment.n_value = symbol->value; + if (bfd_is_und_section (symbol->section)) + { + native->u.syment.n_scnum = N_UNDEF; + native->u.syment.n_value = symbol->value; } else if (bfd_is_com_section (symbol->section)) - { - native->u.syment.n_scnum = N_UNDEF; - native->u.syment.n_value = symbol->value; - - } - - else if (symbol->flags & BSF_DEBUGGING) { - /* - remove name so it doesn't take up any space - */ + { + native->u.syment.n_scnum = N_UNDEF; + native->u.syment.n_value = symbol->value; + } + else if (symbol->flags & BSF_DEBUGGING) + { + /* Remove the symbol name so that it does not take up any space. + COFF won't know what to do with it anyhow. */ symbol->name = ""; } - else { - native->u.syment.n_scnum = symbol->section->output_section->target_index; - native->u.syment.n_value = symbol->value + - symbol->section->output_section->vma + - symbol->section->output_offset; - /* Copy the any flags from the the file hdr into the symbol */ - { - coff_symbol_type *c = coff_symbol_from(abfd, symbol); - if (c != (coff_symbol_type *)NULL) { - native->u.syment.n_flags = bfd_asymbol_bfd(&c->symbol)->flags; - } - } - } - - native->u.syment.n_type = 0; - if (symbol->flags & BSF_LOCAL) - native->u.syment.n_sclass = C_STAT; else - native->u.syment.n_sclass = C_EXT; - native->u.syment.n_numaux = 0; + { + native->u.syment.n_scnum = + symbol->section->output_section->target_index; + native->u.syment.n_value = (symbol->value + + symbol->section->output_section->vma + + symbol->section->output_offset); - return coff_write_symbol(abfd, symbol, native, written); + /* Copy the any flags from the the file header into the symbol. + FIXME: Why? */ + { + coff_symbol_type *c = coff_symbol_from (abfd, symbol); + if (c != (coff_symbol_type *) NULL) + native->u.syment.n_flags = bfd_asymbol_bfd (&c->symbol)->flags; + } + } + + native->u.syment.n_type = 0; + if (symbol->flags & BSF_LOCAL) + native->u.syment.n_sclass = C_STAT; + else + native->u.syment.n_sclass = C_EXT; + native->u.syment.n_numaux = 0; + + return coff_write_symbol (abfd, symbol, native, written); } -static unsigned int -DEFUN(coff_write_native_symbol,(abfd, symbol, written), -bfd *abfd AND -coff_symbol_type *symbol AND -unsigned int written) +/* Write a native symbol to a COFF file. */ + +static boolean +coff_write_native_symbol (abfd, symbol, written) + bfd *abfd; + coff_symbol_type *symbol; + unsigned int *written; { - /* - Does this symbol have an ascociated line number - if so then - make it remember this symbol index. Also tag the auxent of - this symbol to point to the right place in the lineno table - */ combined_entry_type *native = symbol->native; + alent *lineno = symbol->lineno; - alent *lineno = symbol->lineno; + /* If this symbol has an associated line number, we must store the + symbol index in the line number field. We also tag the auxent to + point to the right place in the lineno table. */ + if (lineno && !symbol->done_lineno) + { + unsigned int count = 0; + lineno[count].u.offset = *written; + if (native->u.syment.n_numaux) + { + union internal_auxent *a = &((native+1)->u.auxent); - if (lineno && !symbol->done_lineno) { - unsigned int count = 0; - lineno[count].u.offset = written; - if (native->u.syment.n_numaux) { - union internal_auxent *a = &((native+1)->u.auxent); + a->x_sym.x_fcnary.x_fcn.x_lnnoptr = + symbol->symbol.section->output_section->moving_line_filepos; + } - a->x_sym.x_fcnary.x_fcn.x_lnnoptr = - symbol->symbol.section->output_section->moving_line_filepos; - } - /* - And count and relocate all other linenumbers - */ - - count++; - while (lineno[count].line_number) { -#if 0 -/* 13 april 92. sac -I've been told this, but still need proof: -> The second bug is also in `bfd/coffcode.h'. This bug causes the linker to screw -> up the pc-relocations for all the line numbers in COFF code. This bug isn't -> only specific to A29K implementations, but affects all systems using COFF -> format binaries. Note that in COFF object files, the line number core offsets -> output by the assembler are relative to the start of each procedure, not -> to the start of the .text section. This patch relocates the line numbers -> relative to the `native->u.syment.n_value' instead of the section virtual -> address. modular!olson@cs.arizona.edu (Jon Olson) -*/ - lineno[count].u.offset += native->u.syment.n_value; - -#else - lineno[count].u.offset += - symbol->symbol.section->output_section->vma + - symbol->symbol.section->output_offset; -#endif + /* Count and relocate all other linenumbers. */ count++; - } - symbol->done_lineno = true; + while (lineno[count].line_number != 0) + { +#if 0 + /* 13 april 92. sac + I've been told this, but still need proof: + > The second bug is also in `bfd/coffcode.h'. This bug + > causes the linker to screw up the pc-relocations for + > all the line numbers in COFF code. This bug isn't only + > specific to A29K implementations, but affects all + > systems using COFF format binaries. Note that in COFF + > object files, the line number core offsets output by + > the assembler are relative to the start of each + > procedure, not to the start of the .text section. This + > patch relocates the line numbers relative to the + > `native->u.syment.n_value' instead of the section + > virtual address. + > modular!olson@cs.arizona.edu (Jon Olson) + */ + lineno[count].u.offset += native->u.syment.n_value; +#else + lineno[count].u.offset += + (symbol->symbol.section->output_section->vma + + symbol->symbol.section->output_offset); +#endif + count++; + } + symbol->done_lineno = true; - symbol->symbol.section->output_section->moving_line_filepos += - count * bfd_coff_linesz (abfd); - } - return coff_write_symbol(abfd, &( symbol->symbol), native,written); + symbol->symbol.section->output_section->moving_line_filepos += + count * bfd_coff_linesz (abfd); + } + + return coff_write_symbol (abfd, &(symbol->symbol), native, written); } -void -DEFUN(coff_write_symbols,(abfd), - bfd *abfd) -{ - unsigned int i; - unsigned int limit = bfd_get_symcount(abfd); - unsigned int written = 0; +/* Write out the COFF symbols. */ - asymbol **p; +boolean +coff_write_symbols (abfd) + bfd *abfd; +{ + unsigned int i; + unsigned int limit = bfd_get_symcount(abfd); + unsigned int written = 0; + asymbol **p; string_size = 0; - + debug_string_size = 0; /* Seek to the right place */ - bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET); + if (bfd_seek (abfd, obj_sym_filepos(abfd), SEEK_SET) != 0) + return false; /* Output all the symbols we have */ written = 0; for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) - { - asymbol *symbol = *p; - coff_symbol_type *c_symbol = coff_symbol_from(abfd, symbol); + { + asymbol *symbol = *p; + coff_symbol_type *c_symbol = coff_symbol_from (abfd, symbol); - if (c_symbol == (coff_symbol_type *) NULL || - c_symbol->native == (combined_entry_type *)NULL) - { - written = coff_write_alien_symbol(abfd, symbol, written); - } - else - { - written = coff_write_native_symbol(abfd, c_symbol, written); - } + if (c_symbol == (coff_symbol_type *) NULL + || c_symbol->native == (combined_entry_type *)NULL) + { + if (! coff_write_alien_symbol (abfd, symbol, &written)) + return false; + } + else + { + if (! coff_write_native_symbol (abfd, c_symbol, &written)) + return false; + } + } - } - - bfd_get_symcount(abfd) = written; + bfd_get_symcount (abfd) = written; /* Now write out strings */ if (string_size != 0) { - unsigned int size = string_size + 4; + unsigned int size = string_size + 4; bfd_byte buffer[4]; - bfd_h_put_32(abfd, size, buffer); - bfd_write((PTR) buffer, 1, sizeof(buffer), abfd); + bfd_h_put_32 (abfd, size, buffer); + if (bfd_write ((PTR) buffer, 1, sizeof (buffer), abfd) != sizeof (buffer)) + return false; for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) - { - asymbol *q = *p; - size_t name_length = strlen(q->name); - int maxlen; - coff_symbol_type* c_symbol = coff_symbol_from(abfd, q); - maxlen = ((c_symbol != NULL && c_symbol->native != NULL) && - (c_symbol->native->u.syment.n_sclass == C_FILE)) ? - FILNMLEN : SYMNMLEN; + { + asymbol *q = *p; + size_t name_length = strlen (q->name); + coff_symbol_type *c_symbol = coff_symbol_from (abfd, q); + size_t maxlen; - if (name_length > maxlen) { - bfd_write((PTR) (q->name), 1, name_length + 1, abfd); + /* Figure out whether the symbol name should go in the string + table. Symbol names that are short enough are stored + directly in the syment structure. File names permit a + different, longer, length in the syment structure. On + XCOFF, some symbol names are stored in the .debug section + rather than in the string table. */ + + if (c_symbol == NULL + || c_symbol->native == NULL) + { + /* This is not a COFF symbol, so it certainly is not a + file name, nor does it go in the .debug section. */ + maxlen = SYMNMLEN; } - } - } - else { - /* We would normally not write anything here, but we'll write - out 4 so that any stupid coff reader which tries to read - the string table even when there isn't one won't croak. */ - unsigned int size = 4; - bfd_byte buffer[4]; + else if (bfd_coff_symname_in_debug (abfd, + &c_symbol->native->u.syment)) + { + /* This symbol name is in the XCOFF .debug section. + Don't write it into the string table. */ + maxlen = name_length; + } + else if (c_symbol->native->u.syment.n_sclass == C_FILE) + maxlen = FILNMLEN; + else + maxlen = SYMNMLEN; - bfd_h_put_32 (abfd, size, buffer); - bfd_write((PTR) buffer, 1, sizeof (buffer), abfd); - } + if (name_length > maxlen) + { + if (bfd_write ((PTR) (q->name), 1, name_length + 1, abfd) + != name_length + 1) + return false; + } + } + } + else + { + /* We would normally not write anything here, but we'll write + out 4 so that any stupid coff reader which tries to read the + string table even when there isn't one won't croak. */ + unsigned int size = 4; + bfd_byte buffer[4]; + + bfd_h_put_32 (abfd, size, buffer); + if (bfd_write ((PTR) buffer, 1, 4, abfd) != 4) + return false; + } + + /* Make sure the .debug section was created to be the correct size. + We should create it ourselves on the fly, but we don't because + BFD won't let us write to any section until we know how large all + the sections are. We could still do it by making another pass + over the symbols. FIXME. */ + BFD_ASSERT (debug_string_size == 0 + || (debug_string_section != (asection *) NULL + && (BFD_ALIGN (debug_string_size, + 1 << debug_string_section->alignment_power) + == bfd_section_size (abfd, debug_string_section)))); + + return true; } -void -DEFUN(coff_write_linenumbers,(abfd), - bfd *abfd) +boolean +coff_write_linenumbers (abfd) + bfd *abfd; { asection *s; bfd_size_type linesz; @@ -858,10 +1004,16 @@ DEFUN(coff_write_linenumbers,(abfd), linesz = bfd_coff_linesz (abfd); buff = bfd_alloc (abfd, linesz); + if (!buff) + { + bfd_set_error (bfd_error_no_memory); + return false; + } for (s = abfd->sections; s != (asection *) NULL; s = s->next) { if (s->lineno_count) { asymbol **q = abfd->outsymbols; - bfd_seek(abfd, s->line_filepos, SEEK_SET); + if (bfd_seek(abfd, s->line_filepos, SEEK_SET) != 0) + return false; /* Find all the linenumbers in this section */ while (*q) { asymbol *p = *q; @@ -875,13 +1027,15 @@ DEFUN(coff_write_linenumbers,(abfd), out.l_lnno = 0; out.l_addr.l_symndx = l->u.offset; bfd_coff_swap_lineno_out(abfd, &out, buff); - bfd_write(buff, 1, linesz, abfd); + if (bfd_write(buff, 1, linesz, abfd) != linesz) + return false; l++; while (l->line_number) { out.l_lnno = l->line_number; out.l_addr.l_symndx = l->u.offset; bfd_coff_swap_lineno_out(abfd, &out, buff); - bfd_write(buff, 1, linesz, abfd); + if (bfd_write(buff, 1, linesz, abfd) != linesz) + return false; l++; } } @@ -891,12 +1045,14 @@ DEFUN(coff_write_linenumbers,(abfd), } } bfd_release (abfd, buff); + return true; } +/*ARGSUSED*/ alent * -DEFUN(coff_get_lineno,(ignore_abfd, symbol), - bfd *ignore_abfd AND - asymbol *symbol) +coff_get_lineno (ignore_abfd, symbol) + bfd *ignore_abfd; + asymbol *symbol; { return coffsymbol(symbol)->lineno; } @@ -922,6 +1078,11 @@ coff_section_symbol (abfd, name) }; struct foo *f; f = (struct foo *) bfd_alloc_by_size_t (abfd, sizeof (*f)); + if (!f) + { + bfd_set_error (bfd_error_no_error); + return NULL; + } memset ((char *) f, 0, sizeof (*f)); coff_symbol_from (abfd, sym)->native = csym = f->e; } @@ -945,12 +1106,12 @@ coff_section_symbol (abfd, name) pointers to syments. */ static void -DEFUN(coff_pointerize_aux,(abfd, table_base, type, class, auxent), -bfd *abfd AND -combined_entry_type *table_base AND -int type AND -int class AND -combined_entry_type *auxent) +coff_pointerize_aux (abfd, table_base, type, class, auxent) + bfd *abfd; + combined_entry_type *table_base; + int type; + int class; + combined_entry_type *auxent; { /* Don't bother if this is a file or a section */ if (class == C_STAT && type == T_NULL) return; @@ -974,8 +1135,8 @@ combined_entry_type *auxent) } static char * -DEFUN(build_string_table,(abfd), -bfd *abfd) +build_string_table (abfd) + bfd *abfd; { char string_table_size_buffer[4]; unsigned int string_table_size; @@ -985,21 +1146,17 @@ bfd *abfd) symbols === the symbol table size. */ if (bfd_read((char *) string_table_size_buffer, sizeof(string_table_size_buffer), - 1, abfd) != sizeof(string_table_size)) { - bfd_error = system_call_error; + 1, abfd) != sizeof(string_table_size)) return (NULL); - } /* on error */ string_table_size = bfd_h_get_32(abfd, (bfd_byte *) string_table_size_buffer); if ((string_table = (PTR) bfd_alloc(abfd, string_table_size -= 4)) == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (NULL); } /* on mallocation error */ - if (bfd_read(string_table, string_table_size, 1, abfd) != string_table_size) { - bfd_error = system_call_error; + if (bfd_read(string_table, string_table_size, 1, abfd) != string_table_size) return (NULL); - } return string_table; } @@ -1008,8 +1165,8 @@ bfd *abfd) we didn't want to go to the trouble until someone needed it. */ static char * -DEFUN(build_debug_section,(abfd), - bfd *abfd) +build_debug_section (abfd) + bfd *abfd; { char *debug_section; long position; @@ -1017,14 +1174,14 @@ DEFUN(build_debug_section,(abfd), asection *sect = bfd_get_section_by_name (abfd, ".debug"); if (!sect) { - bfd_error = no_debug_section; + bfd_set_error (bfd_error_no_debug_section); return NULL; } debug_section = (PTR) bfd_alloc (abfd, bfd_get_section_size_before_reloc (sect)); if (debug_section == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } @@ -1033,14 +1190,12 @@ DEFUN(build_debug_section,(abfd), Then read debug section and reset the file pointer. */ position = bfd_tell (abfd); - bfd_seek (abfd, sect->filepos, SEEK_SET); - if (bfd_read (debug_section, - bfd_get_section_size_before_reloc (sect), 1, abfd) - != bfd_get_section_size_before_reloc(sect)) { - bfd_error = system_call_error; + if (bfd_seek (abfd, sect->filepos, SEEK_SET) != 0 + || (bfd_read (debug_section, + bfd_get_section_size_before_reloc (sect), 1, abfd) + != bfd_get_section_size_before_reloc(sect)) + || bfd_seek (abfd, position, SEEK_SET) != 0) return NULL; - } - bfd_seek (abfd, position, SEEK_SET); return debug_section; } @@ -1049,10 +1204,10 @@ DEFUN(build_debug_section,(abfd), \0-terminated, but will not exceed 'maxlen' characters. The copy *will* be \0-terminated. */ static char * -DEFUN(copy_name,(abfd, name, maxlen), - bfd *abfd AND - char *name AND - int maxlen) +copy_name (abfd, name, maxlen) + bfd *abfd; + char *name; + int maxlen; { int len; char *newname; @@ -1064,7 +1219,7 @@ DEFUN(copy_name,(abfd, name, maxlen), } if ((newname = (PTR) bfd_alloc(abfd, len+1)) == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (NULL); } strncpy(newname, name, len); @@ -1078,8 +1233,8 @@ DEFUN(copy_name,(abfd, name, maxlen), terminated string. */ combined_entry_type * -DEFUN(coff_get_normalized_symtab,(abfd), -bfd *abfd) +coff_get_normalized_symtab (abfd) + bfd *abfd; { combined_entry_type *internal; combined_entry_type *internal_ptr; @@ -1098,22 +1253,30 @@ bfd *abfd) return obj_raw_syments(abfd); } if ((size = bfd_get_symcount(abfd) * sizeof(combined_entry_type)) == 0) { - bfd_error = no_symbols; + bfd_set_error (bfd_error_no_symbols); return (NULL); } internal = (combined_entry_type *)bfd_alloc(abfd, size); + if (!internal) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } internal_end = internal + bfd_get_symcount(abfd); symesz = bfd_coff_symesz (abfd); raw_size = bfd_get_symcount(abfd) * symesz; raw = bfd_alloc(abfd,raw_size); + if (!raw) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } if (bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET) == -1 - || bfd_read(raw, raw_size, 1, abfd) != raw_size) { - bfd_error = system_call_error; + || bfd_read(raw, raw_size, 1, abfd) != raw_size) return (NULL); - } /* mark the end of the symbols */ raw_end = (char *) raw + bfd_get_symcount(abfd) * symesz; /* @@ -1128,8 +1291,10 @@ bfd *abfd) unsigned int i; bfd_coff_swap_sym_in(abfd, (PTR)raw_src, (PTR)&internal_ptr->u.syment); + internal_ptr->fix_value = 0; internal_ptr->fix_tag = 0; internal_ptr->fix_end = 0; + internal_ptr->fix_scnlen = 0; symbol_ptr = internal_ptr; for (i = 0; @@ -1139,11 +1304,14 @@ bfd *abfd) internal_ptr++; raw_src += symesz; + internal_ptr->fix_value = 0; internal_ptr->fix_tag = 0; internal_ptr->fix_end = 0; + internal_ptr->fix_scnlen = 0; bfd_coff_swap_aux_in(abfd, (PTR) raw_src, symbol_ptr->u.syment.n_type, symbol_ptr->u.syment.n_sclass, + i, symbol_ptr->u.syment.n_numaux, &(internal_ptr->u.auxent)); /* Remember that bal entries arn't pointerized */ if (i != 1 || symbol_ptr->u.syment.n_sclass != C_LEAFPROC) @@ -1200,7 +1368,7 @@ bfd *abfd) } /* possible lengths of this string. */ if ((newstring = (PTR) bfd_alloc(abfd, ++i)) == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (NULL); } /* on error */ memset(newstring, 0, i); @@ -1208,6 +1376,8 @@ bfd *abfd) internal_ptr->u.syment._n._n_n._n_offset = (long int) newstring; internal_ptr->u.syment._n._n_n._n_zeroes = 0; } + else if (internal_ptr->u.syment._n._n_n._n_offset == 0) + internal_ptr->u.syment._n._n_n._n_offset = (long int) ""; else if (!bfd_coff_symname_in_debug(abfd, &internal_ptr->u.syment)) { /* Long name already. Point symbol at the string in the table. */ if (string_table == NULL) { @@ -1234,27 +1404,28 @@ bfd *abfd) return (internal); } /* coff_get_normalized_symtab() */ -unsigned int -DEFUN (coff_get_reloc_upper_bound, (abfd, asect), - bfd *abfd AND - sec_ptr asect) +long +coff_get_reloc_upper_bound (abfd, asect) + bfd *abfd; + sec_ptr asect; { if (bfd_get_format(abfd) != bfd_object) { - bfd_error = invalid_operation; - return 0; + bfd_set_error (bfd_error_invalid_operation); + return -1; } return (asect->reloc_count + 1) * sizeof(arelent *); } asymbol * -DEFUN (coff_make_empty_symbol, (abfd), - bfd *abfd) +coff_make_empty_symbol (abfd) + bfd *abfd; { coff_symbol_type *new = (coff_symbol_type *) bfd_alloc(abfd, sizeof(coff_symbol_type)); if (new == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (NULL); } /* on error */ + memset (new, 0, sizeof *new); new->symbol.section = 0; new->native = 0; new->lineno = (alent *) NULL; @@ -1273,11 +1444,16 @@ coff_bfd_make_debug_symbol (abfd, ptr, sz) { coff_symbol_type *new = (coff_symbol_type *) bfd_alloc(abfd, sizeof(coff_symbol_type)); if (new == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (NULL); } /* on error */ /* @@ This shouldn't be using a constant multiplier. */ new->native = (combined_entry_type *) bfd_zalloc (abfd, sizeof (combined_entry_type) * 10); + if (!new->native) + { + bfd_set_error (bfd_error_no_memory); + return (NULL); + } /* on error */ new->symbol.section = &bfd_debug_section; new->lineno = (alent *) NULL; new->done_lineno = false; @@ -1285,6 +1461,7 @@ coff_bfd_make_debug_symbol (abfd, ptr, sz) return &new->symbol; } +/*ARGSUSED*/ void coff_get_symbol_info (abfd, symbol, ret) bfd *abfd; @@ -1328,13 +1505,13 @@ coff_print_symbol (abfd, filep, symbol, how) fprintf (file,"[%3d]", combined - root); fprintf (file, - "(sc %2d)(fl 0x%02x)(ty %3x)(sc %3d) (nx %d) 0x%08x %s", + "(sc %2d)(fl 0x%02x)(ty %3x)(sc %3d) (nx %d) 0x%08lx %s", combined->u.syment.n_scnum, combined->u.syment.n_flags, combined->u.syment.n_type, combined->u.syment.n_sclass, combined->u.syment.n_numaux, - combined->u.syment.n_value, + (unsigned long) combined->u.syment.n_value, symbol->name); for (aux = 0; aux < combined->u.syment.n_numaux; aux++) @@ -1355,7 +1532,7 @@ coff_print_symbol (abfd, filep, symbol, how) break; default: - fprintf (file, "AUX lnno %d size 0x%x tagndx %d", + fprintf (file, "AUX lnno %d size 0x%x tagndx %ld", auxp->u.auxent.x_sym.x_misc.x_lnsz.x_lnno, auxp->u.auxent.x_sym.x_misc.x_lnsz.x_size, tagndx); @@ -1369,9 +1546,10 @@ coff_print_symbol (abfd, filep, symbol, how) l++; while (l->line_number) { - fprintf (file, "\n%4d : 0x%x", - l->line_number, - l->u.offset + symbol->section->vma); + fprintf (file, "\n%4d : 0x%lx", + l->line_number, + ((unsigned long) + (l->u.offset + symbol->section->vma))); l++; } } @@ -1392,21 +1570,17 @@ coff_print_symbol (abfd, filep, symbol, how) and return the name of the source file and the line nearest to the wanted location. */ +/*ARGSUSED*/ boolean -DEFUN(coff_find_nearest_line,(abfd, - section, - ignore_symbols, - offset, - filename_ptr, - functionname_ptr, - line_ptr), - bfd *abfd AND - asection *section AND - asymbol **ignore_symbols AND - bfd_vma offset AND - CONST char **filename_ptr AND - CONST char **functionname_ptr AND - unsigned int *line_ptr) +coff_find_nearest_line (abfd, section, ignore_symbols, offset, filename_ptr, + functionname_ptr, line_ptr) + bfd *abfd; + asection *section; + asymbol **ignore_symbols; + bfd_vma offset; + CONST char **filename_ptr; + CONST char **functionname_ptr; + unsigned int *line_ptr; { static bfd *cache_abfd; static asection *cache_section; @@ -1501,9 +1675,9 @@ DEFUN(coff_find_nearest_line,(abfd, } int -DEFUN(coff_sizeof_headers,(abfd, reloc), - bfd *abfd AND - boolean reloc) +coff_sizeof_headers (abfd, reloc) + bfd *abfd; + boolean reloc; { size_t size; diff --git a/gnu/usr.bin/gdb/bfd/core.c b/gnu/usr.bin/gdb/bfd/core.c index c428775fbf3f..5d88a494c36a 100644 --- a/gnu/usr.bin/gdb/bfd/core.c +++ b/gnu/usr.bin/gdb/bfd/core.c @@ -1,5 +1,5 @@ /* Core file generic interface routines for BFD. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -23,7 +23,7 @@ SECTION Core files DESCRIPTION - Buff output this facinating topic + These are functions pertaining to core files. */ #include "bfd.h" @@ -36,20 +36,20 @@ FUNCTION bfd_core_file_failing_command SYNOPSIS - CONST char *bfd_core_file_failing_command(bfd *); + CONST char *bfd_core_file_failing_command(bfd *abfd); DESCRIPTION - Returns a read-only string explaining what program was running - when it failed and produced the core file being read + Return a read-only string explaining which program was running + when it failed and produced the core file @var{abfd}. */ CONST char * -DEFUN(bfd_core_file_failing_command,(abfd), - bfd *abfd) +bfd_core_file_failing_command (abfd) + bfd *abfd; { if (abfd->format != bfd_core) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return NULL; } return BFD_SEND (abfd, _core_file_failing_command, (abfd)); @@ -60,11 +60,11 @@ FUNCTION bfd_core_file_failing_signal SYNOPSIS - int bfd_core_file_failing_signal(bfd *); + int bfd_core_file_failing_signal(bfd *abfd); DESCRIPTION Returns the signal number which caused the core dump which - generated the file the BFD is attached to. + generated the file the BFD @var{abfd} is attached to. */ int @@ -72,7 +72,7 @@ bfd_core_file_failing_signal (abfd) bfd *abfd; { if (abfd->format != bfd_core) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return 0; } return BFD_SEND (abfd, _core_file_failing_signal, (abfd)); @@ -88,16 +88,16 @@ SYNOPSIS (bfd *core_bfd, bfd *exec_bfd); DESCRIPTION - Returns <> if the core file attached to @var{core_bfd} + Return <> if the core file attached to @var{core_bfd} was generated by a run of the executable file attached to - @var{exec_bfd}, or else <>. + @var{exec_bfd}, <> otherwise. */ boolean core_file_matches_executable_p (core_bfd, exec_bfd) bfd *core_bfd, *exec_bfd; { if ((core_bfd->format != bfd_core) || (exec_bfd->format != bfd_object)) { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return false; } diff --git a/gnu/usr.bin/gdb/bfd/cpu-i386.c b/gnu/usr.bin/gdb/bfd/cpu-i386.c index b4afdb2392bb..3a8214ff3f4e 100644 --- a/gnu/usr.bin/gdb/bfd/cpu-i386.c +++ b/gnu/usr.bin/gdb/bfd/cpu-i386.c @@ -37,7 +37,8 @@ static bfd_arch_info_type arch_info_struct = 0, }; -void DEFUN_VOID(bfd_i386_arch) +void +bfd_i386_arch () { bfd_arch_linkin(&arch_info_struct); } diff --git a/gnu/usr.bin/gdb/bfd/ctor.c b/gnu/usr.bin/gdb/bfd/ctor.c index adc69195ff6a..8a6e4e4e3393 100644 --- a/gnu/usr.bin/gdb/bfd/ctor.c +++ b/gnu/usr.bin/gdb/bfd/ctor.c @@ -1,5 +1,5 @@ /* BFD library support routines for constructors - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Hacked by Steve Chamberlain of Cygnus Support. With some help from Judy Chamberlain too. @@ -25,27 +25,27 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION Constructors - Classes in C++ have `constructors' and `destructors'. These + Classes in C++ have @dfn{constructors} and @dfn{destructors}. These are functions which are called automatically by the language whenever data of a class is created or destroyed. Class data - which is static data may also be have a type which requires - `construction', the contructor must be called before the data + which is static may also be have a type which requires + `construction'; the contructor must be called before the data can be referenced, so the contructor must be called before the program begins. The common solution to this problem is for the compiler to - call a magic function as the first statement <
>. - This magic function, (often called <<__main>>) runs around + call a magic function as the first statement before <
>. + This magic function (often called <<__main>>) runs around calling the constructors for all the things needing it. - With COFF the compile has a bargain with the linker et al. - All constructors are given strange names, for example + With COFF, the compiler has a bargain with the linker et al. + All constructors are given strange names; for example, <<__GLOBAL__$I$foo>> might be the label of a contructor for the class @var{foo}. The solution on unfortunate systems - (most system V machines) is to perform a partial link on all + (most System V machines) is to perform a partial link on all the <<.o>> files, do an <> on the result, run <> or some such over the result looking for strange <<__GLOBAL__$>> - symbols, generate a C program from this, compile it and link + symbols, generate a C program from this, compile it, and link with the partially linked input. This process is usually called <>. @@ -54,10 +54,10 @@ SECTION from the compiler with a special stab code saying that they are constructors, and the linker can deal with them directly. - BFD allows applications (ie the linker) to deal with + BFD allows applications (i.e., the linker) to deal with constructor information independently of their external - implimentation by providing a set of entry points for the - indiviual object back ends to call which maintains a database + implementation by providing a set of entry points for the + indiviual object back ends to call to maintain a database of the contructor information. The application can interrogate the database to find out what it wants. The construction data essential for the linker to be able to @@ -71,15 +71,15 @@ SECTION The type of symbol, i.e., is it a constructor, a destructor or something else someone dreamed up to make our lives difficult. - This module takes this information and then builds extra - sections attached to the bfds which own the entry points. It + The constructor module takes this information and builds extra + sections attached to the BFDs which own the entry points. It creates these sections as if they were tables of pointers to the entry points, and builds relocation entries to go with them so that the tables can be relocated along with the data they reference. These sections are marked with a special bit - (<>) which the linker notices and do with + (<>), which the linker notices and does with what it wants. */ @@ -95,28 +95,30 @@ INTERNAL_FUNCTION bfd_constructor_entry SYNOPSIS - void bfd_constructor_entry(bfd *abfd, + boolean bfd_constructor_entry(bfd *abfd, asymbol **symbol_ptr_ptr, CONST char*type); DESCRIPTION - This function is called with an a symbol describing the - function to be called, an string which descibes the xtor type, - e.g., something like "CTOR" or "DTOR" would be fine. And the bfd - which owns the function. Its duty is to create a section - called "CTOR" or "DTOR" or whatever if the bfd doesn't already + @var{symbol_ptr_ptr} describes the + function to be called; @var{type} descibes the xtor type, + e.g., something like "CTOR" or "DTOR" would be fine. @var{abfd} + is the BFD which owns the function. Create a section + called "CTOR" or "DTOR" or whatever if the BFD doesn't already have one, and grow a relocation table for the entry points as they accumulate. + Return <> if successful, <> if out of memory. + */ -void DEFUN(bfd_constructor_entry,(abfd, symbol_ptr_ptr, type), - bfd *abfd AND - asymbol **symbol_ptr_ptr AND - CONST char *type) - +boolean +bfd_constructor_entry (abfd, symbol_ptr_ptr, type) + bfd *abfd; + asymbol **symbol_ptr_ptr; + CONST char *type; { /* Look up the section we're using to store the table in */ asection *rel_section = bfd_get_section_by_name (abfd, type); @@ -131,6 +133,11 @@ void DEFUN(bfd_constructor_entry,(abfd, symbol_ptr_ptr, type), { arelent_chain *reloc = (arelent_chain *)bfd_alloc(abfd, sizeof(arelent_chain)); + if (!reloc) + { + bfd_set_error (bfd_error_no_memory); + return false; + } /* reloc->relent.section = (asection *)NULL;*/ reloc->relent.addend = 0; @@ -144,5 +151,5 @@ void DEFUN(bfd_constructor_entry,(abfd, symbol_ptr_ptr, type), rel_section->_cooked_size += sizeof(int *); rel_section->reloc_count++; } - + return true; } diff --git a/gnu/usr.bin/gdb/bfd/ecoff.c b/gnu/usr.bin/gdb/bfd/ecoff.c index e3b7c937aa05..9bf5050aad4f 100644 --- a/gnu/usr.bin/gdb/bfd/ecoff.c +++ b/gnu/usr.bin/gdb/bfd/ecoff.c @@ -21,8 +21,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" -#include "seclet.h" #include "aout/ar.h" #include "aout/ranlib.h" @@ -45,30 +45,24 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Prototypes for static functions. */ static int ecoff_get_magic PARAMS ((bfd *abfd)); -static void ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym, +static long ecoff_sec_to_styp_flags PARAMS ((const char *name, + flagword flags)); +static boolean ecoff_slurp_symbolic_header PARAMS ((bfd *abfd)); +static boolean ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym, asymbol *asym, int ext, asymbol **indirect_ptr_ptr)); -static void ecoff_emit_aggregate PARAMS ((bfd *abfd, char *string, +static void ecoff_emit_aggregate PARAMS ((bfd *abfd, FDR *fdr, + char *string, RNDXR *rndx, long isym, - CONST char *which)); -static char *ecoff_type_to_string PARAMS ((bfd *abfd, union aux_ext *aux_ptr, - unsigned int indx, int bigendian)); + const char *which)); +static char *ecoff_type_to_string PARAMS ((bfd *abfd, FDR *fdr, + unsigned int indx)); static boolean ecoff_slurp_reloc_table PARAMS ((bfd *abfd, asection *section, asymbol **symbols)); -static void ecoff_clear_output_flags PARAMS ((bfd *abfd)); -static boolean ecoff_rel PARAMS ((bfd *output_bfd, bfd_seclet_type *seclet, - asection *output_section, PTR data, - boolean relocateable)); -static boolean ecoff_dump_seclet PARAMS ((bfd *abfd, bfd_seclet_type *seclet, - asection *section, PTR data, - boolean relocateable)); -static long ecoff_add_string PARAMS ((bfd *output_bfd, FDR *fdr, - CONST char *string, boolean external)); -static boolean ecoff_get_debug PARAMS ((bfd *output_bfd, - bfd_seclet_type *seclet, - asection *section, - boolean relocateable)); static void ecoff_compute_section_file_positions PARAMS ((bfd *abfd)); +static bfd_size_type ecoff_compute_reloc_file_positions PARAMS ((bfd *abfd)); +static boolean ecoff_get_extr PARAMS ((asymbol *, EXTR *)); +static void ecoff_set_index PARAMS ((asymbol *, bfd_size_type)); static unsigned int ecoff_armap_hash PARAMS ((CONST char *s, unsigned int *rehash, unsigned int size, @@ -81,22 +75,17 @@ static asection bfd_debug_section = { "*DEBUG*" }; /* Create an ECOFF object. */ boolean -ecoff_mkobject (abfd) +_bfd_ecoff_mkobject (abfd) bfd *abfd; { abfd->tdata.ecoff_obj_data = ((struct ecoff_tdata *) bfd_zalloc (abfd, sizeof (ecoff_data_type))); if (abfd->tdata.ecoff_obj_data == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } - /* Always create a .scommon section for every BFD. This is a hack so - that the linker has something to attach scSCommon symbols to. */ - if (bfd_make_section (abfd, SCOMMON) == NULL) - return false; - return true; } @@ -104,7 +93,7 @@ ecoff_mkobject (abfd) specific information. */ PTR -ecoff_mkobject_hook (abfd, filehdr, aouthdr) +_bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr) bfd *abfd; PTR filehdr; PTR aouthdr; @@ -112,22 +101,14 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr) struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr; ecoff_data_type *ecoff; - asection *regsec; - if (ecoff_mkobject (abfd) == false) + if (_bfd_ecoff_mkobject (abfd) == false) return NULL; ecoff = ecoff_data (abfd); ecoff->gp_size = 8; ecoff->sym_filepos = internal_f->f_symptr; - /* Create the .reginfo section to give programs outside BFD a way to - see the information stored in the a.out header. See the comment - in coff/ecoff.h. */ - regsec = bfd_make_section (abfd, REGINFO); - if (regsec == NULL) - return NULL; - if (internal_a != (struct internal_aouthdr *) NULL) { int i; @@ -154,8 +135,9 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr) /* This is a hook needed by SCO COFF, but we have nothing to do. */ +/*ARGSUSED*/ asection * -ecoff_make_section_hook (abfd, name) +_bfd_ecoff_make_section_hook (abfd, name) bfd *abfd; char *name; { @@ -165,11 +147,19 @@ ecoff_make_section_hook (abfd, name) /* Initialize a new section. */ boolean -ecoff_new_section_hook (abfd, section) +_bfd_ecoff_new_section_hook (abfd, section) bfd *abfd; asection *section; { - section->alignment_power = abfd->xvec->align_power_min; + /* For the .pdata section, which has a special meaning on the Alpha, + we set the alignment to 8. We correct this later in + ecoff_compute_section_file_positions. We do this hackery because + we need to know the exact unaligned size of the .pdata section in + order to set the lnnoptr field correctly. */ + if (strcmp (section->name, _PDATA) == 0) + section->alignment_power = 3; + else + section->alignment_power = abfd->xvec->align_power_min; if (strcmp (section->name, _TEXT) == 0) section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC; @@ -183,10 +173,10 @@ ecoff_new_section_hook (abfd, section) else if (strcmp (section->name, _BSS) == 0 || strcmp (section->name, _SBSS) == 0) section->flags |= SEC_ALLOC; - else if (strcmp (section->name, REGINFO) == 0) + else if (strcmp (section->name, _LIB) == 0) { - section->flags |= SEC_HAS_CONTENTS | SEC_NEVER_LOAD; - section->_raw_size = sizeof (struct ecoff_reginfo); + /* An Irix 4 shared libary. */ + section->flags |= SEC_COFF_SHARED_LIBRARY; } /* Probably any other section name is SEC_NEVER_LOAD, but I'm @@ -202,7 +192,7 @@ ecoff_new_section_hook (abfd, section) for each target, but there aren't all that many ECOFF targets. */ boolean -ecoff_set_arch_mach_hook (abfd, filehdr) +_bfd_ecoff_set_arch_mach_hook (abfd, filehdr) bfd *abfd; PTR filehdr; { @@ -248,7 +238,7 @@ ecoff_set_arch_mach_hook (abfd, filehdr) } /* Get the magic number to use based on the architecture and machine. - This is the inverse of ecoff_set_arch_mach_hook, above. */ + This is the inverse of _bfd_ecoff_set_arch_mach_hook, above. */ static int ecoff_get_magic (abfd) @@ -292,9 +282,9 @@ ecoff_get_magic (abfd) /* Get the section s_flags to use for a section. */ -long +static long ecoff_sec_to_styp_flags (name, flags) - CONST char *name; + const char *name; flagword flags; { long styp; @@ -309,6 +299,8 @@ ecoff_sec_to_styp_flags (name, flags) styp = STYP_SDATA; else if (strcmp (name, _RDATA) == 0) styp = STYP_RDATA; + else if (strcmp (name, _LITA) == 0) + styp = STYP_LITA; else if (strcmp (name, _LIT8) == 0) styp = STYP_LIT8; else if (strcmp (name, _LIT4) == 0) @@ -321,6 +313,12 @@ ecoff_sec_to_styp_flags (name, flags) styp = STYP_ECOFF_INIT; else if (strcmp (name, _FINI) == 0) styp = STYP_ECOFF_FINI; + else if (strcmp (name, _PDATA) == 0) + styp = STYP_PDATA; + else if (strcmp (name, _XDATA) == 0) + styp = STYP_XDATA; + else if (strcmp (name, _LIB) == 0) + styp = STYP_ECOFF_LIB; else if (flags & SEC_CODE) styp = STYP_TEXT; else if (flags & SEC_DATA) @@ -340,8 +338,9 @@ ecoff_sec_to_styp_flags (name, flags) /* Get the BFD flags to use for a section. */ +/*ARGSUSED*/ flagword -ecoff_styp_to_sec_flags (abfd, hdr) +_bfd_ecoff_styp_to_sec_flags (abfd, hdr) bfd *abfd; PTR hdr; { @@ -359,19 +358,22 @@ ecoff_styp_to_sec_flags (abfd, hdr) || (styp_flags & STYP_ECOFF_FINI)) { if (sec_flags & SEC_NEVER_LOAD) - sec_flags |= SEC_CODE | SEC_SHARED_LIBRARY; + sec_flags |= SEC_CODE | SEC_COFF_SHARED_LIBRARY; else sec_flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC; } else if ((styp_flags & STYP_DATA) || (styp_flags & STYP_RDATA) - || (styp_flags & STYP_SDATA)) + || (styp_flags & STYP_SDATA) + || styp_flags == STYP_PDATA + || styp_flags == STYP_XDATA) { if (sec_flags & SEC_NEVER_LOAD) - sec_flags |= SEC_DATA | SEC_SHARED_LIBRARY; + sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY; else sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC; - if (styp_flags & STYP_RDATA) + if ((styp_flags & STYP_RDATA) + || styp_flags == STYP_PDATA) sec_flags |= SEC_READONLY; } else if ((styp_flags & STYP_BSS) @@ -379,15 +381,20 @@ ecoff_styp_to_sec_flags (abfd, hdr) { sec_flags |= SEC_ALLOC; } - else if (styp_flags & STYP_INFO) + else if ((styp_flags & STYP_INFO) || styp_flags == STYP_COMMENT) { sec_flags |= SEC_NEVER_LOAD; } - else if ((styp_flags & STYP_LIT8) + else if ((styp_flags & STYP_LITA) + || (styp_flags & STYP_LIT8) || (styp_flags & STYP_LIT4)) { sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY; } + else if (styp_flags & STYP_ECOFF_LIB) + { + sec_flags |= SEC_COFF_SHARED_LIBRARY; + } else { sec_flags |= SEC_ALLOC | SEC_LOAD; @@ -405,9 +412,9 @@ ecoff_styp_to_sec_flags (abfd, hdr) info comes from the file header record (fh-fBigendian). */ void -ecoff_swap_tir_in (bigend, ext_copy, intern) +_bfd_ecoff_swap_tir_in (bigend, ext_copy, intern) int bigend; - struct tir_ext *ext_copy; + const struct tir_ext *ext_copy; TIR *intern; { struct tir_ext ext[1]; @@ -462,9 +469,9 @@ ecoff_swap_tir_in (bigend, ext_copy, intern) info comes from the file header record (fh-fBigendian). */ void -ecoff_swap_tir_out (bigend, intern_copy, ext) +_bfd_ecoff_swap_tir_out (bigend, intern_copy, ext) int bigend; - TIR *intern_copy; + const TIR *intern_copy; struct tir_ext *ext; { TIR intern[1]; @@ -518,9 +525,9 @@ ecoff_swap_tir_out (bigend, intern_copy, ext) big-endian or little-endian format.*/ void -ecoff_swap_rndx_in (bigend, ext_copy, intern) +_bfd_ecoff_swap_rndx_in (bigend, ext_copy, intern) int bigend; - struct rndx_ext *ext_copy; + const struct rndx_ext *ext_copy; RNDXR *intern; { struct rndx_ext ext[1]; @@ -543,7 +550,8 @@ ecoff_swap_rndx_in (bigend, ext_copy, intern) intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_LITTLE) >> RNDX_BITS1_INDEX_SH_LITTLE) | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_LITTLE) - | (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_LITTLE); + | ((unsigned int) ext->r_bits[3] + << RNDX_BITS3_INDEX_SH_LEFT_LITTLE); } #ifdef TEST @@ -556,9 +564,9 @@ ecoff_swap_rndx_in (bigend, ext_copy, intern) big-endian or little-endian format.*/ void -ecoff_swap_rndx_out (bigend, intern_copy, ext) +_bfd_ecoff_swap_rndx_out (bigend, intern_copy, ext) int bigend; - RNDXR *intern_copy; + const RNDXR *intern_copy; struct rndx_ext *ext; { RNDXR intern[1]; @@ -590,15 +598,86 @@ ecoff_swap_rndx_out (bigend, intern_copy, ext) #endif } -/* Read in and swap the important symbolic information for an ECOFF - object file. This is called by gdb. */ +/* Read in the symbolic header for an ECOFF object file. */ -boolean -ecoff_slurp_symbolic_info (abfd) +static boolean +ecoff_slurp_symbolic_header (abfd) bfd *abfd; { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); bfd_size_type external_hdr_size; + PTR raw = NULL; + HDRR *internal_symhdr; + + /* See if we've already read it in. */ + if (ecoff_data (abfd)->debug_info.symbolic_header.magic == + backend->debug_swap.sym_magic) + return true; + + /* See whether there is a symbolic header. */ + if (ecoff_data (abfd)->sym_filepos == 0) + { + bfd_get_symcount (abfd) = 0; + return true; + } + + /* At this point bfd_get_symcount (abfd) holds the number of symbols + as read from the file header, but on ECOFF this is always the + size of the symbolic information header. It would be cleaner to + handle this when we first read the file in coffgen.c. */ + external_hdr_size = backend->debug_swap.external_hdr_size; + if (bfd_get_symcount (abfd) != external_hdr_size) + { + bfd_set_error (bfd_error_bad_value); + return false; + } + + /* Read the symbolic information header. */ + raw = (PTR) malloc ((size_t) external_hdr_size); + if (raw == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) == -1 + || (bfd_read (raw, external_hdr_size, 1, abfd) + != external_hdr_size)) + goto error_return; + internal_symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; + (*backend->debug_swap.swap_hdr_in) (abfd, raw, internal_symhdr); + + if (internal_symhdr->magic != backend->debug_swap.sym_magic) + { + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + + /* Now we can get the correct number of symbols. */ + bfd_get_symcount (abfd) = (internal_symhdr->isymMax + + internal_symhdr->iextMax); + + if (raw != NULL) + free (raw); + return true; + error_return: + if (raw != NULL) + free (raw); + return false; +} + +/* Read in and swap the important symbolic information for an ECOFF + object file. This is called by gdb via the read_debug_info entry + point in the backend structure. */ + +/*ARGSUSED*/ +boolean +_bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug) + bfd *abfd; + asection *ignore; + struct ecoff_debug_info *debug; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); HDRR *internal_symhdr; bfd_size_type raw_base; bfd_size_type raw_size; @@ -610,6 +689,8 @@ ecoff_slurp_symbolic_info (abfd) bfd_size_type raw_end; bfd_size_type cb_end; + BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info); + /* Check whether we've already gotten it, and whether there's any to get. */ if (ecoff_data (abfd)->raw_syments != (PTR) NULL) @@ -620,41 +701,14 @@ ecoff_slurp_symbolic_info (abfd) return true; } - /* At this point bfd_get_symcount (abfd) holds the number of symbols - as read from the file header, but on ECOFF this is always the - size of the symbolic information header. It would be cleaner to - handle this when we first read the file in coffgen.c. */ - external_hdr_size = backend->external_hdr_size; - if (bfd_get_symcount (abfd) != external_hdr_size) - { - bfd_error = bad_value; - return false; - } + if (! ecoff_slurp_symbolic_header (abfd)) + return false; - /* Read the symbolic information header. */ - raw = (PTR) alloca (external_hdr_size); - if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) == -1 - || (bfd_read (raw, external_hdr_size, 1, abfd) - != external_hdr_size)) - { - bfd_error = system_call_error; - return false; - } - internal_symhdr = &ecoff_data (abfd)->symbolic_header; - (*backend->swap_hdr_in) (abfd, raw, internal_symhdr); - - if (internal_symhdr->magic != backend->sym_magic) - { - bfd_error = bad_value; - return false; - } - - /* Now we can get the correct number of symbols. */ - bfd_get_symcount (abfd) = (internal_symhdr->isymMax - + internal_symhdr->iextMax); + internal_symhdr = &debug->symbolic_header; /* Read all the symbolic information at once. */ - raw_base = ecoff_data (abfd)->sym_filepos + external_hdr_size; + raw_base = (ecoff_data (abfd)->sym_filepos + + backend->debug_swap.external_hdr_size); /* Alpha ecoff makes the determination of raw_size difficult. It has an undocumented debug data section between the symhdr and the first @@ -670,16 +724,16 @@ ecoff_slurp_symbolic_info (abfd) raw_end = cb_end UPDATE_RAW_END (cbLineOffset, cbLine, sizeof (unsigned char)); - UPDATE_RAW_END (cbDnOffset, idnMax, backend->external_dnr_size); - UPDATE_RAW_END (cbPdOffset, ipdMax, backend->external_pdr_size); - UPDATE_RAW_END (cbSymOffset, isymMax, backend->external_sym_size); - UPDATE_RAW_END (cbOptOffset, ioptMax, backend->external_opt_size); + UPDATE_RAW_END (cbDnOffset, idnMax, backend->debug_swap.external_dnr_size); + UPDATE_RAW_END (cbPdOffset, ipdMax, backend->debug_swap.external_pdr_size); + UPDATE_RAW_END (cbSymOffset, isymMax, backend->debug_swap.external_sym_size); + UPDATE_RAW_END (cbOptOffset, ioptMax, backend->debug_swap.external_opt_size); UPDATE_RAW_END (cbAuxOffset, iauxMax, sizeof (union aux_ext)); UPDATE_RAW_END (cbSsOffset, issMax, sizeof (char)); UPDATE_RAW_END (cbSsExtOffset, issExtMax, sizeof (char)); - UPDATE_RAW_END (cbFdOffset, ifdMax, backend->external_fdr_size); - UPDATE_RAW_END (cbRfdOffset, crfd, backend->external_rfd_size); - UPDATE_RAW_END (cbExtOffset, iextMax, backend->external_ext_size); + UPDATE_RAW_END (cbFdOffset, ifdMax, backend->debug_swap.external_fdr_size); + UPDATE_RAW_END (cbRfdOffset, crfd, backend->debug_swap.external_rfd_size); + UPDATE_RAW_END (cbExtOffset, iextMax, backend->debug_swap.external_ext_size); #undef UPDATE_RAW_END @@ -692,27 +746,29 @@ ecoff_slurp_symbolic_info (abfd) raw = (PTR) bfd_alloc (abfd, raw_size); if (raw == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } - if (bfd_read (raw, raw_size, 1, abfd) != raw_size) + if (bfd_seek (abfd, + (ecoff_data (abfd)->sym_filepos + + backend->debug_swap.external_hdr_size), + SEEK_SET) != 0 + || bfd_read (raw, raw_size, 1, abfd) != raw_size) { - bfd_error = system_call_error; bfd_release (abfd, raw); return false; } - ecoff_data (abfd)->raw_size = raw_size; ecoff_data (abfd)->raw_syments = raw; /* Get pointers for the numeric offsets in the HDRR structure. */ #define FIX(off1, off2, type) \ if (internal_symhdr->off1 == 0) \ - ecoff_data (abfd)->off2 = (type) NULL; \ + debug->off2 = (type) NULL; \ else \ - ecoff_data (abfd)->off2 = (type) ((char *) raw \ - + internal_symhdr->off1 \ - - raw_base) + debug->off2 = (type) ((char *) raw \ + + internal_symhdr->off1 \ + - raw_base) FIX (cbLineOffset, line, unsigned char *); FIX (cbDnOffset, external_dnr, PTR); FIX (cbPdOffset, external_pdr, PTR); @@ -734,21 +790,20 @@ ecoff_slurp_symbolic_info (abfd) We need to look at the fdr to deal with a lot of information in the symbols, so we swap them here. */ - ecoff_data (abfd)->fdr = - (struct fdr *) bfd_alloc (abfd, - (internal_symhdr->ifdMax * - sizeof (struct fdr))); - if (ecoff_data (abfd)->fdr == NULL) + debug->fdr = (struct fdr *) bfd_alloc (abfd, + (internal_symhdr->ifdMax * + sizeof (struct fdr))); + if (debug->fdr == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } - external_fdr_size = backend->external_fdr_size; - fdr_ptr = ecoff_data (abfd)->fdr; - fraw_src = (char *) ecoff_data (abfd)->external_fdr; + external_fdr_size = backend->debug_swap.external_fdr_size; + fdr_ptr = debug->fdr; + fraw_src = (char *) debug->external_fdr; fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size; for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++) - (*backend->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr); + (*backend->debug_swap.swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr); return true; } @@ -768,7 +823,7 @@ static asymbol *ecoff_scom_symbol_ptr; /* Create an empty symbol. */ asymbol * -ecoff_make_empty_symbol (abfd) +_bfd_ecoff_make_empty_symbol (abfd) bfd *abfd; { ecoff_symbol_type *new; @@ -776,10 +831,10 @@ ecoff_make_empty_symbol (abfd) new = (ecoff_symbol_type *) bfd_alloc (abfd, sizeof (ecoff_symbol_type)); if (new == (ecoff_symbol_type *) NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (asymbol *) NULL; } - memset (new, 0, sizeof *new); + memset ((PTR) new, 0, sizeof *new); new->symbol.section = (asection *) NULL; new->fdr = (FDR *) NULL; new->local = false; @@ -790,7 +845,7 @@ ecoff_make_empty_symbol (abfd) /* Set the BFD flags and section for an ECOFF symbol. */ -static void +static boolean ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) bfd *abfd; SYMR *ecoff_sym; @@ -816,19 +871,19 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) (*indirect_ptr_ptr)->value = (bfd_vma) asym; asym->flags = BSF_DEBUGGING; - asym->section = &bfd_und_section; + asym->section = bfd_und_section_ptr; *indirect_ptr_ptr = NULL; - return; + return true; } if (ECOFF_IS_STAB (ecoff_sym) && (ECOFF_UNMARK_STAB (ecoff_sym->index) | N_EXT) == (N_INDR | N_EXT)) { asym->flags = BSF_DEBUGGING | BSF_INDIRECT; - asym->section = &bfd_ind_section; + asym->section = bfd_ind_section_ptr; /* Pass this symbol on to the next call to this function. */ *indirect_ptr_ptr = asym; - return; + return true; } /* Most symbol types are just for debugging. */ @@ -844,12 +899,12 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) if (ECOFF_IS_STAB (ecoff_sym)) { asym->flags = BSF_DEBUGGING; - return; + return true; } break; default: asym->flags = BSF_DEBUGGING; - return; + return true; } if (ext) @@ -881,10 +936,10 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) asym->flags = BSF_DEBUGGING; break; case scAbs: - asym->section = &bfd_abs_section; + asym->section = bfd_abs_section_ptr; break; case scUndefined: - asym->section = &bfd_und_section; + asym->section = bfd_und_section_ptr; asym->flags = 0; asym->value = 0; break; @@ -914,7 +969,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) case scCommon: if (asym->value > ecoff_data (abfd)->gp_size) { - asym->section = &bfd_com_section; + asym->section = bfd_com_section_ptr; asym->flags = 0; break; } @@ -941,7 +996,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) asym->flags = BSF_DEBUGGING; break; case scSUndefined: - asym->section = &bfd_und_section; + asym->section = bfd_und_section_ptr; asym->flags = 0; asym->value = 0; break; @@ -1001,6 +1056,11 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) char *copy; copy = (char *) bfd_alloc (abfd, strlen (name) + 1); + if (!copy) + { + bfd_set_error (bfd_error_no_memory); + return false; + } strcpy (copy, name); section = bfd_make_section (abfd, copy); } @@ -1008,6 +1068,11 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) /* Build a reloc pointing to this constructor. */ reloc_chain = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain)); + if (!reloc_chain) + { + bfd_set_error (bfd_error_no_memory); + return false; + } reloc_chain->relent.sym_ptr_ptr = bfd_get_section (asym)->symbol_ptr_ptr; reloc_chain->relent.address = section->_raw_size; @@ -1038,21 +1103,24 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr) break; } } + return true; } /* Read an ECOFF symbol table. */ boolean -ecoff_slurp_symbol_table (abfd) +_bfd_ecoff_slurp_symbol_table (abfd) bfd *abfd; { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); - const bfd_size_type external_ext_size = backend->external_ext_size; - const bfd_size_type external_sym_size = backend->external_sym_size; + const bfd_size_type external_ext_size + = backend->debug_swap.external_ext_size; + const bfd_size_type external_sym_size + = backend->debug_swap.external_sym_size; void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)) - = backend->swap_ext_in; + = backend->debug_swap.swap_ext_in; void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) - = backend->swap_sym_in; + = backend->debug_swap.swap_sym_in; bfd_size_type internal_size; ecoff_symbol_type *internal; ecoff_symbol_type *internal_ptr; @@ -1067,7 +1135,8 @@ ecoff_slurp_symbol_table (abfd) return true; /* Get the symbolic information. */ - if (ecoff_slurp_symbolic_info (abfd) == false) + if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, + &ecoff_data (abfd)->debug_info)) return false; if (bfd_get_symcount (abfd) == 0) return true; @@ -1076,28 +1145,30 @@ ecoff_slurp_symbol_table (abfd) internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size); if (internal == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } internal_ptr = internal; indirect_ptr = NULL; - eraw_src = (char *) ecoff_data (abfd)->external_ext; + eraw_src = (char *) ecoff_data (abfd)->debug_info.external_ext; eraw_end = (eraw_src - + (ecoff_data (abfd)->symbolic_header.iextMax + + (ecoff_data (abfd)->debug_info.symbolic_header.iextMax * external_ext_size)); for (; eraw_src < eraw_end; eraw_src += external_ext_size, internal_ptr++) { EXTR internal_esym; (*swap_ext_in) (abfd, (PTR) eraw_src, &internal_esym); - internal_ptr->symbol.name = (ecoff_data (abfd)->ssext + internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ssext + internal_esym.asym.iss); - ecoff_set_symbol_info (abfd, &internal_esym.asym, - &internal_ptr->symbol, 1, &indirect_ptr); + if (!ecoff_set_symbol_info (abfd, &internal_esym.asym, + &internal_ptr->symbol, 1, &indirect_ptr)) + return false; /* The alpha uses a negative ifd field for section symbols. */ if (internal_esym.ifd >= 0) - internal_ptr->fdr = ecoff_data (abfd)->fdr + internal_esym.ifd; + internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr + + internal_esym.ifd); else internal_ptr->fdr = NULL; internal_ptr->local = false; @@ -1107,14 +1178,14 @@ ecoff_slurp_symbol_table (abfd) /* The local symbols must be accessed via the fdr's, because the string and aux indices are relative to the fdr information. */ - fdr_ptr = ecoff_data (abfd)->fdr; - fdr_end = fdr_ptr + ecoff_data (abfd)->symbolic_header.ifdMax; + fdr_ptr = ecoff_data (abfd)->debug_info.fdr; + fdr_end = fdr_ptr + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax; for (; fdr_ptr < fdr_end; fdr_ptr++) { char *lraw_src; char *lraw_end; - lraw_src = ((char *) ecoff_data (abfd)->external_sym + lraw_src = ((char *) ecoff_data (abfd)->debug_info.external_sym + fdr_ptr->isymBase * external_sym_size); lraw_end = lraw_src + fdr_ptr->csym * external_sym_size; for (; @@ -1124,11 +1195,12 @@ ecoff_slurp_symbol_table (abfd) SYMR internal_sym; (*swap_sym_in) (abfd, (PTR) lraw_src, &internal_sym); - internal_ptr->symbol.name = (ecoff_data (abfd)->ss + internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ss + fdr_ptr->issBase + internal_sym.iss); - ecoff_set_symbol_info (abfd, &internal_sym, - &internal_ptr->symbol, 0, &indirect_ptr); + if (!ecoff_set_symbol_info (abfd, &internal_sym, + &internal_ptr->symbol, 0, &indirect_ptr)) + return false; internal_ptr->fdr = fdr_ptr; internal_ptr->local = true; internal_ptr->native = (PTR) lraw_src; @@ -1143,21 +1215,24 @@ ecoff_slurp_symbol_table (abfd) /* Return the amount of space needed for the canonical symbols. */ -unsigned int -ecoff_get_symtab_upper_bound (abfd) +long +_bfd_ecoff_get_symtab_upper_bound (abfd) bfd *abfd; { - if (ecoff_slurp_symbolic_info (abfd) == false - || bfd_get_symcount (abfd) == 0) + if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, + &ecoff_data (abfd)->debug_info)) + return -1; + + if (bfd_get_symcount (abfd) == 0) return 0; return (bfd_get_symcount (abfd) + 1) * (sizeof (ecoff_symbol_type *)); } -/* Get the canonicals symbols. */ +/* Get the canonical symbols. */ -unsigned int -ecoff_get_symtab (abfd, alocation) +long +_bfd_ecoff_get_symtab (abfd, alocation) bfd *abfd; asymbol **alocation; { @@ -1165,8 +1240,9 @@ ecoff_get_symtab (abfd, alocation) ecoff_symbol_type *symbase; ecoff_symbol_type **location = (ecoff_symbol_type **) alocation; - if (ecoff_slurp_symbol_table (abfd) == false - || bfd_get_symcount (abfd) == 0) + if (_bfd_ecoff_slurp_symbol_table (abfd) == false) + return -1; + if (bfd_get_symcount (abfd) == 0) return 0; symbase = ecoff_data (abfd)->canonical_symbols; @@ -1186,54 +1262,76 @@ ecoff_get_symtab (abfd, alocation) /* Write aggregate information to a string. */ static void -ecoff_emit_aggregate (abfd, string, rndx, isym, which) +ecoff_emit_aggregate (abfd, fdr, string, rndx, isym, which) bfd *abfd; + FDR *fdr; char *string; RNDXR *rndx; long isym; - CONST char *which; + const char *which; { - int ifd = rndx->rfd; - int indx = rndx->index; - int sym_base, ss_base; - CONST char *name; + const struct ecoff_debug_swap * const debug_swap = + &ecoff_backend (abfd)->debug_swap; + struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info; + unsigned int ifd = rndx->rfd; + unsigned int indx = rndx->index; + const char *name; if (ifd == 0xfff) ifd = isym; - sym_base = ecoff_data (abfd)->fdr[ifd].isymBase; - ss_base = ecoff_data (abfd)->fdr[ifd].issBase; - - if (indx == indexNil) - name = "/* no name */"; + /* An ifd of -1 is an opaque type. An escaped index of 0 is a + struct return type of a procedure compiled without -g. */ + if (ifd == 0xffffffff + || (rndx->rfd == 0xfff && indx == 0)) + name = ""; + else if (indx == indexNil) + name = ""; else { - const struct ecoff_backend_data * const backend = ecoff_backend (abfd); SYMR sym; - indx += sym_base; - (*backend->swap_sym_in) (abfd, - ((char *) ecoff_data (abfd)->external_sym - + indx * backend->external_sym_size), - &sym); - name = ecoff_data (abfd)->ss + ss_base + sym.iss; + if (debug_info->external_rfd == NULL) + fdr = debug_info->fdr + ifd; + else + { + RFDT rfd; + + (*debug_swap->swap_rfd_in) (abfd, + ((char *) debug_info->external_rfd + + ((fdr->rfdBase + ifd) + * debug_swap->external_rfd_size)), + &rfd); + fdr = debug_info->fdr + rfd; + } + + indx += fdr->isymBase; + + (*debug_swap->swap_sym_in) (abfd, + ((char *) debug_info->external_sym + + indx * debug_swap->external_sym_size), + &sym); + + name = debug_info->ss + fdr->issBase + sym.iss; } sprintf (string, - "%s %s { ifd = %d, index = %d }", + "%s %s { ifd = %u, index = %lu }", which, name, ifd, - indx + ecoff_data (abfd)->symbolic_header.iextMax); + ((long) indx + + debug_info->symbolic_header.iextMax)); } /* Convert the type information to string format. */ static char * -ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) +ecoff_type_to_string (abfd, fdr, indx) bfd *abfd; - union aux_ext *aux_ptr; + FDR *fdr; unsigned int indx; - int bigendian; { + union aux_ext *aux_ptr; + int bigendian; AUXU u; struct qual { unsigned int type; @@ -1241,7 +1339,6 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) int high_bound; int stride; } qualifiers[7]; - unsigned int basic_type; int i; static char buffer1[1024]; @@ -1250,6 +1347,9 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) char *p2 = buffer2; RNDXR rndx; + aux_ptr = ecoff_data (abfd)->debug_info.external_aux + fdr->iauxBase; + bigendian = fdr->fBigendian; + for (i = 0; i < 7; i++) { qualifiers[i].low_bound = 0; @@ -1259,7 +1359,7 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) if (AUX_GET_ISYM (bigendian, &aux_ptr[indx]) == -1) return "-1 (no type)"; - ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti); + _bfd_ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti); basic_type = u.ti.bt; qualifiers[0].type = u.ti.tq0; @@ -1328,9 +1428,9 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ case btStruct: /* Structure (Record) */ - ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); - ecoff_emit_aggregate (abfd, p1, &rndx, - AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), + _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); + ecoff_emit_aggregate (abfd, fdr, p1, &rndx, + (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "struct"); indx++; /* skip aux words */ break; @@ -1340,9 +1440,9 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ case btUnion: /* Union */ - ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); - ecoff_emit_aggregate (abfd, p1, &rndx, - AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), + _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); + ecoff_emit_aggregate (abfd, fdr, p1, &rndx, + (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "union"); indx++; /* skip aux words */ break; @@ -1352,9 +1452,9 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ case btEnum: /* Enumeration */ - ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); - ecoff_emit_aggregate (abfd, p1, &rndx, - AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), + _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); + ecoff_emit_aggregate (abfd, fdr, p1, &rndx, + (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "enum"); indx++; /* skip aux words */ break; @@ -1533,8 +1633,9 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) /* Return information about ECOFF symbol SYMBOL in RET. */ +/*ARGSUSED*/ void -ecoff_get_symbol_info (abfd, symbol, ret) +_bfd_ecoff_get_symbol_info (abfd, symbol, ret) bfd *abfd; /* Ignored. */ asymbol *symbol; symbol_info *ret; @@ -1545,13 +1646,14 @@ ecoff_get_symbol_info (abfd, symbol, ret) /* Print information about an ECOFF symbol. */ void -ecoff_print_symbol (abfd, filep, symbol, how) +_bfd_ecoff_print_symbol (abfd, filep, symbol, how) bfd *abfd; PTR filep; asymbol *symbol; bfd_print_symbol_type how; { - const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + const struct ecoff_debug_swap * const debug_swap + = &ecoff_backend (abfd)->debug_swap; FILE *file = (FILE *)filep; switch (how) @@ -1564,8 +1666,8 @@ ecoff_print_symbol (abfd, filep, symbol, how) { SYMR ecoff_sym; - (*backend->swap_sym_in) (abfd, ecoffsymbol (symbol)->native, - &ecoff_sym); + (*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native, + &ecoff_sym); fprintf (file, "ecoff local "); fprintf_vma (file, (bfd_vma) ecoff_sym.value); fprintf (file, " %x %x", (unsigned) ecoff_sym.st, @@ -1575,8 +1677,8 @@ ecoff_print_symbol (abfd, filep, symbol, how) { EXTR ecoff_ext; - (*backend->swap_ext_in) (abfd, ecoffsymbol (symbol)->native, - &ecoff_ext); + (*debug_swap->swap_ext_in) (abfd, ecoffsymbol (symbol)->native, + &ecoff_ext); fprintf (file, "ecoff extern "); fprintf_vma (file, (bfd_vma) ecoff_ext.asym.value); fprintf (file, " %x %x", (unsigned) ecoff_ext.asym.st, @@ -1595,25 +1697,25 @@ ecoff_print_symbol (abfd, filep, symbol, how) if (ecoffsymbol (symbol)->local) { - (*backend->swap_sym_in) (abfd, ecoffsymbol (symbol)->native, - &ecoff_ext.asym); + (*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native, + &ecoff_ext.asym); type = 'l'; pos = ((((char *) ecoffsymbol (symbol)->native - - (char *) ecoff_data (abfd)->external_sym) - / backend->external_sym_size) - + ecoff_data (abfd)->symbolic_header.iextMax); + - (char *) ecoff_data (abfd)->debug_info.external_sym) + / debug_swap->external_sym_size) + + ecoff_data (abfd)->debug_info.symbolic_header.iextMax); jmptbl = ' '; cobol_main = ' '; weakext = ' '; } else { - (*backend->swap_ext_in) (abfd, ecoffsymbol (symbol)->native, - &ecoff_ext); + (*debug_swap->swap_ext_in) (abfd, ecoffsymbol (symbol)->native, + &ecoff_ext); type = 'e'; pos = (((char *) ecoffsymbol (symbol)->native - - (char *) ecoff_data (abfd)->external_ext) - / backend->external_ext_size); + - (char *) ecoff_data (abfd)->debug_info.external_ext) + / debug_swap->external_ext_size); jmptbl = ecoff_ext.jmptbl ? 'j' : ' '; cobol_main = ecoff_ext.cobol_main ? 'c' : ' '; weakext = ecoff_ext.weakext ? 'w' : ' '; @@ -1632,28 +1734,31 @@ ecoff_print_symbol (abfd, filep, symbol, how) if (ecoffsymbol (symbol)->fdr != NULL && ecoff_ext.asym.index != indexNil) { + FDR *fdr; unsigned int indx; int bigendian; bfd_size_type sym_base; union aux_ext *aux_base; + fdr = ecoffsymbol (symbol)->fdr; indx = ecoff_ext.asym.index; /* sym_base is used to map the fdr relative indices which appear in the file to the position number which we are using. */ - sym_base = ecoffsymbol (symbol)->fdr->isymBase; + sym_base = fdr->isymBase; if (ecoffsymbol (symbol)->local) - sym_base += ecoff_data (abfd)->symbolic_header.iextMax; + sym_base += + ecoff_data (abfd)->debug_info.symbolic_header.iextMax; /* aux_base is the start of the aux entries for this file; asym.index is an offset from this. */ - aux_base = (ecoff_data (abfd)->external_aux - + ecoffsymbol (symbol)->fdr->iauxBase); + aux_base = (ecoff_data (abfd)->debug_info.external_aux + + fdr->iauxBase); /* The aux entries are stored in host byte order; the order is indicated by a bit in the fdr. */ - bigendian = ecoffsymbol (symbol)->fdr->fBigendian; + bigendian = fdr->fBigendian; /* This switch is basically from gcc/mips-tdump.c */ switch (ecoff_ext.asym.st) @@ -1675,9 +1780,10 @@ ecoff_print_symbol (abfd, filep, symbol, how) (long) (indx + sym_base)); else fprintf (file, "\n First symbol: %ld", - (long) (AUX_GET_ISYM (bigendian, - &aux_base[ecoff_ext.asym.index]) - + sym_base)); + ((long) + (AUX_GET_ISYM (bigendian, + &aux_base[ecoff_ext.asym.index]) + + sym_base))); break; case stProc: @@ -1686,23 +1792,38 @@ ecoff_print_symbol (abfd, filep, symbol, how) ; else if (ecoffsymbol (symbol)->local) fprintf (file, "\n End+1 symbol: %-7ld Type: %s", - (long) (AUX_GET_ISYM (bigendian, - &aux_base[ecoff_ext.asym.index]) - + sym_base), - ecoff_type_to_string (abfd, aux_base, indx + 1, - bigendian)); + ((long) + (AUX_GET_ISYM (bigendian, + &aux_base[ecoff_ext.asym.index]) + + sym_base)), + ecoff_type_to_string (abfd, fdr, indx + 1)); else - fprintf (file, "\n Local symbol: %d", - (indx - + sym_base - + ecoff_data (abfd)->symbolic_header.iextMax)); + fprintf (file, "\n Local symbol: %ld", + ((long) indx + + (long) sym_base + + (ecoff_data (abfd) + ->debug_info.symbolic_header.iextMax))); + break; + + case stStruct: + fprintf (file, "\n struct; End+1 symbol: %ld", + (long) (indx + sym_base)); + break; + + case stUnion: + fprintf (file, "\n union; End+1 symbol: %ld", + (long) (indx + sym_base)); + break; + + case stEnum: + fprintf (file, "\n enum; End+1 symbol: %ld", + (long) (indx + sym_base)); break; default: if (! ECOFF_IS_STAB (&ecoff_ext.asym)) fprintf (file, "\n Type: %s", - ecoff_type_to_string (abfd, aux_base, indx, - bigendian)); + ecoff_type_to_string (abfd, fdr, indx)); break; } } @@ -1732,7 +1853,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols) || (section->flags & SEC_CONSTRUCTOR) != 0) return true; - if (ecoff_slurp_symbol_table (abfd) == false) + if (_bfd_ecoff_slurp_symbol_table (abfd) == false) return false; internal_relocs = (arelent *) bfd_alloc (abfd, @@ -1744,17 +1865,14 @@ ecoff_slurp_reloc_table (abfd, section, symbols) if (internal_relocs == (arelent *) NULL || external_relocs == (char *) NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } if (bfd_seek (abfd, section->rel_filepos, SEEK_SET) != 0) return false; if (bfd_read (external_relocs, 1, external_relocs_size, abfd) != external_relocs_size) - { - bfd_error = system_call_error; - return false; - } + return false; for (i = 0, rptr = internal_relocs; i < section->reloc_count; i++, rptr++) { @@ -1769,14 +1887,15 @@ ecoff_slurp_reloc_table (abfd, section, symbols) /* r_symndx is an index into the external symbols. */ BFD_ASSERT (intern.r_symndx >= 0 && (intern.r_symndx - < ecoff_data (abfd)->symbolic_header.iextMax)); + < (ecoff_data (abfd) + ->debug_info.symbolic_header.iextMax))); rptr->sym_ptr_ptr = symbols + intern.r_symndx; rptr->addend = 0; } else if (intern.r_symndx == RELOC_SECTION_NONE || intern.r_symndx == RELOC_SECTION_ABS) { - rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr; + rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; rptr->addend = 0; } else @@ -1798,6 +1917,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols) case RELOC_SECTION_LIT4: sec_name = ".lit4"; break; case RELOC_SECTION_XDATA: sec_name = ".xdata"; break; case RELOC_SECTION_PDATA: sec_name = ".pdata"; break; + case RELOC_SECTION_FINI: sec_name = ".fini"; break; case RELOC_SECTION_LITA: sec_name = ".lita"; break; default: abort (); } @@ -1814,7 +1934,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols) /* Let the backend select the howto field and do any other required processing. */ - (*backend->finish_reloc) (abfd, &intern, rptr); + (*backend->adjust_reloc_in) (abfd, &intern, rptr); } bfd_release (abfd, external_relocs); @@ -1826,8 +1946,8 @@ ecoff_slurp_reloc_table (abfd, section, symbols) /* Get a canonical list of relocs. */ -unsigned int -ecoff_canonicalize_reloc (abfd, section, relptr, symbols) +long +_bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols) bfd *abfd; asection *section; arelent **relptr; @@ -1852,11 +1972,9 @@ ecoff_canonicalize_reloc (abfd, section, relptr, symbols) arelent *tblptr; if (ecoff_slurp_reloc_table (abfd, section, symbols) == false) - return 0; + return -1; tblptr = section->relocation; - if (tblptr == (arelent *) NULL) - return 0; for (count = 0; count < section->reloc_count; count++) *relptr++ = tblptr++; @@ -1871,14 +1989,10 @@ ecoff_canonicalize_reloc (abfd, section, relptr, symbols) and return the name of the source file and the line nearest to the wanted location. */ +/*ARGSUSED*/ boolean -ecoff_find_nearest_line (abfd, - section, - ignore_symbols, - offset, - filename_ptr, - functionname_ptr, - retline_ptr) +_bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset, + filename_ptr, functionname_ptr, retline_ptr) bfd *abfd; asection *section; asymbol **ignore_symbols; @@ -1887,7 +2001,8 @@ ecoff_find_nearest_line (abfd, CONST char **functionname_ptr; unsigned int *retline_ptr; { - const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + const struct ecoff_debug_swap * const debug_swap + = &ecoff_backend (abfd)->debug_swap; FDR *fdr_ptr; FDR *fdr_start; FDR *fdr_end; @@ -1896,6 +2011,7 @@ ecoff_find_nearest_line (abfd, char *pdr_ptr; char *pdr_end; PDR pdr; + bfd_vma first_off; unsigned char *line_ptr; unsigned char *line_end; int lineno; @@ -1908,7 +2024,8 @@ ecoff_find_nearest_line (abfd, return false; /* Make sure we have the FDR's. */ - if (ecoff_slurp_symbolic_info (abfd) == false + if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, + &ecoff_data (abfd)->debug_info) || bfd_get_symcount (abfd) == 0) return false; @@ -1917,8 +2034,8 @@ ecoff_find_nearest_line (abfd, memory order. If speed is ever important, this can become a binary search. We must ignore FDR's with no PDR entries; they will have the adr of the FDR before or after them. */ - fdr_start = ecoff_data (abfd)->fdr; - fdr_end = fdr_start + ecoff_data (abfd)->symbolic_header.ifdMax; + fdr_start = ecoff_data (abfd)->debug_info.fdr; + fdr_end = fdr_start + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax; fdr_hold = (FDR *) NULL; for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++) { @@ -1936,21 +2053,23 @@ ecoff_find_nearest_line (abfd, have an address, which is relative to the FDR address, and are also stored in increasing memory order. */ offset -= fdr_ptr->adr; - external_pdr_size = backend->external_pdr_size; - pdr_ptr = ((char *) ecoff_data (abfd)->external_pdr + external_pdr_size = debug_swap->external_pdr_size; + pdr_ptr = ((char *) ecoff_data (abfd)->debug_info.external_pdr + fdr_ptr->ipdFirst * external_pdr_size); pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size; - (*backend->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); + (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); + if (offset < pdr.adr) + return false; /* The address of the first PDR is an offset which applies to the addresses of all the PDR's. */ - offset += pdr.adr; + first_off = pdr.adr; for (pdr_ptr += external_pdr_size; pdr_ptr < pdr_end; pdr_ptr += external_pdr_size) { - (*backend->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); + (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); if (offset < pdr.adr) break; } @@ -1959,7 +2078,7 @@ ecoff_find_nearest_line (abfd, stored in a very funky format, which I won't try to describe. Note that right here pdr_ptr and pdr hold the PDR *after* the one we want; we need this to compute line_end. */ - line_end = ecoff_data (abfd)->line; + line_end = ecoff_data (abfd)->debug_info.line; if (pdr_ptr == pdr_end) line_end += fdr_ptr->cbLineOffset + fdr_ptr->cbLine; else @@ -1967,11 +2086,11 @@ ecoff_find_nearest_line (abfd, /* Now change pdr and pdr_ptr to the one we want. */ pdr_ptr -= external_pdr_size; - (*backend->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); + (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); - offset -= pdr.adr; + offset -= pdr.adr - first_off; lineno = pdr.lnLow; - line_ptr = (ecoff_data (abfd)->line + line_ptr = (ecoff_data (abfd)->debug_info.line + fdr_ptr->cbLineOffset + pdr.cbLineOffset); while (line_ptr < line_end) @@ -2008,24 +2127,28 @@ ecoff_find_nearest_line (abfd, { EXTR proc_ext; - (*backend->swap_ext_in) (abfd, - ((char *) ecoff_data (abfd)->external_ext - + pdr.isym * backend->external_ext_size), - &proc_ext); - *functionname_ptr = ecoff_data (abfd)->ssext + proc_ext.asym.iss; + (*debug_swap->swap_ext_in) + (abfd, + ((char *) ecoff_data (abfd)->debug_info.external_ext + + pdr.isym * debug_swap->external_ext_size), + &proc_ext); + *functionname_ptr = (ecoff_data (abfd)->debug_info.ssext + + proc_ext.asym.iss); } } else { SYMR proc_sym; - *filename_ptr = ecoff_data (abfd)->ss + fdr_ptr->issBase + fdr_ptr->rss; - (*backend->swap_sym_in) (abfd, - ((char *) ecoff_data (abfd)->external_sym - + ((fdr_ptr->isymBase + pdr.isym) - * backend->external_sym_size)), - &proc_sym); - *functionname_ptr = (ecoff_data (abfd)->ss + *filename_ptr = (ecoff_data (abfd)->debug_info.ss + + fdr_ptr->issBase + + fdr_ptr->rss); + (*debug_swap->swap_sym_in) + (abfd, + ((char *) ecoff_data (abfd)->debug_info.external_sym + + (fdr_ptr->isymBase + pdr.isym) * debug_swap->external_sym_size), + &proc_sym); + *functionname_ptr = (ecoff_data (abfd)->debug_info.ss + fdr_ptr->issBase + proc_sym.iss); } @@ -2035,913 +2158,122 @@ ecoff_find_nearest_line (abfd, return true; } -/* We can't use the generic linking routines for ECOFF, because we - have to handle all the debugging information. The generic link - routine just works out the section contents and attaches a list of - symbols. - - We link by looping over all the seclets. We make two passes. On - the first we set the actual section contents and determine the size - of the debugging information. On the second we accumulate the - debugging information and write it out. - - This currently always accumulates the debugging information, which - is incorrect, because it ignores the -s and -S options of the - linker. The linker needs to be modified to give us that - information in a more useful format (currently it just provides a - list of symbols which should appear in the output file). */ - -/* Clear the output_has_begun flag for all the input BFD's. We use it - to avoid linking in the debugging information for a BFD more than - once. */ - -static void -ecoff_clear_output_flags (abfd) - bfd *abfd; -{ - register asection *o; - register bfd_seclet_type *p; - - for (o = abfd->sections; o != (asection *) NULL; o = o->next) - for (p = o->seclets_head; - p != (bfd_seclet_type *) NULL; - p = p->next) - if (p->type == bfd_indirect_seclet) - p->u.indirect.section->owner->output_has_begun = false; -} - -/* Handle an indirect seclet on the first pass. Set the contents of - the output section, and accumulate the debugging information if - any. */ - -static boolean -ecoff_rel (output_bfd, seclet, output_section, data, relocateable) - bfd *output_bfd; - bfd_seclet_type *seclet; - asection *output_section; - PTR data; - boolean relocateable; -{ - bfd *input_bfd; - HDRR *output_symhdr; - HDRR *input_symhdr; - - if ((output_section->flags & SEC_HAS_CONTENTS) - && !(output_section->flags & SEC_NEVER_LOAD) - && (output_section->flags & SEC_LOAD) - && seclet->size) - { - data = (PTR) bfd_get_relocated_section_contents (output_bfd, - seclet, - data, - relocateable); - if (bfd_set_section_contents (output_bfd, - output_section, - data, - seclet->offset, - seclet->size) - == false) - { - abort(); - } - } - - input_bfd = seclet->u.indirect.section->owner; - - /* We want to figure out how much space will be required to - incorporate all the debugging information from input_bfd. We use - the output_has_begun field to avoid adding it in more than once. - The actual incorporation is done in the second pass, in - ecoff_get_debug. The code has to parallel that code in its - manipulations of output_symhdr. */ - - if (input_bfd->output_has_begun) - return true; - input_bfd->output_has_begun = true; - - output_symhdr = &ecoff_data (output_bfd)->symbolic_header; - - if (input_bfd->xvec->flavour != bfd_target_ecoff_flavour) - { - asymbol **symbols; - asymbol **sym_ptr; - asymbol **sym_end; - - /* We just accumulate local symbols from a non-ECOFF BFD. The - external symbols are handled separately. */ - - symbols = (asymbol **) bfd_alloc (output_bfd, - get_symtab_upper_bound (input_bfd)); - if (symbols == (asymbol **) NULL) - { - bfd_error = no_memory; - return false; - } - sym_end = symbols + bfd_canonicalize_symtab (input_bfd, symbols); - - for (sym_ptr = symbols; sym_ptr < sym_end; sym_ptr++) - { - size_t len; - - len = strlen ((*sym_ptr)->name); - if (((*sym_ptr)->flags & BSF_EXPORT) == 0) - { - ++output_symhdr->isymMax; - output_symhdr->issMax += len + 1; - } - } - - bfd_release (output_bfd, (PTR) symbols); - - ++output_symhdr->ifdMax; - - return true; - } - - /* We simply add in the information from another ECOFF BFD. First - we make sure we have the symbolic information. */ - if (ecoff_slurp_symbol_table (input_bfd) == false) - return false; - if (bfd_get_symcount (input_bfd) == 0) - return true; - - input_symhdr = &ecoff_data (input_bfd)->symbolic_header; - - /* Figure out how much information we are going to be putting in. - The external symbols are handled separately. */ - output_symhdr->ilineMax += input_symhdr->ilineMax; - output_symhdr->cbLine += input_symhdr->cbLine; - output_symhdr->idnMax += input_symhdr->idnMax; - output_symhdr->ipdMax += input_symhdr->ipdMax; - output_symhdr->isymMax += input_symhdr->isymMax; - output_symhdr->ioptMax += input_symhdr->ioptMax; - output_symhdr->iauxMax += input_symhdr->iauxMax; - output_symhdr->issMax += input_symhdr->issMax; - output_symhdr->ifdMax += input_symhdr->ifdMax; - - /* The RFD's are special, since we create them if needed. */ - if (input_symhdr->crfd > 0) - output_symhdr->crfd += input_symhdr->crfd; - else - output_symhdr->crfd += input_symhdr->ifdMax; - - return true; -} - -/* Handle an arbitrary seclet on the first pass. */ - -static boolean -ecoff_dump_seclet (abfd, seclet, section, data, relocateable) - bfd *abfd; - bfd_seclet_type *seclet; - asection *section; - PTR data; - boolean relocateable; -{ - switch (seclet->type) - { - case bfd_indirect_seclet: - /* The contents of this section come from another one somewhere - else. */ - return ecoff_rel (abfd, seclet, section, data, relocateable); - - case bfd_fill_seclet: - /* Fill in the section with fill.value. This is used to pad out - sections, but we must avoid padding the .bss section. */ - if ((section->flags & SEC_HAS_CONTENTS) == 0) - { - if (seclet->u.fill.value != 0) - abort (); - } - else - { - char *d = (char *) bfd_alloc (abfd, seclet->size); - unsigned int i; - boolean ret; - - for (i = 0; i < seclet->size; i+=2) - d[i] = seclet->u.fill.value >> 8; - for (i = 1; i < seclet->size; i+=2) - d[i] = seclet->u.fill.value; - ret = bfd_set_section_contents (abfd, section, d, seclet->offset, - seclet->size); - bfd_release (abfd, (PTR) d); - return ret; - } - break; - - default: - abort(); - } - - return true; -} - -/* Add a string to the debugging information we are accumulating for a - file. Return the offset from the fdr string base or from the - external string base. */ - -static long -ecoff_add_string (output_bfd, fdr, string, external) - bfd *output_bfd; - FDR *fdr; - CONST char *string; - boolean external; -{ - HDRR *symhdr; - size_t len; - long ret; - - symhdr = &ecoff_data (output_bfd)->symbolic_header; - len = strlen (string); - if (external) - { - strcpy (ecoff_data (output_bfd)->ssext + symhdr->issExtMax, string); - ret = symhdr->issExtMax; - symhdr->issExtMax += len + 1; - } - else - { - strcpy (ecoff_data (output_bfd)->ss + symhdr->issMax, string); - ret = fdr->cbSs; - symhdr->issMax += len + 1; - fdr->cbSs += len + 1; - } - return ret; -} - -/* Accumulate the debugging information from an input section. */ - -static boolean -ecoff_get_debug (output_bfd, seclet, section, relocateable) - bfd *output_bfd; - bfd_seclet_type *seclet; - asection *section; - boolean relocateable; -{ - const struct ecoff_backend_data * const backend = ecoff_backend (output_bfd); - const bfd_size_type external_sym_size = backend->external_sym_size; - const bfd_size_type external_pdr_size = backend->external_pdr_size; - const bfd_size_type external_fdr_size = backend->external_fdr_size; - const bfd_size_type external_rfd_size = backend->external_rfd_size; - void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) - = backend->swap_sym_in; - void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR)) - = backend->swap_sym_out; - void (* const swap_pdr_in) PARAMS ((bfd *, PTR, PDR *)) - = backend->swap_pdr_in; - void (* const swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR)) - = backend->swap_fdr_out; - void (* const swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR)) - = backend->swap_rfd_out; - bfd *input_bfd; - HDRR *output_symhdr; - HDRR *input_symhdr; - ecoff_data_type *output_ecoff; - ecoff_data_type *input_ecoff; - unsigned int count; - char *sym_out; - ecoff_symbol_type *esym_ptr; - ecoff_symbol_type *esym_end; - FDR *fdr_ptr; - FDR *fdr_end; - char *fdr_out; - - input_bfd = seclet->u.indirect.section->owner; - - /* Don't get the information more than once. */ - if (input_bfd->output_has_begun) - return true; - input_bfd->output_has_begun = true; - - output_ecoff = ecoff_data (output_bfd); - output_symhdr = &output_ecoff->symbolic_header; - - if (input_bfd->xvec->flavour != bfd_target_ecoff_flavour) - { - FDR fdr; - asymbol **symbols; - asymbol **sym_ptr; - asymbol **sym_end; - - /* This is not an ECOFF BFD. Just gather the symbols. */ - - memset (&fdr, 0, sizeof fdr); - - fdr.adr = bfd_get_section_vma (output_bfd, section) + seclet->offset; - fdr.issBase = output_symhdr->issMax; - fdr.cbSs = 0; - fdr.rss = ecoff_add_string (output_bfd, - &fdr, - bfd_get_filename (input_bfd), - false); - fdr.isymBase = output_symhdr->isymMax; - - /* Get the local symbols from the input BFD. */ - symbols = (asymbol **) bfd_alloc (output_bfd, - get_symtab_upper_bound (input_bfd)); - if (symbols == (asymbol **) NULL) - { - bfd_error = no_memory; - return false; - } - sym_end = symbols + bfd_canonicalize_symtab (input_bfd, symbols); - - /* Handle the local symbols. Any external symbols are handled - separately. */ - fdr.csym = 0; - for (sym_ptr = symbols; sym_ptr != sym_end; sym_ptr++) - { - SYMR internal_sym; - - if (((*sym_ptr)->flags & BSF_EXPORT) != 0) - continue; - memset (&internal_sym, 0, sizeof internal_sym); - internal_sym.iss = ecoff_add_string (output_bfd, - &fdr, - (*sym_ptr)->name, - false); - - if (bfd_is_com_section ((*sym_ptr)->section) - || (*sym_ptr)->section == &bfd_und_section) - internal_sym.value = (*sym_ptr)->value; - else - internal_sym.value = ((*sym_ptr)->value - + (*sym_ptr)->section->output_offset - + (*sym_ptr)->section->output_section->vma); - internal_sym.st = stNil; - internal_sym.sc = scUndefined; - internal_sym.index = indexNil; - (*swap_sym_out) (output_bfd, &internal_sym, - ((char *) output_ecoff->external_sym - + output_symhdr->isymMax * external_sym_size)); - ++fdr.csym; - ++output_symhdr->isymMax; - } - - bfd_release (output_bfd, (PTR) symbols); - - /* Leave everything else in the FDR zeroed out. This will cause - the lang field to be langC. The fBigendian field will - indicate little endian format, but it doesn't matter because - it only applies to aux fields and there are none. */ - - (*swap_fdr_out) (output_bfd, &fdr, - ((char *) output_ecoff->external_fdr - + output_symhdr->ifdMax * external_fdr_size)); - ++output_symhdr->ifdMax; - return true; - } - - /* This is an ECOFF BFD. We want to grab the information from - input_bfd and attach it to output_bfd. */ - count = bfd_get_symcount (input_bfd); - if (count == 0) - return true; - input_ecoff = ecoff_data (input_bfd); - input_symhdr = &input_ecoff->symbolic_header; - - /* I think that it is more efficient to simply copy the debugging - information from the input BFD to the output BFD. Because ECOFF - uses relative pointers for most of the debugging information, - only a little of it has to be changed at all. */ - - /* Swap in the local symbols, adjust their values, and swap them out - again. The external symbols are handled separately. */ - sym_out = ((char *) output_ecoff->external_sym - + output_symhdr->isymMax * external_sym_size); - - esym_ptr = ecoff_data (input_bfd)->canonical_symbols; - esym_end = esym_ptr + count; - for (; esym_ptr < esym_end; esym_ptr++) - { - if (esym_ptr->local) - { - SYMR sym; - - (*swap_sym_in) (input_bfd, esym_ptr->native, &sym); - - /* If we're producing an executable, move common symbols - into bss. */ - if (relocateable == false) - { - if (sym.sc == scCommon) - sym.sc = scBss; - else if (sym.sc == scSCommon) - sym.sc = scSBss; - } - - if (! bfd_is_com_section (esym_ptr->symbol.section) - && (esym_ptr->symbol.flags & BSF_DEBUGGING) == 0 - && esym_ptr->symbol.section != &bfd_und_section) - sym.value = (esym_ptr->symbol.value - + esym_ptr->symbol.section->output_offset - + esym_ptr->symbol.section->output_section->vma); - (*swap_sym_out) (output_bfd, &sym, sym_out); - sym_out += external_sym_size; - } - } - - /* That should have accounted for all the local symbols in - input_bfd. */ - - /* Copy the information that does not need swapping. */ - memcpy (output_ecoff->line + output_symhdr->cbLine, - input_ecoff->line, - input_symhdr->cbLine * sizeof (unsigned char)); - memcpy (output_ecoff->external_aux + output_symhdr->iauxMax, - input_ecoff->external_aux, - input_symhdr->iauxMax * sizeof (union aux_ext)); - memcpy (output_ecoff->ss + output_symhdr->issMax, - input_ecoff->ss, - input_symhdr->issMax * sizeof (char)); - - /* Some of the information may need to be swapped. */ - if (output_bfd->xvec->header_byteorder_big_p - == input_bfd->xvec->header_byteorder_big_p) - { - /* The two BFD's have the same endianness, so memcpy will - suffice. */ - if (input_symhdr->idnMax > 0) - memcpy (((char *) output_ecoff->external_dnr - + output_symhdr->idnMax * backend->external_dnr_size), - input_ecoff->external_dnr, - input_symhdr->idnMax * backend->external_dnr_size); - if (input_symhdr->ipdMax > 0) - memcpy (((char *) output_ecoff->external_pdr - + output_symhdr->ipdMax * external_pdr_size), - input_ecoff->external_pdr, - input_symhdr->ipdMax * external_pdr_size); - if (input_symhdr->ioptMax > 0) - memcpy (((char *) output_ecoff->external_opt - + output_symhdr->ioptMax * backend->external_opt_size), - input_ecoff->external_opt, - input_symhdr->ioptMax * backend->external_opt_size); - } - else - { - bfd_size_type sz; - char *in; - char *end; - char *out; - - /* The two BFD's have different endianness, so we must swap - everything in and out. This code would always work, but it - would be slow in the normal case. */ - sz = backend->external_dnr_size; - in = (char *) input_ecoff->external_dnr; - end = in + input_symhdr->idnMax * sz; - out = (char *) output_ecoff->external_dnr + output_symhdr->idnMax * sz; - for (; in < end; in += sz, out += sz) - { - DNR dnr; - - (*backend->swap_dnr_in) (input_bfd, in, &dnr); - (*backend->swap_dnr_out) (output_bfd, &dnr, out); - } - - sz = external_pdr_size; - in = (char *) input_ecoff->external_pdr; - end = in + input_symhdr->ipdMax * sz; - out = (char *) output_ecoff->external_pdr + output_symhdr->ipdMax * sz; - for (; in < end; in += sz, out += sz) - { - PDR pdr; - - (*swap_pdr_in) (input_bfd, in, &pdr); - (*backend->swap_pdr_out) (output_bfd, &pdr, out); - } - - sz = backend->external_opt_size; - in = (char *) input_ecoff->external_opt; - end = in + input_symhdr->ioptMax * sz; - out = (char *) output_ecoff->external_opt + output_symhdr->ioptMax * sz; - for (; in < end; in += sz, out += sz) - { - OPTR opt; - - (*backend->swap_opt_in) (input_bfd, in, &opt); - (*backend->swap_opt_out) (output_bfd, &opt, out); - } - } - - /* Set ifdbase so that the external symbols know how to adjust their - ifd values. */ - input_ecoff->ifdbase = output_symhdr->ifdMax; - - fdr_ptr = input_ecoff->fdr; - fdr_end = fdr_ptr + input_symhdr->ifdMax; - fdr_out = ((char *) output_ecoff->external_fdr - + output_symhdr->ifdMax * external_fdr_size); - for (; fdr_ptr < fdr_end; fdr_ptr++, fdr_out += external_fdr_size) - { - FDR fdr; - unsigned long pdr_off; - - fdr = *fdr_ptr; - - /* The memory address for this fdr is the address for the seclet - plus the offset to this fdr within input_bfd. For some - reason the offset of the first procedure pointer is also - added in. */ - if (fdr.cpd == 0) - pdr_off = 0; - else - { - PDR pdr; - - (*swap_pdr_in) (input_bfd, - ((char *) input_ecoff->external_pdr - + fdr.ipdFirst * external_pdr_size), - &pdr); - pdr_off = pdr.adr; - } - fdr.adr = (bfd_get_section_vma (output_bfd, section) - + seclet->offset - + (fdr_ptr->adr - input_ecoff->fdr->adr) - + pdr_off); - - fdr.issBase += output_symhdr->issMax; - fdr.isymBase += output_symhdr->isymMax; - fdr.ilineBase += output_symhdr->ilineMax; - fdr.ioptBase += output_symhdr->ioptMax; - fdr.ipdFirst += output_symhdr->ipdMax; - fdr.iauxBase += output_symhdr->iauxMax; - fdr.rfdBase += output_symhdr->crfd; - - /* If there are no RFD's, we are going to add some. We don't - want to adjust irfd for this, so that all the FDR's can share - the RFD's. */ - if (input_symhdr->crfd == 0) - fdr.crfd = input_symhdr->ifdMax; - - if (fdr.cbLine != 0) - fdr.cbLineOffset += output_symhdr->cbLine; - - (*swap_fdr_out) (output_bfd, &fdr, fdr_out); - } - - if (input_symhdr->crfd > 0) - { - void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *)) - = backend->swap_rfd_in; - char *rfd_in; - char *rfd_end; - char *rfd_out; - - /* Swap and adjust the RFD's. RFD's are only created by the - linker, so this will only be necessary if one of the input - files is the result of a partial link. Presumably all - necessary RFD's are present. */ - rfd_in = (char *) input_ecoff->external_rfd; - rfd_end = rfd_in + input_symhdr->crfd * external_rfd_size; - rfd_out = ((char *) output_ecoff->external_rfd - + output_symhdr->crfd * external_rfd_size); - for (; - rfd_in < rfd_end; - rfd_in += external_rfd_size, rfd_out += external_rfd_size) - { - RFDT rfd; - - (*swap_rfd_in) (input_bfd, rfd_in, &rfd); - rfd += output_symhdr->ifdMax; - (*swap_rfd_out) (output_bfd, &rfd, rfd_out); - } - output_symhdr->crfd += input_symhdr->crfd; - } - else - { - char *rfd_out; - char *rfd_end; - RFDT rfd; - - /* Create RFD's. Some of the debugging information includes - relative file indices. These indices are taken as indices to - the RFD table if there is one, or to the global table if - there is not. If we did not create RFD's, we would have to - parse and adjust all the debugging information which contains - file indices. */ - rfd = output_symhdr->ifdMax; - rfd_out = ((char *) output_ecoff->external_rfd - + output_symhdr->crfd * external_rfd_size); - rfd_end = rfd_out + input_symhdr->ifdMax * external_rfd_size; - for (; rfd_out < rfd_end; rfd_out += external_rfd_size, rfd++) - (*swap_rfd_out) (output_bfd, &rfd, rfd_out); - output_symhdr->crfd += input_symhdr->ifdMax; - } - - /* Combine the register masks. Not all of these are used on all - targets, but that's OK because only the relevant ones will be - swapped in and out. */ - { - int i; - - output_ecoff->gprmask |= input_ecoff->gprmask; - output_ecoff->fprmask |= input_ecoff->fprmask; - for (i = 0; i < 4; i++) - output_ecoff->cprmask[i] |= input_ecoff->cprmask[i]; - } - - /* Update the counts. */ - output_symhdr->ilineMax += input_symhdr->ilineMax; - output_symhdr->cbLine += input_symhdr->cbLine; - output_symhdr->idnMax += input_symhdr->idnMax; - output_symhdr->ipdMax += input_symhdr->ipdMax; - output_symhdr->isymMax += input_symhdr->isymMax; - output_symhdr->ioptMax += input_symhdr->ioptMax; - output_symhdr->iauxMax += input_symhdr->iauxMax; - output_symhdr->issMax += input_symhdr->issMax; - output_symhdr->ifdMax += input_symhdr->ifdMax; - - return true; -} - -/* This is the actual link routine. It makes two passes over all the - seclets. */ +/* Copy private BFD data. This is called by objcopy and strip. We + use it to copy the ECOFF debugging information from one BFD to the + other. It would be theoretically possible to represent the ECOFF + debugging information in the symbol table. However, it would be a + lot of work, and there would be little gain (gas, gdb, and ld + already access the ECOFF debugging information via the + ecoff_debug_info structure, and that structure would have to be + retained in order to support ECOFF debugging in MIPS ELF). + + The debugging information for the ECOFF external symbols comes from + the symbol table, so this function only handles the other debugging + information. */ boolean -ecoff_bfd_seclet_link (abfd, data, relocateable) - bfd *abfd; - PTR data; - boolean relocateable; +_bfd_ecoff_bfd_copy_private_bfd_data (ibfd, obfd) + bfd *ibfd; + bfd *obfd; { - const struct ecoff_backend_data * const backend = ecoff_backend (abfd); - HDRR *symhdr; - int ipass; - register asection *o; - register bfd_seclet_type *p; + struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info; + struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info; + register int i; asymbol **sym_ptr_ptr; - bfd_size_type debug_align; - bfd_size_type size; - char *raw; + size_t c; + boolean local; - /* We accumulate the debugging information counts in the symbolic - header. */ - symhdr = &ecoff_data (abfd)->symbolic_header; - symhdr->magic = backend->sym_magic; - /* FIXME: What should the version stamp be? */ - symhdr->vstamp = 0; - symhdr->ilineMax = 0; - symhdr->cbLine = 0; - symhdr->idnMax = 0; - symhdr->ipdMax = 0; - symhdr->isymMax = 0; - symhdr->ioptMax = 0; - symhdr->iauxMax = 0; - symhdr->issMax = 0; - symhdr->issExtMax = 0; - symhdr->ifdMax = 0; - symhdr->crfd = 0; - symhdr->iextMax = 0; + /* This function is selected based on the input vector. We only + want to copy information over if the output BFD also uses ECOFF + format. */ + if (bfd_get_flavour (obfd) != bfd_target_ecoff_flavour) + return true; - /* We need to copy over the debugging symbols from each input BFD. - When we do this copying, we have to adjust the text address in - the FDR structures, so we have to know the text address used for - the input BFD. Since we only want to copy the symbols once per - input BFD, but we are going to look at each input BFD multiple - times (once for each section it provides), we arrange to always - look at the text section first. That means that when we copy the - debugging information, we always know the text address. So we - actually do each pass in two sub passes; first the text sections, - then the non-text sections. We use the output_has_begun flag to - determine whether we have copied over the debugging information - yet. */ + /* Copy the GP value and the register masks. */ + ecoff_data (obfd)->gp = ecoff_data (ibfd)->gp; + ecoff_data (obfd)->gprmask = ecoff_data (ibfd)->gprmask; + ecoff_data (obfd)->fprmask = ecoff_data (ibfd)->fprmask; + for (i = 0; i < 3; i++) + ecoff_data (obfd)->cprmask[i] = ecoff_data (ibfd)->cprmask[i]; - /* Do the first pass: set the output section contents and count the - debugging information. */ - ecoff_clear_output_flags (abfd); - for (ipass = 0; ipass < 2; ipass++) + /* Copy the version stamp. */ + oinfo->symbolic_header.vstamp = iinfo->symbolic_header.vstamp; + + /* If there are no symbols, don't copy any debugging information. */ + c = bfd_get_symcount (obfd); + sym_ptr_ptr = bfd_get_outsymbols (obfd); + if (c == 0 || sym_ptr_ptr == (asymbol **) NULL) + return true; + + /* See if there are any local symbols. */ + local = false; + for (; c > 0; c--, sym_ptr_ptr++) { - for (o = abfd->sections; o != (asection *) NULL; o = o->next) + if (ecoffsymbol (*sym_ptr_ptr)->local) { - /* If this is a fake section, just forget it. The register - information is handled in another way. */ - if (strcmp (o->name, SCOMMON) == 0 - || strcmp (o->name, REGINFO) == 0) - continue; - - /* For SEC_CODE sections, (flags & SEC_CODE) == 0 is false, - so they are done on pass 0. For other sections the - expression is true, so they are done on pass 1. */ - if (((o->flags & SEC_CODE) == 0) != ipass) - continue; - - for (p = o->seclets_head; - p != (bfd_seclet_type *) NULL; - p = p->next) - { - if (ecoff_dump_seclet (abfd, p, o, data, relocateable) - == false) - return false; - } + local = true; + break; } } - /* We handle the external symbols differently. We use the ones - attached to the output_bfd. The linker will have already - determined which symbols are to be attached. Here we just - determine how much space we will need for them. */ - sym_ptr_ptr = bfd_get_outsymbols (abfd); - if (sym_ptr_ptr != NULL) + if (local) { - asymbol **sym_end; + /* There are some local symbols. We just bring over all the + debugging information. FIXME: This is not quite the right + thing to do. If the user has asked us to discard all + debugging information, then we are probably going to wind up + keeping it because there will probably be some local symbol + which objcopy did not discard. We should actually break + apart the debugging information and only keep that which + applies to the symbols we want to keep. */ + oinfo->symbolic_header.ilineMax = iinfo->symbolic_header.ilineMax; + oinfo->symbolic_header.cbLine = iinfo->symbolic_header.cbLine; + oinfo->line = iinfo->line; - sym_end = sym_ptr_ptr + bfd_get_symcount (abfd); - for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++) - { - if (((*sym_ptr_ptr)->flags & BSF_DEBUGGING) == 0 - && ((*sym_ptr_ptr)->flags & BSF_LOCAL) == 0) - { - ++symhdr->iextMax; - symhdr->issExtMax += strlen ((*sym_ptr_ptr)->name) + 1; - } - } + oinfo->symbolic_header.idnMax = iinfo->symbolic_header.idnMax; + oinfo->external_dnr = iinfo->external_dnr; + + oinfo->symbolic_header.ipdMax = iinfo->symbolic_header.ipdMax; + oinfo->external_pdr = iinfo->external_pdr; + + oinfo->symbolic_header.isymMax = iinfo->symbolic_header.isymMax; + oinfo->external_sym = iinfo->external_sym; + + oinfo->symbolic_header.ioptMax = iinfo->symbolic_header.ioptMax; + oinfo->external_opt = iinfo->external_opt; + + oinfo->symbolic_header.iauxMax = iinfo->symbolic_header.iauxMax; + oinfo->external_aux = iinfo->external_aux; + + oinfo->symbolic_header.issMax = iinfo->symbolic_header.issMax; + oinfo->ss = iinfo->ss; + + oinfo->symbolic_header.ifdMax = iinfo->symbolic_header.ifdMax; + oinfo->external_fdr = iinfo->external_fdr; + + oinfo->symbolic_header.crfd = iinfo->symbolic_header.crfd; + oinfo->external_rfd = iinfo->external_rfd; } - - /* Adjust the counts so that structures are longword aligned. */ - debug_align = backend->debug_align; - --debug_align; - symhdr->cbLine = (symhdr->cbLine + debug_align) &~ debug_align; - symhdr->issMax = (symhdr->issMax + debug_align) &~ debug_align; - symhdr->issExtMax = (symhdr->issExtMax + debug_align) &~ debug_align; - - /* Now the counts in symhdr are the correct size for the debugging - information. We allocate the right amount of space, and reset - the counts so that the second pass can use them as indices. It - would be possible to output the debugging information directly to - the file in pass 2, rather than to build it in memory and then - write it out. Outputting to the file would require a lot of - seeks and small writes, though, and I think this approach is - faster. */ - size = (symhdr->cbLine * sizeof (unsigned char) - + symhdr->idnMax * backend->external_dnr_size - + symhdr->ipdMax * backend->external_pdr_size - + symhdr->isymMax * backend->external_sym_size - + symhdr->ioptMax * backend->external_opt_size - + symhdr->iauxMax * sizeof (union aux_ext) - + symhdr->issMax * sizeof (char) - + symhdr->issExtMax * sizeof (char) - + symhdr->ifdMax * backend->external_fdr_size - + symhdr->crfd * backend->external_rfd_size - + symhdr->iextMax * backend->external_ext_size); - raw = (char *) bfd_alloc (abfd, size); - if (raw == (char *) NULL) + else { - bfd_error = no_memory; - return false; - } - ecoff_data (abfd)->raw_size = size; - ecoff_data (abfd)->raw_syments = (PTR) raw; - - /* Initialize the raw pointers. */ -#define SET(field, count, type, size) \ - ecoff_data (abfd)->field = (type) raw; \ - raw += symhdr->count * size - - SET (line, cbLine, unsigned char *, sizeof (unsigned char)); - SET (external_dnr, idnMax, PTR, backend->external_dnr_size); - SET (external_pdr, ipdMax, PTR, backend->external_pdr_size); - SET (external_sym, isymMax, PTR, backend->external_sym_size); - SET (external_opt, ioptMax, PTR, backend->external_opt_size); - SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext)); - SET (ss, issMax, char *, sizeof (char)); - SET (ssext, issExtMax, char *, sizeof (char)); - SET (external_fdr, ifdMax, PTR, backend->external_fdr_size); - SET (external_rfd, crfd, PTR, backend->external_rfd_size); - SET (external_ext, iextMax, PTR, backend->external_ext_size); -#undef SET - - /* Reset the counts so the second pass can use them to know how far - it has gotten. */ - symhdr->ilineMax = 0; - symhdr->cbLine = 0; - symhdr->idnMax = 0; - symhdr->ipdMax = 0; - symhdr->isymMax = 0; - symhdr->ioptMax = 0; - symhdr->iauxMax = 0; - symhdr->issMax = 0; - symhdr->issExtMax = 0; - symhdr->ifdMax = 0; - symhdr->crfd = 0; - symhdr->iextMax = 0; - - /* Do the second pass: accumulate the debugging information. */ - ecoff_clear_output_flags (abfd); - for (ipass = 0; ipass < 2; ipass++) - { - for (o = abfd->sections; o != (asection *) NULL; o = o->next) + /* We are discarding all the local symbol information. Look + through the external symbols and remove all references to FDR + or aux information. */ + c = bfd_get_symcount (obfd); + sym_ptr_ptr = bfd_get_outsymbols (obfd); + for (; c > 0; c--, sym_ptr_ptr++) { - if (strcmp (o->name, SCOMMON) == 0 - || strcmp (o->name, REGINFO) == 0) - continue; - if (((o->flags & SEC_CODE) == 0) != ipass) - continue; - for (p = o->seclets_head; - p != (bfd_seclet_type *) NULL; - p = p->next) - { - if (p->type == bfd_indirect_seclet) - { - if (ecoff_get_debug (abfd, p, o, relocateable) == false) - return false; - } - } - } - } - - /* Put in the external symbols. */ - sym_ptr_ptr = bfd_get_outsymbols (abfd); - if (sym_ptr_ptr != NULL) - { - const bfd_size_type external_ext_size = backend->external_ext_size; - void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)) - = backend->swap_ext_in; - void (* const swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR)) - = backend->swap_ext_out; - char *ssext; - char *external_ext; - - ssext = ecoff_data (abfd)->ssext; - external_ext = (char *) ecoff_data (abfd)->external_ext; - for (; *sym_ptr_ptr != NULL; sym_ptr_ptr++) - { - asymbol *sym_ptr; EXTR esym; - sym_ptr = *sym_ptr_ptr; - - if ((sym_ptr->flags & BSF_DEBUGGING) != 0 - || (sym_ptr->flags & BSF_LOCAL) != 0) - continue; - - /* The native pointer can be NULL for a symbol created by - the linker via ecoff_make_empty_symbol. */ - if (bfd_asymbol_flavour (sym_ptr) != bfd_target_ecoff_flavour - || ecoffsymbol (sym_ptr)->native == NULL) - { - esym.jmptbl = 0; - esym.cobol_main = 0; - esym.weakext = 0; - esym.reserved = 0; - esym.ifd = ifdNil; - /* FIXME: we can do better than this for st and sc. */ - esym.asym.st = stGlobal; - esym.asym.sc = scAbs; - esym.asym.reserved = 0; - esym.asym.index = indexNil; - } - else - { - ecoff_symbol_type *ecoff_sym_ptr; - - ecoff_sym_ptr = ecoffsymbol (sym_ptr); - if (ecoff_sym_ptr->local) - abort (); - (*swap_ext_in) (abfd, ecoff_sym_ptr->native, &esym); - - /* If we're producing an executable, move common symbols - into bss. */ - if (relocateable == false) - { - if (esym.asym.sc == scCommon) - esym.asym.sc = scBss; - else if (esym.asym.sc == scSCommon) - esym.asym.sc = scSBss; - } - - /* Adjust the FDR index for the symbol by that used for - the input BFD. */ - esym.ifd += ecoff_data (bfd_asymbol_bfd (sym_ptr))->ifdbase; - } - - esym.asym.iss = symhdr->issExtMax; - - if (bfd_is_com_section (sym_ptr->section) - || sym_ptr->section == &bfd_und_section) - esym.asym.value = sym_ptr->value; - else - esym.asym.value = (sym_ptr->value - + sym_ptr->section->output_offset - + sym_ptr->section->output_section->vma); - - (*swap_ext_out) (abfd, &esym, external_ext); - - ecoff_set_sym_index (sym_ptr, symhdr->iextMax); - - external_ext += external_ext_size; - ++symhdr->iextMax; - - strcpy (ssext + symhdr->issExtMax, sym_ptr->name); - symhdr->issExtMax += strlen (sym_ptr->name) + 1; + (*(ecoff_backend (obfd)->debug_swap.swap_ext_in)) + (obfd, ecoffsymbol (*sym_ptr_ptr)->native, &esym); + esym.ifd = ifdNil; + esym.asym.index = indexNil; + (*(ecoff_backend (obfd)->debug_swap.swap_ext_out)) + (obfd, &esym, ecoffsymbol (*sym_ptr_ptr)->native); } } - /* Adjust the counts so that structures are longword aligned. */ - symhdr->cbLine = (symhdr->cbLine + debug_align) &~ debug_align; - symhdr->issMax = (symhdr->issMax + debug_align) &~ debug_align; - symhdr->issExtMax = (symhdr->issExtMax + debug_align) &~ debug_align; - return true; } @@ -2950,7 +2282,7 @@ ecoff_bfd_seclet_link (abfd, data, relocateable) callers ignore the return value. */ boolean -ecoff_set_arch_mach (abfd, arch, machine) +_bfd_ecoff_set_arch_mach (abfd, arch, machine) bfd *abfd; enum bfd_architecture arch; unsigned long machine; @@ -2959,64 +2291,42 @@ ecoff_set_arch_mach (abfd, arch, machine) return arch == ecoff_backend (abfd)->arch; } -/* Get the size of the section headers. We do not output the .scommon - section which we created in ecoff_mkobject, nor do we output any - .reginfo section. */ +/* Get the size of the section headers. */ +/*ARGSUSED*/ int -ecoff_sizeof_headers (abfd, reloc) +_bfd_ecoff_sizeof_headers (abfd, reloc) bfd *abfd; boolean reloc; { asection *current; int c; + int ret; c = 0; for (current = abfd->sections; current != (asection *)NULL; current = current->next) - if (strcmp (current->name, SCOMMON) != 0 - && strcmp (current->name, REGINFO) != 0) - ++c; + ++c; - return (bfd_coff_filhsz (abfd) - + bfd_coff_aoutsz (abfd) - + c * bfd_coff_scnhsz (abfd)); + ret = (bfd_coff_filhsz (abfd) + + bfd_coff_aoutsz (abfd) + + c * bfd_coff_scnhsz (abfd)); + return BFD_ALIGN (ret, 16); } - -/* Get the contents of a section. This is where we handle reading the - .reginfo section, which implicitly holds the contents of an - ecoff_reginfo structure. */ +/* Get the contents of a section. */ boolean -ecoff_get_section_contents (abfd, section, location, offset, count) +_bfd_ecoff_get_section_contents (abfd, section, location, offset, count) bfd *abfd; asection *section; PTR location; file_ptr offset; bfd_size_type count; { - ecoff_data_type *tdata = ecoff_data (abfd); - struct ecoff_reginfo s; - int i; - - if (strcmp (section->name, REGINFO) != 0) - return bfd_generic_get_section_contents (abfd, section, location, - offset, count); - - s.gp_value = tdata->gp; - s.gprmask = tdata->gprmask; - for (i = 0; i < 4; i++) - s.cprmask[i] = tdata->cprmask[i]; - s.fprmask = tdata->fprmask; - - /* bfd_get_section_contents has already checked that the offset and - size is reasonable. We don't have to worry about swapping or any - such thing; the .reginfo section is defined such that the - contents are an ecoff_reginfo structure as seen on the host. */ - memcpy (location, ((char *) &s) + offset, count); - return true; + return _bfd_generic_get_section_contents (abfd, section, location, + offset, count); } /* Calculate the file position for each section, and set @@ -3031,41 +2341,64 @@ ecoff_compute_section_file_positions (abfd) file_ptr old_sofar; boolean first_data; - if (bfd_get_start_address (abfd)) - abfd->flags |= EXEC_P; - - sofar = ecoff_sizeof_headers (abfd, false); + sofar = _bfd_ecoff_sizeof_headers (abfd, false); first_data = true; for (current = abfd->sections; current != (asection *) NULL; current = current->next) { + unsigned int alignment_power; + /* Only deal with sections which have contents */ - if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0 - || strcmp (current->name, SCOMMON) == 0 - || strcmp (current->name, REGINFO) == 0) + if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0) continue; + /* For the Alpha ECOFF .pdata section the lnnoptr field is + supposed to indicate the number of .pdata entries that are + really in the section. Each entry is 8 bytes. We store this + away in line_filepos before increasing the section size. */ + if (strcmp (current->name, _PDATA) != 0) + alignment_power = current->alignment_power; + else + { + current->line_filepos = current->_raw_size / 8; + alignment_power = 4; + } + /* On Ultrix, the data sections in an executable file must be aligned to a page boundary within the file. This does not affect the section size, though. FIXME: Does this work for - other platforms? */ + other platforms? It requires some modification for the + Alpha, because .rdata on the Alpha goes with the text, not + the data. */ if ((abfd->flags & EXEC_P) != 0 && (abfd->flags & D_PAGED) != 0 && first_data != false - && (current->flags & SEC_CODE) == 0) + && (current->flags & SEC_CODE) == 0 + && (! ecoff_backend (abfd)->rdata_in_text + || strcmp (current->name, _RDATA) != 0) + && strcmp (current->name, _PDATA) != 0) { const bfd_vma round = ecoff_backend (abfd)->round; sofar = (sofar + round - 1) &~ (round - 1); first_data = false; } + else if (strcmp (current->name, _LIB) == 0) + { + const bfd_vma round = ecoff_backend (abfd)->round; + /* On Irix 4, the location of contents of the .lib section + from a shared library section is also rounded up to a + page boundary. */ + + sofar = (sofar + round - 1) &~ (round - 1); + } /* Align the sections in the file to the same boundary on which they are aligned in virtual memory. */ old_sofar = sofar; - sofar = BFD_ALIGN (sofar, 1 << current->alignment_power); + sofar = BFD_ALIGN (sofar, 1 << alignment_power); current->filepos = sofar; @@ -3073,126 +2406,44 @@ ecoff_compute_section_file_positions (abfd) /* make sure that this section is of the right size too */ old_sofar = sofar; - sofar = BFD_ALIGN (sofar, 1 << current->alignment_power); + sofar = BFD_ALIGN (sofar, 1 << alignment_power); current->_raw_size += sofar - old_sofar; } ecoff_data (abfd)->reloc_filepos = sofar; } -/* Set the contents of a section. This is where we handle setting the - contents of the .reginfo section, which implicitly holds a - ecoff_reginfo structure. */ +/* Determine the location of the relocs for all the sections in the + output file, as well as the location of the symbolic debugging + information. */ -boolean -ecoff_set_section_contents (abfd, section, location, offset, count) - bfd *abfd; - asection *section; - PTR location; - file_ptr offset; - bfd_size_type count; -{ - if (abfd->output_has_begun == false) - ecoff_compute_section_file_positions (abfd); - - if (strcmp (section->name, REGINFO) == 0) - { - ecoff_data_type *tdata = ecoff_data (abfd); - struct ecoff_reginfo s; - int i; - - /* If the caller is only changing part of the structure, we must - retrieve the current information before the memcpy. */ - if (offset != 0 || count != sizeof (struct ecoff_reginfo)) - { - s.gp_value = tdata->gp; - s.gprmask = tdata->gprmask; - for (i = 0; i < 4; i++) - s.cprmask[i] = tdata->cprmask[i]; - s.fprmask = tdata->fprmask; - } - - /* bfd_set_section_contents has already checked that the offset - and size is reasonable. We don't have to worry about - swapping or any such thing; the .reginfo section is defined - such that the contents are an ecoff_reginfo structure as seen - on the host. */ - memcpy (((char *) &s) + offset, location, count); - - tdata->gp = s.gp_value; - tdata->gprmask = s.gprmask; - for (i = 0; i < 4; i++) - tdata->cprmask[i] = s.cprmask[i]; - tdata->fprmask = s.fprmask; - - return true; - - } - - bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET); - - if (count != 0) - return (bfd_write (location, 1, count, abfd) == count) ? true : false; - - return true; -} - -/* Write out an ECOFF file. */ - -boolean -ecoff_write_object_contents (abfd) +static bfd_size_type +ecoff_compute_reloc_file_positions (abfd) bfd *abfd; { - const struct ecoff_backend_data * const backend = ecoff_backend (abfd); - const bfd_vma round = backend->round; - const bfd_size_type filhsz = bfd_coff_filhsz (abfd); - const bfd_size_type aoutsz = bfd_coff_aoutsz (abfd); - const bfd_size_type scnhsz = bfd_coff_scnhsz (abfd); - const bfd_size_type external_hdr_size = backend->external_hdr_size; - const bfd_size_type external_reloc_size = backend->external_reloc_size; - void (* const swap_reloc_out) PARAMS ((bfd *, - const struct internal_reloc *, - PTR)) - = backend->swap_reloc_out; - asection *current; - unsigned int count; - file_ptr scn_base; + const bfd_size_type external_reloc_size = + ecoff_backend (abfd)->external_reloc_size; file_ptr reloc_base; + bfd_size_type reloc_size; + asection *current; file_ptr sym_base; - unsigned long reloc_size; - unsigned long text_size; - unsigned long text_start; - unsigned long data_size; - unsigned long data_start; - unsigned long bss_size; - PTR buff; - struct internal_filehdr internal_f; - struct internal_aouthdr internal_a; - int i; - bfd_error = system_call_error; - - if(abfd->output_has_begun == false) - ecoff_compute_section_file_positions(abfd); - - if (abfd->sections != (asection *) NULL) - scn_base = abfd->sections->filepos; - else - scn_base = 0; + if (! abfd->output_has_begun) + { + ecoff_compute_section_file_positions (abfd); + abfd->output_has_begun = true; + } + reloc_base = ecoff_data (abfd)->reloc_filepos; - count = 1; reloc_size = 0; for (current = abfd->sections; current != (asection *)NULL; current = current->next) { - if (strcmp (current->name, SCOMMON) == 0 - || strcmp (current->name, REGINFO) == 0) - continue; - current->target_index = count; - ++count; - if (current->reloc_count != 0) + if (current->reloc_count == 0) + current->rel_filepos = 0; + else { bfd_size_type relsize; @@ -3201,36 +2452,286 @@ ecoff_write_object_contents (abfd) reloc_size += relsize; reloc_base += relsize; } - else - current->rel_filepos = 0; } - sym_base = reloc_base + reloc_size; + sym_base = ecoff_data (abfd)->reloc_filepos + reloc_size; /* At least on Ultrix, the symbol table of an executable file must be aligned to a page boundary. FIXME: Is this true on other platforms? */ if ((abfd->flags & EXEC_P) != 0 && (abfd->flags & D_PAGED) != 0) - sym_base = (sym_base + round - 1) &~ (round - 1); + sym_base = ((sym_base + ecoff_backend (abfd)->round - 1) + &~ (ecoff_backend (abfd)->round - 1)); ecoff_data (abfd)->sym_filepos = sym_base; + return reloc_size; +} + +/* Set the contents of a section. */ + +boolean +_bfd_ecoff_set_section_contents (abfd, section, location, offset, count) + bfd *abfd; + asection *section; + PTR location; + file_ptr offset; + bfd_size_type count; +{ + /* This must be done first, because bfd_set_section_contents is + going to set output_has_begun to true. */ + if (abfd->output_has_begun == false) + ecoff_compute_section_file_positions (abfd); + + /* If this is a .lib section, bump the vma address so that it winds + up being the number of .lib sections output. This is right for + Irix 4. Ian Taylor . */ + if (strcmp (section->name, _LIB) == 0) + ++section->vma; + + if (count == 0) + return true; + + if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0 + || bfd_write (location, 1, count, abfd) != count) + return false; + + return true; +} + +/* Get the GP value for an ECOFF file. This is a hook used by + nlmconv. */ + +bfd_vma +bfd_ecoff_get_gp_value (abfd) + bfd *abfd; +{ + if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour + || bfd_get_format (abfd) != bfd_object) + { + bfd_set_error (bfd_error_invalid_operation); + return 0; + } + + return ecoff_data (abfd)->gp; +} + +/* Set the GP value for an ECOFF file. This is a hook used by the + assembler. */ + +boolean +bfd_ecoff_set_gp_value (abfd, gp_value) + bfd *abfd; + bfd_vma gp_value; +{ + if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour + || bfd_get_format (abfd) != bfd_object) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + + ecoff_data (abfd)->gp = gp_value; + + return true; +} + +/* Set the register masks for an ECOFF file. This is a hook used by + the assembler. */ + +boolean +bfd_ecoff_set_regmasks (abfd, gprmask, fprmask, cprmask) + bfd *abfd; + unsigned long gprmask; + unsigned long fprmask; + unsigned long *cprmask; +{ + ecoff_data_type *tdata; + + if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour + || bfd_get_format (abfd) != bfd_object) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + + tdata = ecoff_data (abfd); + tdata->gprmask = gprmask; + tdata->fprmask = fprmask; + if (cprmask != (unsigned long *) NULL) + { + register int i; + + for (i = 0; i < 3; i++) + tdata->cprmask[i] = cprmask[i]; + } + + return true; +} + +/* Get ECOFF EXTR information for an external symbol. This function + is passed to bfd_ecoff_debug_externals. */ + +static boolean +ecoff_get_extr (sym, esym) + asymbol *sym; + EXTR *esym; +{ + ecoff_symbol_type *ecoff_sym_ptr; + bfd *input_bfd; + + if (bfd_asymbol_flavour (sym) != bfd_target_ecoff_flavour + || ecoffsymbol (sym)->native == NULL) + { + /* Don't include debugging, local, or section symbols. */ + if ((sym->flags & BSF_DEBUGGING) != 0 + || (sym->flags & BSF_LOCAL) != 0 + || (sym->flags & BSF_SECTION_SYM) != 0) + return false; + + esym->jmptbl = 0; + esym->cobol_main = 0; + esym->weakext = 0; + esym->reserved = 0; + esym->ifd = ifdNil; + /* FIXME: we can do better than this for st and sc. */ + esym->asym.st = stGlobal; + esym->asym.sc = scAbs; + esym->asym.reserved = 0; + esym->asym.index = indexNil; + return true; + } + + ecoff_sym_ptr = ecoffsymbol (sym); + + if (ecoff_sym_ptr->local) + return false; + + input_bfd = bfd_asymbol_bfd (sym); + (*(ecoff_backend (input_bfd)->debug_swap.swap_ext_in)) + (input_bfd, ecoff_sym_ptr->native, esym); + + /* If the symbol was defined by the linker, then esym will be + undefined but sym will not be. Get a better class for such a + symbol. */ + if ((esym->asym.sc == scUndefined + || esym->asym.sc == scSUndefined) + && ! bfd_is_und_section (bfd_get_section (sym))) + esym->asym.sc = scAbs; + + /* Adjust the FDR index for the symbol by that used for the input + BFD. */ + if (esym->ifd != -1) + { + struct ecoff_debug_info *input_debug; + + input_debug = &ecoff_data (input_bfd)->debug_info; + BFD_ASSERT (esym->ifd < input_debug->symbolic_header.ifdMax); + if (input_debug->ifdmap != (RFDT *) NULL) + esym->ifd = input_debug->ifdmap[esym->ifd]; + } + + return true; +} + +/* Set the external symbol index. This routine is passed to + bfd_ecoff_debug_externals. */ + +static void +ecoff_set_index (sym, indx) + asymbol *sym; + bfd_size_type indx; +{ + ecoff_set_sym_index (sym, indx); +} + +/* Write out an ECOFF file. */ + +boolean +_bfd_ecoff_write_object_contents (abfd) + bfd *abfd; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + const bfd_vma round = backend->round; + const bfd_size_type filhsz = bfd_coff_filhsz (abfd); + const bfd_size_type aoutsz = bfd_coff_aoutsz (abfd); + const bfd_size_type scnhsz = bfd_coff_scnhsz (abfd); + const bfd_size_type external_hdr_size + = backend->debug_swap.external_hdr_size; + const bfd_size_type external_reloc_size = backend->external_reloc_size; + void (* const adjust_reloc_out) PARAMS ((bfd *, + const arelent *, + struct internal_reloc *)) + = backend->adjust_reloc_out; + void (* const swap_reloc_out) PARAMS ((bfd *, + const struct internal_reloc *, + PTR)) + = backend->swap_reloc_out; + struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info; + HDRR * const symhdr = &debug->symbolic_header; + asection *current; + unsigned int count; + bfd_size_type reloc_size; + bfd_size_type text_size; + bfd_vma text_start; + boolean set_text_start; + bfd_size_type data_size; + bfd_vma data_start; + boolean set_data_start; + bfd_size_type bss_size; + PTR buff = NULL; + PTR reloc_buff = NULL; + struct internal_filehdr internal_f; + struct internal_aouthdr internal_a; + int i; + + /* Determine where the sections and relocs will go in the output + file. */ + reloc_size = ecoff_compute_reloc_file_positions (abfd); + + count = 1; + for (current = abfd->sections; + current != (asection *)NULL; + current = current->next) + { + current->target_index = count; + ++count; + } + if ((abfd->flags & D_PAGED) != 0) - text_size = ecoff_sizeof_headers (abfd, false); + text_size = _bfd_ecoff_sizeof_headers (abfd, false); else text_size = 0; text_start = 0; + set_text_start = false; data_size = 0; data_start = 0; + set_data_start = false; bss_size = 0; /* Write section headers to the file. */ - buff = (PTR) alloca (scnhsz); + /* Allocate buff big enough to hold a section header, + file header, or a.out header. */ + { + bfd_size_type siz; + siz = scnhsz; + if (siz < filhsz) + siz = filhsz; + if (siz < aoutsz) + siz = aoutsz; + buff = (PTR) malloc (siz); + if (buff == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + } + internal_f.f_nscns = 0; if (bfd_seek (abfd, (file_ptr) (filhsz + aoutsz), SEEK_SET) != 0) - return false; + goto error_return; for (current = abfd->sections; current != (asection *) NULL; current = current->next) @@ -3238,24 +2739,11 @@ ecoff_write_object_contents (abfd) struct internal_scnhdr section; bfd_vma vma; - if (strcmp (current->name, SCOMMON) == 0) - { - BFD_ASSERT (bfd_get_section_size_before_reloc (current) == 0 - && current->reloc_count == 0); - continue; - } - if (strcmp (current->name, REGINFO) == 0) - { - BFD_ASSERT (current->reloc_count == 0); - continue; - } - ++internal_f.f_nscns; strncpy (section.s_name, current->name, sizeof section.s_name); - /* FIXME: is this correct for shared libraries? I think it is - but I have no platform to check. Ian Lance Taylor. */ + /* This seems to be correct for Irix 4 shared libraries. */ vma = bfd_get_section_vma (abfd, current); if (strcmp (current->name, _LIB) == 0) section.s_vaddr = 0; @@ -3279,7 +2767,16 @@ ecoff_write_object_contents (abfd) want the linker to compute the best size to use, or something. I don't know what happens if the information is not present. */ - section.s_lnnoptr = 0; + if (strcmp (current->name, _PDATA) != 0) + section.s_lnnoptr = 0; + else + { + /* The Alpha ECOFF .pdata section uses the lnnoptr field to + hold the number of entries in the section (each entry is + 8 bytes). We stored this in the line_filepos field in + ecoff_compute_section_file_positions. */ + section.s_lnnoptr = current->line_filepos; + } section.s_nreloc = current->reloc_count; section.s_nlnno = 0; @@ -3288,27 +2785,42 @@ ecoff_write_object_contents (abfd) bfd_coff_swap_scnhdr_out (abfd, (PTR) §ion, buff); if (bfd_write (buff, 1, scnhsz, abfd) != scnhsz) - return false; + goto error_return; - if ((section.s_flags & STYP_TEXT) != 0) + if ((section.s_flags & STYP_TEXT) != 0 + || ((section.s_flags & STYP_RDATA) != 0 + && backend->rdata_in_text) + || strcmp (current->name, _PDATA) == 0) { text_size += bfd_get_section_size_before_reloc (current); - if (text_start == 0 || text_start > vma) - text_start = vma; + if (! set_text_start || text_start > vma) + { + text_start = vma; + set_text_start = true; + } } else if ((section.s_flags & STYP_RDATA) != 0 || (section.s_flags & STYP_DATA) != 0 + || (section.s_flags & STYP_LITA) != 0 || (section.s_flags & STYP_LIT8) != 0 || (section.s_flags & STYP_LIT4) != 0 - || (section.s_flags & STYP_SDATA) != 0) + || (section.s_flags & STYP_SDATA) != 0 + || strcmp (current->name, _XDATA) == 0) { data_size += bfd_get_section_size_before_reloc (current); - if (data_start == 0 || data_start > vma) - data_start = vma; + if (! set_data_start || data_start > vma) + { + data_start = vma; + set_data_start = true; + } } else if ((section.s_flags & STYP_BSS) != 0 || (section.s_flags & STYP_SBSS) != 0) bss_size += bfd_get_section_size_before_reloc (current); + else if ((section.s_flags & STYP_ECOFF_LIB) != 0) + /* Do nothing */ ; + else + abort (); } /* Set up the file header. */ @@ -3327,7 +2839,7 @@ ecoff_write_object_contents (abfd) /* The ECOFF f_nsyms field is not actually the number of symbols, it's the size of symbolic information header. */ internal_f.f_nsyms = external_hdr_size; - internal_f.f_symptr = sym_base; + internal_f.f_symptr = ecoff_data (abfd)->sym_filepos; } else { @@ -3356,9 +2868,8 @@ ecoff_write_object_contents (abfd) else internal_a.magic = ECOFF_AOUT_OMAGIC; - /* FIXME: This is what Ultrix puts in, and it makes the Ultrix - linker happy. But, is it right? */ - internal_a.vstamp = 0x20a; + /* FIXME: Is this really correct? */ + internal_a.vstamp = symhdr->vstamp; /* At least on Ultrix, these have to be rounded to page boundaries. FIXME: Is this true on other platforms? */ @@ -3401,171 +2912,182 @@ ecoff_write_object_contents (abfd) /* Write out the file header and the optional header. */ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) - return false; + goto error_return; - buff = (PTR) alloca (filhsz); bfd_coff_swap_filehdr_out (abfd, (PTR) &internal_f, buff); if (bfd_write (buff, 1, filhsz, abfd) != filhsz) - return false; + goto error_return; - buff = (PTR) alloca (aoutsz); bfd_coff_swap_aouthdr_out (abfd, (PTR) &internal_a, buff); if (bfd_write (buff, 1, aoutsz, abfd) != aoutsz) - return false; + goto error_return; - /* Write out the relocs. */ - for (current = abfd->sections; - current != (asection *) NULL; - current = current->next) + /* Build the external symbol information. This must be done before + writing out the relocs so that we know the symbol indices. We + don't do this if this BFD was created by the backend linker, + since it will have already handled the symbols and relocs. */ + if (! ecoff_data (abfd)->linker) { - arelent **reloc_ptr_ptr; - arelent **reloc_end; - char *out_ptr; + symhdr->iextMax = 0; + symhdr->issExtMax = 0; + debug->external_ext = debug->external_ext_end = NULL; + debug->ssext = debug->ssext_end = NULL; + if (bfd_ecoff_debug_externals (abfd, debug, &backend->debug_swap, + (((abfd->flags & EXEC_P) == 0) + ? true : false), + ecoff_get_extr, ecoff_set_index) + == false) + goto error_return; - if (current->reloc_count == 0) - continue; - - buff = bfd_alloc (abfd, current->reloc_count * external_reloc_size); - if (buff == NULL) + /* Write out the relocs. */ + for (current = abfd->sections; + current != (asection *) NULL; + current = current->next) { - bfd_error = no_memory; - return false; - } + arelent **reloc_ptr_ptr; + arelent **reloc_end; + char *out_ptr; - reloc_ptr_ptr = current->orelocation; - reloc_end = reloc_ptr_ptr + current->reloc_count; - out_ptr = (char *) buff; - for (; - reloc_ptr_ptr < reloc_end; - reloc_ptr_ptr++, out_ptr += external_reloc_size) - { - arelent *reloc; - asymbol *sym; - struct internal_reloc in; + if (current->reloc_count == 0) + continue; + + reloc_buff = + bfd_alloc (abfd, current->reloc_count * external_reloc_size); + if (reloc_buff == NULL) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + reloc_ptr_ptr = current->orelocation; + reloc_end = reloc_ptr_ptr + current->reloc_count; + out_ptr = (char *) reloc_buff; + for (; + reloc_ptr_ptr < reloc_end; + reloc_ptr_ptr++, out_ptr += external_reloc_size) + { + arelent *reloc; + asymbol *sym; + struct internal_reloc in; - memset (&in, 0, sizeof in); + memset ((PTR) &in, 0, sizeof in); - reloc = *reloc_ptr_ptr; - sym = *reloc->sym_ptr_ptr; + reloc = *reloc_ptr_ptr; + sym = *reloc->sym_ptr_ptr; - in.r_vaddr = reloc->address + bfd_get_section_vma (abfd, current); - in.r_type = reloc->howto->type; + in.r_vaddr = (reloc->address + + bfd_get_section_vma (abfd, current)); + in.r_type = reloc->howto->type; - if ((sym->flags & BSF_SECTION_SYM) == 0) - { - in.r_symndx = ecoff_get_sym_index (*reloc->sym_ptr_ptr); - in.r_extern = 1; - } - else - { - CONST char *name; - - name = bfd_get_section_name (abfd, bfd_get_section (sym)); - if (strcmp (name, ".text") == 0) - in.r_symndx = RELOC_SECTION_TEXT; - else if (strcmp (name, ".rdata") == 0) - in.r_symndx = RELOC_SECTION_RDATA; - else if (strcmp (name, ".data") == 0) - in.r_symndx = RELOC_SECTION_DATA; - else if (strcmp (name, ".sdata") == 0) - in.r_symndx = RELOC_SECTION_SDATA; - else if (strcmp (name, ".sbss") == 0) - in.r_symndx = RELOC_SECTION_SBSS; - else if (strcmp (name, ".bss") == 0) - in.r_symndx = RELOC_SECTION_BSS; - else if (strcmp (name, ".init") == 0) - in.r_symndx = RELOC_SECTION_INIT; - else if (strcmp (name, ".lit8") == 0) - in.r_symndx = RELOC_SECTION_LIT8; - else if (strcmp (name, ".lit4") == 0) - in.r_symndx = RELOC_SECTION_LIT4; + if ((sym->flags & BSF_SECTION_SYM) == 0) + { + in.r_symndx = ecoff_get_sym_index (*reloc->sym_ptr_ptr); + in.r_extern = 1; + } else - abort (); - in.r_extern = 0; + { + CONST char *name; + + name = bfd_get_section_name (abfd, bfd_get_section (sym)); + if (strcmp (name, ".text") == 0) + in.r_symndx = RELOC_SECTION_TEXT; + else if (strcmp (name, ".rdata") == 0) + in.r_symndx = RELOC_SECTION_RDATA; + else if (strcmp (name, ".data") == 0) + in.r_symndx = RELOC_SECTION_DATA; + else if (strcmp (name, ".sdata") == 0) + in.r_symndx = RELOC_SECTION_SDATA; + else if (strcmp (name, ".sbss") == 0) + in.r_symndx = RELOC_SECTION_SBSS; + else if (strcmp (name, ".bss") == 0) + in.r_symndx = RELOC_SECTION_BSS; + else if (strcmp (name, ".init") == 0) + in.r_symndx = RELOC_SECTION_INIT; + else if (strcmp (name, ".lit8") == 0) + in.r_symndx = RELOC_SECTION_LIT8; + else if (strcmp (name, ".lit4") == 0) + in.r_symndx = RELOC_SECTION_LIT4; + else if (strcmp (name, ".xdata") == 0) + in.r_symndx = RELOC_SECTION_XDATA; + else if (strcmp (name, ".pdata") == 0) + in.r_symndx = RELOC_SECTION_PDATA; + else if (strcmp (name, ".fini") == 0) + in.r_symndx = RELOC_SECTION_FINI; + else if (strcmp (name, ".lita") == 0) + in.r_symndx = RELOC_SECTION_LITA; + else if (strcmp (name, "*ABS*") == 0) + in.r_symndx = RELOC_SECTION_ABS; + else + abort (); + in.r_extern = 0; + } + + (*adjust_reloc_out) (abfd, reloc, &in); + + (*swap_reloc_out) (abfd, &in, (PTR) out_ptr); } - (*swap_reloc_out) (abfd, &in, (PTR) out_ptr); + if (bfd_seek (abfd, current->rel_filepos, SEEK_SET) != 0) + goto error_return; + if (bfd_write (reloc_buff, + external_reloc_size, current->reloc_count, abfd) + != external_reloc_size * current->reloc_count) + goto error_return; + bfd_release (abfd, reloc_buff); + reloc_buff = NULL; } - if (bfd_seek (abfd, current->rel_filepos, SEEK_SET) != 0) - return false; - if (bfd_write (buff, external_reloc_size, current->reloc_count, abfd) - != external_reloc_size * current->reloc_count) - return false; - bfd_release (abfd, buff); + /* Write out the symbolic debugging information. */ + if (bfd_get_symcount (abfd) > 0) + { + /* Write out the debugging information. */ + if (bfd_ecoff_write_debug (abfd, debug, &backend->debug_swap, + ecoff_data (abfd)->sym_filepos) + == false) + goto error_return; + } } - /* Write out the symbolic debugging information. */ - if (bfd_get_symcount (abfd) > 0) - { - HDRR *symhdr; - unsigned long sym_offset; - - /* Set up the offsets in the symbolic header. */ - symhdr = &ecoff_data (abfd)->symbolic_header; - sym_offset = ecoff_data (abfd)->sym_filepos + external_hdr_size; - -#define SET(offset, size, ptr) \ - if (symhdr->size == 0) \ - symhdr->offset = 0; \ - else \ - symhdr->offset = (((char *) ecoff_data (abfd)->ptr \ - - (char *) ecoff_data (abfd)->raw_syments) \ - + sym_offset); - - SET (cbLineOffset, cbLine, line); - SET (cbDnOffset, idnMax, external_dnr); - SET (cbPdOffset, ipdMax, external_pdr); - SET (cbSymOffset, isymMax, external_sym); - SET (cbOptOffset, ioptMax, external_opt); - SET (cbAuxOffset, iauxMax, external_aux); - SET (cbSsOffset, issMax, ss); - SET (cbSsExtOffset, issExtMax, ssext); - SET (cbFdOffset, ifdMax, external_fdr); - SET (cbRfdOffset, crfd, external_rfd); - SET (cbExtOffset, iextMax, external_ext); -#undef SET - - if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos, - SEEK_SET) != 0) - return false; - buff = (PTR) alloca (external_hdr_size); - (*backend->swap_hdr_out) (abfd, &ecoff_data (abfd)->symbolic_header, - buff); - if (bfd_write (buff, 1, external_hdr_size, abfd) != external_hdr_size) - return false; - if (bfd_write ((PTR) ecoff_data (abfd)->raw_syments, 1, - ecoff_data (abfd)->raw_size, abfd) - != ecoff_data (abfd)->raw_size) - return false; - } - else if ((abfd->flags & EXEC_P) != 0 - && (abfd->flags & D_PAGED) != 0) + /* The .bss section of a demand paged executable must receive an + entire page. If there are symbols, the symbols will start on the + next page. If there are no symbols, we must fill out the page by + hand. */ + if (bfd_get_symcount (abfd) == 0 + && (abfd->flags & EXEC_P) != 0 + && (abfd->flags & D_PAGED) != 0) { char c; - /* A demand paged executable must occupy an even number of - pages. */ if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1, SEEK_SET) != 0) - return false; + goto error_return; if (bfd_read (&c, 1, 1, abfd) == 0) c = 0; if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1, SEEK_SET) != 0) - return false; + goto error_return; if (bfd_write (&c, 1, 1, abfd) != 1) - return false; + goto error_return; } + if (reloc_buff != NULL) + bfd_release (abfd, reloc_buff); + if (buff != NULL) + free (buff); return true; + error_return: + if (reloc_buff != NULL) + bfd_release (abfd, reloc_buff); + if (buff != NULL) + free (buff); + return false; } /* Archive handling. ECOFF uses what appears to be a unique type of - archive header (which I call an armap). The byte ordering of the - armap and the contents are encoded in the name of the armap itself. - At least for now, we only support archives with the same byte - ordering in the armap and the contents. + archive header (armap). The byte ordering of the armap and the + contents are encoded in the name of the armap itself. At least for + now, we only support archives with the same byte ordering in the + armap and the contents. The first four bytes in the armap are the number of symbol definitions. This is always a power of two. @@ -3581,10 +3103,6 @@ ecoff_write_object_contents (abfd) The symbols are hashed into the armap with a closed hashing scheme. See the functions below for the details of the algorithm. - We could use the hash table when looking up symbols in a library. - This would require a new BFD target entry point to replace the - bfd_get_next_mapent function used by the linker. - After the symbol definitions comes four bytes holding the size of the string table, followed by the string table itself. */ @@ -3634,7 +3152,7 @@ ecoff_armap_hash (s, rehash, size, hlog) /* Read in the armap. */ boolean -ecoff_slurp_armap (abfd) +_bfd_ecoff_slurp_armap (abfd) bfd *abfd; { char nextname[17]; @@ -3655,7 +3173,8 @@ ecoff_slurp_armap (abfd) if (i != 16) return false; - bfd_seek (abfd, (file_ptr) -16, SEEK_CUR); + if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0) + return false; /* Irix 4.0.5F apparently can use either an ECOFF armap or a standard COFF armap. We could move the ECOFF armap stuff into @@ -3687,13 +3206,13 @@ ecoff_slurp_armap (abfd) || ((nextname[ARMAP_OBJECT_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN) ^ (abfd->xvec->byteorder_big_p != false))) { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return false; } /* Read in the armap. */ ardata = bfd_ardata (abfd); - mapdata = snarf_ar_hdr (abfd); + mapdata = _bfd_snarf_ar_hdr (abfd); if (mapdata == (struct areltdata *) NULL) return false; parsed_size = mapdata->parsed_size; @@ -3702,17 +3221,20 @@ ecoff_slurp_armap (abfd) raw_armap = (char *) bfd_alloc (abfd, parsed_size); if (raw_armap == (char *) NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size) { - bfd_error = malformed_archive; + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_malformed_archive); bfd_release (abfd, (PTR) raw_armap); return false; } + ardata->tdata = (PTR) raw_armap; + count = bfd_h_get_32 (abfd, (PTR) raw_armap); ardata->symdef_count = 0; @@ -3769,6 +3291,12 @@ ecoff_slurp_armap (abfd) symdef_ptr = ((struct symdef *) bfd_alloc (abfd, ardata->symdef_count * sizeof (struct symdef))); + if (!symdef_ptr) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + ardata->symdefs = (carsym *) symdef_ptr; raw_ptr = raw_armap + 4; @@ -3797,7 +3325,7 @@ ecoff_slurp_armap (abfd) /* Write out an armap. */ boolean -ecoff_write_armap (abfd, elength, map, orl_count, stridx) +_bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx) bfd *abfd; unsigned int elength; struct orl *map; @@ -3864,7 +3392,7 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) sprintf (hdr.ar_size, "%-10d", (int) mapsize); hdr.ar_fmag[0] = '`'; - hdr.ar_fmag[1] = '\n'; + hdr.ar_fmag[1] = '\012'; /* Turn all null bytes in the header into spaces. */ for (i = 0; i < sizeof (struct ar_hdr); i++) @@ -3875,11 +3403,16 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) != sizeof (struct ar_hdr)) return false; - bfd_h_put_32 (abfd, hashsize, temp); - if (bfd_write (temp, 1, 4, abfd) != 4) + bfd_h_put_32 (abfd, (bfd_vma) hashsize, temp); + if (bfd_write ((PTR) temp, 1, 4, abfd) != 4) return false; hashtable = (bfd_byte *) bfd_zalloc (abfd, symdefsize); + if (!hashtable) + { + bfd_set_error (bfd_error_no_memory); + return false; + } current = abfd->archive_head; last_elt = current; @@ -3919,18 +3452,20 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) hash = srch; } - bfd_h_put_32 (abfd, map[i].namidx, (PTR) (hashtable + hash * 8)); - bfd_h_put_32 (abfd, firstreal, (PTR) (hashtable + hash * 8 + 4)); + bfd_h_put_32 (abfd, (bfd_vma) map[i].namidx, + (PTR) (hashtable + hash * 8)); + bfd_h_put_32 (abfd, (bfd_vma) firstreal, + (PTR) (hashtable + hash * 8 + 4)); } - if (bfd_write (hashtable, 1, symdefsize, abfd) != symdefsize) + if (bfd_write ((PTR) hashtable, 1, symdefsize, abfd) != symdefsize) return false; bfd_release (abfd, hashtable); /* Now write the strings. */ - bfd_h_put_32 (abfd, stringsize, temp); - if (bfd_write (temp, 1, 4, abfd) != 4) + bfd_h_put_32 (abfd, (bfd_vma) stringsize, temp); + if (bfd_write ((PTR) temp, 1, 4, abfd) != 4) return false; for (i = 0; i < orl_count; i++) { @@ -3945,7 +3480,7 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) bug-compatible for DECstation ar we use a null. */ if (padit) { - if (bfd_write ("\0", 1, 1, abfd) != 1) + if (bfd_write ("", 1, 1, abfd) != 1) return false; } @@ -3955,8 +3490,8 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) /* See whether this BFD is an archive. If it is, read in the armap and the extended name table. */ -bfd_target * -ecoff_archive_p (abfd) +const bfd_target * +_bfd_ecoff_archive_p (abfd) bfd *abfd; { char armag[SARMAG + 1]; @@ -3964,8 +3499,9 @@ ecoff_archive_p (abfd) if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG || strncmp (armag, ARMAG, SARMAG) != 0) { - bfd_error = wrong_format; - return (bfd_target *) NULL; + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); + return (const bfd_target *) NULL; } /* We are setting bfd_ardata(abfd) here, but since bfd_ardata @@ -3976,19 +3512,1442 @@ ecoff_archive_p (abfd) if (bfd_ardata (abfd) == (struct artdata *) NULL) { - bfd_error = no_memory; - return (bfd_target *) NULL; + bfd_set_error (bfd_error_no_memory); + return (const bfd_target *) NULL; } bfd_ardata (abfd)->first_file_filepos = SARMAG; + bfd_ardata (abfd)->cache = NULL; + bfd_ardata (abfd)->archive_head = NULL; + bfd_ardata (abfd)->symdefs = NULL; + bfd_ardata (abfd)->extended_names = NULL; + bfd_ardata (abfd)->tdata = NULL; - if (ecoff_slurp_armap (abfd) == false - || ecoff_slurp_extended_name_table (abfd) == false) + if (_bfd_ecoff_slurp_armap (abfd) == false + || _bfd_ecoff_slurp_extended_name_table (abfd) == false) { bfd_release (abfd, bfd_ardata (abfd)); abfd->tdata.aout_ar_data = (struct artdata *) NULL; - return (bfd_target *) NULL; + return (const bfd_target *) NULL; } return abfd->xvec; } + +/* ECOFF linker code. */ + +static struct bfd_hash_entry *ecoff_link_hash_newfunc + PARAMS ((struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string)); +static boolean ecoff_link_add_archive_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean ecoff_link_check_archive_element + PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded)); +static boolean ecoff_link_add_object_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean ecoff_link_add_externals + PARAMS ((bfd *, struct bfd_link_info *, PTR, char *)); + +/* Routine to create an entry in an ECOFF link hash table. */ + +static struct bfd_hash_entry * +ecoff_link_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct ecoff_link_hash_entry *ret = (struct ecoff_link_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct ecoff_link_hash_entry *) NULL) + ret = ((struct ecoff_link_hash_entry *) + bfd_hash_allocate (table, sizeof (struct ecoff_link_hash_entry))); + if (ret == (struct ecoff_link_hash_entry *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + + /* Call the allocation method of the superclass. */ + ret = ((struct ecoff_link_hash_entry *) + _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, + table, string)); + + if (ret) + { + /* Set local fields. */ + ret->indx = -1; + ret->abfd = NULL; + ret->written = 0; + ret->small = 0; + } + memset ((PTR) &ret->esym, 0, sizeof ret->esym); + + return (struct bfd_hash_entry *) ret; +} + +/* Create an ECOFF link hash table. */ + +struct bfd_link_hash_table * +_bfd_ecoff_bfd_link_hash_table_create (abfd) + bfd *abfd; +{ + struct ecoff_link_hash_table *ret; + + ret = ((struct ecoff_link_hash_table *) + malloc (sizeof (struct ecoff_link_hash_table))); + if (!ret) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + if (! _bfd_link_hash_table_init (&ret->root, abfd, + ecoff_link_hash_newfunc)) + { + free (ret); + return (struct bfd_link_hash_table *) NULL; + } + return &ret->root; +} + +/* Look up an entry in an ECOFF link hash table. */ + +#define ecoff_link_hash_lookup(table, string, create, copy, follow) \ + ((struct ecoff_link_hash_entry *) \ + bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow))) + +/* Traverse an ECOFF link hash table. */ + +#define ecoff_link_hash_traverse(table, func, info) \ + (bfd_link_hash_traverse \ + (&(table)->root, \ + (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \ + (info))) + +/* Get the ECOFF link hash table from the info structure. This is + just a cast. */ + +#define ecoff_hash_table(p) ((struct ecoff_link_hash_table *) ((p)->hash)) + +/* Given an ECOFF BFD, add symbols to the global hash table as + appropriate. */ + +boolean +_bfd_ecoff_bfd_link_add_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + switch (bfd_get_format (abfd)) + { + case bfd_object: + return ecoff_link_add_object_symbols (abfd, info); + case bfd_archive: + return ecoff_link_add_archive_symbols (abfd, info); + default: + bfd_set_error (bfd_error_wrong_format); + return false; + } +} + +/* Add the symbols from an archive file to the global hash table. + This looks through the undefined symbols, looks each one up in the + archive hash table, and adds any associated object file. We do not + use _bfd_generic_link_add_archive_symbols because ECOFF archives + already have a hash table, so there is no reason to construct + another one. */ + +static boolean +ecoff_link_add_archive_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + const bfd_byte *raw_armap; + struct bfd_link_hash_entry **pundef; + unsigned int armap_count; + unsigned int armap_log; + unsigned int i; + const bfd_byte *hashtable; + const char *stringbase; + + if (! bfd_has_map (abfd)) + { + bfd_set_error (bfd_error_no_symbols); + return false; + } + + /* If we don't have any raw data for this archive, as can happen on + Irix 4.0.5F, we call the generic routine. + FIXME: We should be more clever about this, since someday tdata + may get to something for a generic archive. */ + raw_armap = (const bfd_byte *) bfd_ardata (abfd)->tdata; + if (raw_armap == (bfd_byte *) NULL) + return (_bfd_generic_link_add_archive_symbols + (abfd, info, ecoff_link_check_archive_element)); + + armap_count = bfd_h_get_32 (abfd, raw_armap); + + armap_log = 0; + for (i = 1; i < armap_count; i <<= 1) + armap_log++; + BFD_ASSERT (i == armap_count); + + hashtable = raw_armap + 4; + stringbase = (const char *) raw_armap + armap_count * 8 + 8; + + /* Look through the list of undefined symbols. */ + pundef = &info->hash->undefs; + while (*pundef != (struct bfd_link_hash_entry *) NULL) + { + struct bfd_link_hash_entry *h; + unsigned int hash, rehash; + unsigned int file_offset; + const char *name; + bfd *element; + + h = *pundef; + + /* When a symbol is defined, it is not necessarily removed from + the list. */ + if (h->type != bfd_link_hash_undefined + && h->type != bfd_link_hash_common) + { + /* Remove this entry from the list, for general cleanliness + and because we are going to look through the list again + if we search any more libraries. We can't remove the + entry if it is the tail, because that would lose any + entries we add to the list later on. */ + if (*pundef != info->hash->undefs_tail) + *pundef = (*pundef)->next; + else + pundef = &(*pundef)->next; + continue; + } + + /* Native ECOFF linkers do not pull in archive elements merely + to satisfy common definitions, so neither do we. We leave + them on the list, though, in case we are linking against some + other object format. */ + if (h->type != bfd_link_hash_undefined) + { + pundef = &(*pundef)->next; + continue; + } + + /* Look for this symbol in the archive hash table. */ + hash = ecoff_armap_hash (h->root.string, &rehash, armap_count, + armap_log); + + file_offset = bfd_h_get_32 (abfd, hashtable + (hash * 8) + 4); + if (file_offset == 0) + { + /* Nothing in this slot. */ + pundef = &(*pundef)->next; + continue; + } + + name = stringbase + bfd_h_get_32 (abfd, hashtable + (hash * 8)); + if (name[0] != h->root.string[0] + || strcmp (name, h->root.string) != 0) + { + unsigned int srch; + boolean found; + + /* That was the wrong symbol. Try rehashing. */ + found = false; + for (srch = (hash + rehash) & (armap_count - 1); + srch != hash; + srch = (srch + rehash) & (armap_count - 1)) + { + file_offset = bfd_h_get_32 (abfd, hashtable + (srch * 8) + 4); + if (file_offset == 0) + break; + name = stringbase + bfd_h_get_32 (abfd, hashtable + (srch * 8)); + if (name[0] == h->root.string[0] + && strcmp (name, h->root.string) == 0) + { + found = true; + break; + } + } + + if (! found) + { + pundef = &(*pundef)->next; + continue; + } + + hash = srch; + } + + element = _bfd_get_elt_at_filepos (abfd, file_offset); + if (element == (bfd *) NULL) + return false; + + if (! bfd_check_format (element, bfd_object)) + return false; + + /* Unlike the generic linker, we know that this element provides + a definition for an undefined symbol and we know that we want + to include it. We don't need to check anything. */ + if (! (*info->callbacks->add_archive_element) (info, element, name)) + return false; + if (! ecoff_link_add_object_symbols (element, info)) + return false; + + pundef = &(*pundef)->next; + } + + return true; +} + +/* This is called if we used _bfd_generic_link_add_archive_symbols + because we were not dealing with an ECOFF archive. */ + +static boolean +ecoff_link_check_archive_element (abfd, info, pneeded) + bfd *abfd; + struct bfd_link_info *info; + boolean *pneeded; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)) + = backend->debug_swap.swap_ext_in; + HDRR *symhdr; + bfd_size_type external_ext_size; + PTR external_ext = NULL; + size_t esize; + char *ssext = NULL; + char *ext_ptr; + char *ext_end; + + *pneeded = false; + + if (! ecoff_slurp_symbolic_header (abfd)) + goto error_return; + + /* If there are no symbols, we don't want it. */ + if (bfd_get_symcount (abfd) == 0) + goto successful_return; + + symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; + + /* Read in the external symbols and external strings. */ + external_ext_size = backend->debug_swap.external_ext_size; + esize = symhdr->iextMax * external_ext_size; + external_ext = (PTR) malloc (esize); + if (external_ext == NULL && esize != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbExtOffset, SEEK_SET) != 0 + || bfd_read (external_ext, 1, esize, abfd) != esize) + goto error_return; + + ssext = (char *) malloc (symhdr->issExtMax); + if (ssext == NULL && symhdr->issExtMax != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0 + || bfd_read (ssext, 1, symhdr->issExtMax, abfd) != symhdr->issExtMax) + goto error_return; + + /* Look through the external symbols to see if they define some + symbol that is currently undefined. */ + ext_ptr = (char *) external_ext; + ext_end = ext_ptr + esize; + for (; ext_ptr < ext_end; ext_ptr += external_ext_size) + { + EXTR esym; + boolean def; + const char *name; + struct bfd_link_hash_entry *h; + + (*swap_ext_in) (abfd, (PTR) ext_ptr, &esym); + + /* See if this symbol defines something. */ + if (esym.asym.st != stGlobal + && esym.asym.st != stLabel + && esym.asym.st != stProc) + continue; + + switch (esym.asym.sc) + { + case scText: + case scData: + case scBss: + case scAbs: + case scSData: + case scSBss: + case scRData: + case scCommon: + case scSCommon: + case scInit: + case scFini: + def = true; + break; + default: + def = false; + break; + } + + if (! def) + continue; + + name = ssext + esym.asym.iss; + h = bfd_link_hash_lookup (info->hash, name, false, false, true); + + /* Unlike the generic linker, we do not pull in elements because + of common symbols. */ + if (h == (struct bfd_link_hash_entry *) NULL + || h->type != bfd_link_hash_undefined) + continue; + + /* Include this element. */ + if (! (*info->callbacks->add_archive_element) (info, abfd, name)) + goto error_return; + if (! ecoff_link_add_externals (abfd, info, external_ext, ssext)) + goto error_return; + + *pneeded = true; + goto successful_return; + } + + successful_return: + if (external_ext != NULL) + free (external_ext); + if (ssext != NULL) + free (ssext); + return true; + error_return: + if (external_ext != NULL) + free (external_ext); + if (ssext != NULL) + free (ssext); + return false; +} + +/* Add symbols from an ECOFF object file to the global linker hash + table. */ + +static boolean +ecoff_link_add_object_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + HDRR *symhdr; + bfd_size_type external_ext_size; + PTR external_ext = NULL; + size_t esize; + char *ssext = NULL; + boolean result; + + if (! ecoff_slurp_symbolic_header (abfd)) + return false; + + /* If there are no symbols, we don't want it. */ + if (bfd_get_symcount (abfd) == 0) + return true; + + symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; + + /* Read in the external symbols and external strings. */ + external_ext_size = ecoff_backend (abfd)->debug_swap.external_ext_size; + esize = symhdr->iextMax * external_ext_size; + external_ext = (PTR) malloc (esize); + if (external_ext == NULL && esize != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbExtOffset, SEEK_SET) != 0 + || bfd_read (external_ext, 1, esize, abfd) != esize) + goto error_return; + + ssext = (char *) malloc (symhdr->issExtMax); + if (ssext == NULL && symhdr->issExtMax != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0 + || bfd_read (ssext, 1, symhdr->issExtMax, abfd) != symhdr->issExtMax) + goto error_return; + + result = ecoff_link_add_externals (abfd, info, external_ext, ssext); + + if (ssext != NULL) + free (ssext); + if (external_ext != NULL) + free (external_ext); + return result; + + error_return: + if (ssext != NULL) + free (ssext); + if (external_ext != NULL) + free (external_ext); + return false; +} + +/* Add the external symbols of an object file to the global linker + hash table. The external symbols and strings we are passed are + just allocated on the stack, and will be discarded. We must + explicitly save any information we may need later on in the link. + We do not want to read the external symbol information again. */ + +static boolean +ecoff_link_add_externals (abfd, info, external_ext, ssext) + bfd *abfd; + struct bfd_link_info *info; + PTR external_ext; + char *ssext; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)) + = backend->debug_swap.swap_ext_in; + bfd_size_type external_ext_size = backend->debug_swap.external_ext_size; + unsigned long ext_count; + struct ecoff_link_hash_entry **sym_hash; + char *ext_ptr; + char *ext_end; + + ext_count = ecoff_data (abfd)->debug_info.symbolic_header.iextMax; + + sym_hash = ((struct ecoff_link_hash_entry **) + bfd_alloc (abfd, + ext_count * sizeof (struct bfd_link_hash_entry *))); + if (!sym_hash) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + ecoff_data (abfd)->sym_hashes = sym_hash; + + ext_ptr = (char *) external_ext; + ext_end = ext_ptr + ext_count * external_ext_size; + for (; ext_ptr < ext_end; ext_ptr += external_ext_size, sym_hash++) + { + EXTR esym; + boolean skip; + bfd_vma value; + asection *section; + const char *name; + struct ecoff_link_hash_entry *h; + + *sym_hash = NULL; + + (*swap_ext_in) (abfd, (PTR) ext_ptr, &esym); + + /* Skip debugging symbols. */ + skip = false; + switch (esym.asym.st) + { + case stGlobal: + case stStatic: + case stLabel: + case stProc: + case stStaticProc: + break; + default: + skip = true; + break; + } + + if (skip) + continue; + + /* Get the information for this symbol. */ + value = esym.asym.value; + switch (esym.asym.sc) + { + default: + case scNil: + case scRegister: + case scCdbLocal: + case scBits: + case scCdbSystem: + case scRegImage: + case scInfo: + case scUserStruct: + case scVar: + case scVarRegister: + case scVariant: + case scBasedVar: + case scXData: + case scPData: + section = NULL; + break; + case scText: + section = bfd_make_section_old_way (abfd, ".text"); + value -= section->vma; + break; + case scData: + section = bfd_make_section_old_way (abfd, ".data"); + value -= section->vma; + break; + case scBss: + section = bfd_make_section_old_way (abfd, ".bss"); + value -= section->vma; + break; + case scAbs: + section = bfd_abs_section_ptr; + break; + case scUndefined: + section = bfd_und_section_ptr; + break; + case scSData: + section = bfd_make_section_old_way (abfd, ".sdata"); + value -= section->vma; + break; + case scSBss: + section = bfd_make_section_old_way (abfd, ".sbss"); + value -= section->vma; + break; + case scRData: + section = bfd_make_section_old_way (abfd, ".rdata"); + value -= section->vma; + break; + case scCommon: + if (value > ecoff_data (abfd)->gp_size) + { + section = bfd_com_section_ptr; + break; + } + /* Fall through. */ + case scSCommon: + if (ecoff_scom_section.name == NULL) + { + /* Initialize the small common section. */ + ecoff_scom_section.name = SCOMMON; + ecoff_scom_section.flags = SEC_IS_COMMON; + ecoff_scom_section.output_section = &ecoff_scom_section; + ecoff_scom_section.symbol = &ecoff_scom_symbol; + ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr; + ecoff_scom_symbol.name = SCOMMON; + ecoff_scom_symbol.flags = BSF_SECTION_SYM; + ecoff_scom_symbol.section = &ecoff_scom_section; + ecoff_scom_symbol_ptr = &ecoff_scom_symbol; + } + section = &ecoff_scom_section; + break; + case scSUndefined: + section = bfd_und_section_ptr; + break; + case scInit: + section = bfd_make_section_old_way (abfd, ".init"); + value -= section->vma; + break; + case scFini: + section = bfd_make_section_old_way (abfd, ".fini"); + value -= section->vma; + break; + } + + if (section == (asection *) NULL) + continue; + + name = ssext + esym.asym.iss; + + h = NULL; + if (! (_bfd_generic_link_add_one_symbol + (info, abfd, name, BSF_GLOBAL, section, value, + (const char *) NULL, true, true, + (struct bfd_link_hash_entry **) &h))) + return false; + + *sym_hash = h; + + /* If we are building an ECOFF hash table, save the external + symbol information. */ + if (info->hash->creator->flavour == bfd_get_flavour (abfd)) + { + if (h->abfd == (bfd *) NULL + || (! bfd_is_und_section (section) + && (! bfd_is_com_section (section) + || h->root.type != bfd_link_hash_defined))) + { + h->abfd = abfd; + h->esym = esym; + } + + /* Remember whether this symbol was small undefined. */ + if (esym.asym.sc == scSUndefined) + h->small = 1; + + /* If this symbol was ever small undefined, it needs to wind + up in a GP relative section. We can't control the + section of a defined symbol, but we can control the + section of a common symbol. This case is actually needed + on Ultrix 4.2 to handle the symbol cred in -lckrb. */ + if (h->small + && h->root.type == bfd_link_hash_common + && strcmp (h->root.u.c.section->name, SCOMMON) != 0) + { + h->root.u.c.section = bfd_make_section_old_way (abfd, SCOMMON); + h->root.u.c.section->flags = SEC_ALLOC; + if (h->esym.asym.sc == scCommon) + h->esym.asym.sc = scSCommon; + } + } + } + + return true; +} + +/* ECOFF final link routines. */ + +static boolean ecoff_final_link_debug_accumulate + PARAMS ((bfd *output_bfd, bfd *input_bfd, struct bfd_link_info *, + PTR handle)); +static boolean ecoff_link_write_external + PARAMS ((struct ecoff_link_hash_entry *, PTR)); +static boolean ecoff_indirect_link_order + PARAMS ((bfd *, struct bfd_link_info *, asection *, + struct bfd_link_order *)); +static boolean ecoff_reloc_link_order + PARAMS ((bfd *, struct bfd_link_info *, asection *, + struct bfd_link_order *)); + +/* ECOFF final link routine. This looks through all the input BFDs + and gathers together all the debugging information, and then + processes all the link order information. This may cause it to + close and reopen some input BFDs; I'll see how bad this is. */ + +boolean +_bfd_ecoff_bfd_final_link (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + const struct ecoff_backend_data * const backend = ecoff_backend (abfd); + struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info; + HDRR *symhdr; + PTR handle; + register bfd *input_bfd; + asection *o; + struct bfd_link_order *p; + + /* We accumulate the debugging information counts in the symbolic + header. */ + symhdr = &debug->symbolic_header; + symhdr->vstamp = 0; + symhdr->ilineMax = 0; + symhdr->cbLine = 0; + symhdr->idnMax = 0; + symhdr->ipdMax = 0; + symhdr->isymMax = 0; + symhdr->ioptMax = 0; + symhdr->iauxMax = 0; + symhdr->issMax = 0; + symhdr->issExtMax = 0; + symhdr->ifdMax = 0; + symhdr->crfd = 0; + symhdr->iextMax = 0; + + /* We accumulate the debugging information itself in the debug_info + structure. */ + debug->line = NULL; + debug->external_dnr = NULL; + debug->external_pdr = NULL; + debug->external_sym = NULL; + debug->external_opt = NULL; + debug->external_aux = NULL; + debug->ss = NULL; + debug->ssext = debug->ssext_end = NULL; + debug->external_fdr = NULL; + debug->external_rfd = NULL; + debug->external_ext = debug->external_ext_end = NULL; + + handle = bfd_ecoff_debug_init (abfd, debug, &backend->debug_swap, info); + if (handle == (PTR) NULL) + return false; + + /* Accumulate the debugging symbols from each input BFD. */ + for (input_bfd = info->input_bfds; + input_bfd != (bfd *) NULL; + input_bfd = input_bfd->link_next) + { + boolean ret; + + if (bfd_get_flavour (input_bfd) == bfd_target_ecoff_flavour) + { + /* Abitrarily set the symbolic header vstamp to the vstamp + of the first object file in the link. */ + if (symhdr->vstamp == 0) + symhdr->vstamp + = ecoff_data (input_bfd)->debug_info.symbolic_header.vstamp; + ret = ecoff_final_link_debug_accumulate (abfd, input_bfd, info, + handle); + } + else + ret = bfd_ecoff_debug_accumulate_other (handle, abfd, + debug, &backend->debug_swap, + input_bfd, info); + if (! ret) + return false; + + /* Combine the register masks. */ + ecoff_data (abfd)->gprmask |= ecoff_data (input_bfd)->gprmask; + ecoff_data (abfd)->fprmask |= ecoff_data (input_bfd)->fprmask; + ecoff_data (abfd)->cprmask[0] |= ecoff_data (input_bfd)->cprmask[0]; + ecoff_data (abfd)->cprmask[1] |= ecoff_data (input_bfd)->cprmask[1]; + ecoff_data (abfd)->cprmask[2] |= ecoff_data (input_bfd)->cprmask[2]; + ecoff_data (abfd)->cprmask[3] |= ecoff_data (input_bfd)->cprmask[3]; + } + + /* Write out the external symbols. */ + ecoff_link_hash_traverse (ecoff_hash_table (info), + ecoff_link_write_external, + (PTR) abfd); + + if (info->relocateable) + { + /* We need to make a pass over the link_orders to count up the + number of relocations we will need to output, so that we know + how much space they will take up. */ + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + o->reloc_count = 0; + for (p = o->link_order_head; + p != (struct bfd_link_order *) NULL; + p = p->next) + if (p->type == bfd_indirect_link_order) + o->reloc_count += p->u.indirect.section->reloc_count; + else if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + ++o->reloc_count; + } + } + + /* Compute the reloc and symbol file positions. */ + ecoff_compute_reloc_file_positions (abfd); + + /* Write out the debugging information. */ + if (! bfd_ecoff_write_accumulated_debug (handle, abfd, debug, + &backend->debug_swap, info, + ecoff_data (abfd)->sym_filepos)) + return false; + + bfd_ecoff_debug_free (handle, abfd, debug, &backend->debug_swap, info); + + if (info->relocateable) + { + /* Now reset the reloc_count field of the sections in the output + BFD to 0, so that we can use them to keep track of how many + relocs we have output thus far. */ + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + o->reloc_count = 0; + } + + /* Get a value for the GP register. */ + if (ecoff_data (abfd)->gp == 0) + { + struct bfd_link_hash_entry *h; + + h = bfd_link_hash_lookup (info->hash, "_gp", false, false, true); + if (h != (struct bfd_link_hash_entry *) NULL + && h->type == bfd_link_hash_defined) + ecoff_data (abfd)->gp = (h->u.def.value + + h->u.def.section->output_section->vma + + h->u.def.section->output_offset); + else if (info->relocateable) + { + bfd_vma lo; + + /* Make up a value. */ + lo = (bfd_vma) -1; + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + if (o->vma < lo + && (strcmp (o->name, _SBSS) == 0 + || strcmp (o->name, _SDATA) == 0 + || strcmp (o->name, _LIT4) == 0 + || strcmp (o->name, _LIT8) == 0 + || strcmp (o->name, _LITA) == 0)) + lo = o->vma; + } + ecoff_data (abfd)->gp = lo + 0x8000; + } + else + { + /* If the relocate_section function needs to do a reloc + involving the GP value, it should make a reloc_dangerous + callback to warn that GP is not defined. */ + } + } + + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + for (p = o->link_order_head; + p != (struct bfd_link_order *) NULL; + p = p->next) + { + if (p->type == bfd_indirect_link_order + && (bfd_get_flavour (p->u.indirect.section->owner) + == bfd_target_ecoff_flavour)) + { + if (! ecoff_indirect_link_order (abfd, info, o, p)) + return false; + } + else if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + { + if (! ecoff_reloc_link_order (abfd, info, o, p)) + return false; + } + else + { + if (! _bfd_default_link_order (abfd, info, o, p)) + return false; + } + } + } + + bfd_get_symcount (abfd) = symhdr->iextMax + symhdr->isymMax; + + ecoff_data (abfd)->linker = true; + + return true; +} + +/* Accumulate the debugging information for an input BFD into the + output BFD. This must read in the symbolic information of the + input BFD. */ + +static boolean +ecoff_final_link_debug_accumulate (output_bfd, input_bfd, info, handle) + bfd *output_bfd; + bfd *input_bfd; + struct bfd_link_info *info; + PTR handle; +{ + struct ecoff_debug_info * const debug = &ecoff_data (input_bfd)->debug_info; + const struct ecoff_debug_swap * const swap = + &ecoff_backend (input_bfd)->debug_swap; + HDRR *symhdr = &debug->symbolic_header; + boolean ret; + +#define READ(ptr, offset, count, size, type) \ + if (symhdr->count == 0) \ + debug->ptr = NULL; \ + else \ + { \ + debug->ptr = (type) malloc (size * symhdr->count); \ + if (debug->ptr == NULL) \ + { \ + bfd_set_error (bfd_error_no_memory); \ + ret = false; \ + goto return_something; \ + } \ + if ((bfd_seek (input_bfd, (file_ptr) symhdr->offset, SEEK_SET) \ + != 0) \ + || (bfd_read (debug->ptr, size, symhdr->count, \ + input_bfd) != size * symhdr->count)) \ + { \ + ret = false; \ + goto return_something; \ + } \ + } + + /* If raw_syments is not NULL, then the data was already by read by + _bfd_ecoff_slurp_symbolic_info. */ + if (ecoff_data (input_bfd)->raw_syments == NULL) + { + READ (line, cbLineOffset, cbLine, sizeof (unsigned char), + unsigned char *); + READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR); + READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR); + READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR); + READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR); + READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext), + union aux_ext *); + READ (ss, cbSsOffset, issMax, sizeof (char), char *); + READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR); + READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR); + } +#undef READ + + /* We do not read the external strings or the external symbols. */ + + ret = (bfd_ecoff_debug_accumulate + (handle, output_bfd, &ecoff_data (output_bfd)->debug_info, + &ecoff_backend (output_bfd)->debug_swap, + input_bfd, debug, swap, info)); + + return_something: + if (ecoff_data (input_bfd)->raw_syments == NULL) + { + if (debug->line != NULL) + free (debug->line); + if (debug->external_dnr != NULL) + free (debug->external_dnr); + if (debug->external_pdr != NULL) + free (debug->external_pdr); + if (debug->external_sym != NULL) + free (debug->external_sym); + if (debug->external_opt != NULL) + free (debug->external_opt); + if (debug->external_aux != NULL) + free (debug->external_aux); + if (debug->ss != NULL) + free (debug->ss); + if (debug->external_fdr != NULL) + free (debug->external_fdr); + if (debug->external_rfd != NULL) + free (debug->external_rfd); + + /* Make sure we don't accidentally follow one of these pointers + into freed memory. */ + debug->line = NULL; + debug->external_dnr = NULL; + debug->external_pdr = NULL; + debug->external_sym = NULL; + debug->external_opt = NULL; + debug->external_aux = NULL; + debug->ss = NULL; + debug->external_fdr = NULL; + debug->external_rfd = NULL; + } + + return ret; +} + +/* Put out information for an external symbol. These come only from + the hash table. */ + +static boolean +ecoff_link_write_external (h, data) + struct ecoff_link_hash_entry *h; + PTR data; +{ + bfd *output_bfd = (bfd *) data; + + /* FIXME: We should check if this symbol is being stripped. */ + + if (h->written) + return true; + + if (h->abfd == (bfd *) NULL) + { + h->esym.jmptbl = 0; + h->esym.cobol_main = 0; + h->esym.weakext = 0; + h->esym.reserved = 0; + h->esym.ifd = ifdNil; + h->esym.asym.value = 0; + h->esym.asym.st = stGlobal; + + if (h->root.type != bfd_link_hash_defined) + h->esym.asym.sc = scAbs; + else + { + asection *output_section; + const char *name; + + output_section = h->root.u.def.section->output_section; + name = bfd_section_name (output_section->owner, output_section); + + if (strcmp (name, _TEXT) == 0) + h->esym.asym.sc = scText; + else if (strcmp (name, _DATA) == 0) + h->esym.asym.sc = scData; + else if (strcmp (name, _SDATA) == 0) + h->esym.asym.sc = scSData; + else if (strcmp (name, _RDATA) == 0) + h->esym.asym.sc = scRData; + else if (strcmp (name, _BSS) == 0) + h->esym.asym.sc = scBss; + else if (strcmp (name, _SBSS) == 0) + h->esym.asym.sc = scSBss; + else if (strcmp (name, _INIT) == 0) + h->esym.asym.sc = scInit; + else if (strcmp (name, _FINI) == 0) + h->esym.asym.sc = scFini; + else if (strcmp (name, _PDATA) == 0) + h->esym.asym.sc = scPData; + else if (strcmp (name, _XDATA) == 0) + h->esym.asym.sc = scXData; + else + h->esym.asym.sc = scAbs; + } + + h->esym.asym.reserved = 0; + h->esym.asym.index = indexNil; + } + else if (h->esym.ifd != -1) + { + struct ecoff_debug_info *debug; + + /* Adjust the FDR index for the symbol by that used for the + input BFD. */ + debug = &ecoff_data (h->abfd)->debug_info; + BFD_ASSERT (h->esym.ifd >= 0 + && h->esym.ifd < debug->symbolic_header.ifdMax); + h->esym.ifd = debug->ifdmap[h->esym.ifd]; + } + + switch (h->root.type) + { + default: + case bfd_link_hash_new: + abort (); + case bfd_link_hash_undefined: + case bfd_link_hash_weak: + if (h->esym.asym.sc != scUndefined + && h->esym.asym.sc != scSUndefined) + h->esym.asym.sc = scUndefined; + break; + case bfd_link_hash_defined: + if (h->esym.asym.sc == scUndefined + || h->esym.asym.sc == scSUndefined) + h->esym.asym.sc = scAbs; + else if (h->esym.asym.sc == scCommon) + h->esym.asym.sc = scBss; + else if (h->esym.asym.sc == scSCommon) + h->esym.asym.sc = scSBss; + h->esym.asym.value = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + break; + case bfd_link_hash_common: + if (h->esym.asym.sc != scCommon + && h->esym.asym.sc != scSCommon) + h->esym.asym.sc = scCommon; + h->esym.asym.value = h->root.u.c.size; + break; + case bfd_link_hash_indirect: + case bfd_link_hash_warning: + /* FIXME: Ignore these for now. The circumstances under which + they should be written out are not clear to me. */ + return true; + } + + /* bfd_ecoff_debug_one_external uses iextMax to keep track of the + symbol number. */ + h->indx = ecoff_data (output_bfd)->debug_info.symbolic_header.iextMax; + h->written = 1; + + return (bfd_ecoff_debug_one_external + (output_bfd, &ecoff_data (output_bfd)->debug_info, + &ecoff_backend (output_bfd)->debug_swap, h->root.root.string, + &h->esym)); +} + +/* Relocate and write an ECOFF section into an ECOFF output file. */ + +static boolean +ecoff_indirect_link_order (output_bfd, info, output_section, link_order) + bfd *output_bfd; + struct bfd_link_info *info; + asection *output_section; + struct bfd_link_order *link_order; +{ + asection *input_section; + bfd *input_bfd; + struct ecoff_section_tdata *section_tdata; + bfd_size_type raw_size; + bfd_size_type cooked_size; + bfd_byte *contents = NULL; + bfd_size_type external_reloc_size; + bfd_size_type external_relocs_size; + PTR external_relocs = NULL; + + BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0); + + if (link_order->size == 0) + return true; + + input_section = link_order->u.indirect.section; + input_bfd = input_section->owner; + section_tdata = ecoff_section_data (input_bfd, input_section); + + raw_size = input_section->_raw_size; + cooked_size = input_section->_cooked_size; + if (cooked_size == 0) + cooked_size = raw_size; + + BFD_ASSERT (input_section->output_section == output_section); + BFD_ASSERT (input_section->output_offset == link_order->offset); + BFD_ASSERT (cooked_size == link_order->size); + + /* Get the section contents. We allocate memory for the larger of + the size before relocating and the size after relocating. */ + contents = (bfd_byte *) malloc (raw_size >= cooked_size + ? raw_size + : cooked_size); + if (contents == NULL && raw_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + /* If we are relaxing, the contents may have already been read into + memory, in which case we copy them into our new buffer. We don't + simply reuse the old buffer in case cooked_size > raw_size. */ + if (section_tdata != (struct ecoff_section_tdata *) NULL + && section_tdata->contents != (bfd_byte *) NULL) + memcpy (contents, section_tdata->contents, raw_size); + else + { + if (! bfd_get_section_contents (input_bfd, input_section, + (PTR) contents, + (file_ptr) 0, raw_size)) + goto error_return; + } + + /* Get the relocs. If we are relaxing MIPS code, they will already + have been read in. Otherwise, we read them in now. */ + external_reloc_size = ecoff_backend (input_bfd)->external_reloc_size; + external_relocs_size = external_reloc_size * input_section->reloc_count; + + if (section_tdata != (struct ecoff_section_tdata *) NULL) + external_relocs = section_tdata->external_relocs; + else + { + external_relocs = (PTR) malloc (external_relocs_size); + if (external_relocs == NULL && external_relocs_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + + if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0 + || (bfd_read (external_relocs, 1, external_relocs_size, input_bfd) + != external_relocs_size)) + goto error_return; + } + + /* Relocate the section contents. */ + if (! ((*ecoff_backend (input_bfd)->relocate_section) + (output_bfd, info, input_bfd, input_section, contents, + external_relocs))) + goto error_return; + + /* Write out the relocated section. */ + if (! bfd_set_section_contents (output_bfd, + output_section, + (PTR) contents, + input_section->output_offset, + cooked_size)) + goto error_return; + + /* If we are producing relocateable output, the relocs were + modified, and we write them out now. We use the reloc_count + field of output_section to keep track of the number of relocs we + have output so far. */ + if (info->relocateable) + { + if (bfd_seek (output_bfd, + (output_section->rel_filepos + + output_section->reloc_count * external_reloc_size), + SEEK_SET) != 0 + || (bfd_write (external_relocs, 1, external_relocs_size, output_bfd) + != external_relocs_size)) + goto error_return; + output_section->reloc_count += input_section->reloc_count; + } + + if (contents != NULL) + free (contents); + if (external_relocs != NULL && section_tdata == NULL) + free (external_relocs); + return true; + + error_return: + if (contents != NULL) + free (contents); + if (external_relocs != NULL && section_tdata == NULL) + free (external_relocs); + return false; +} + +/* Generate a reloc when linking an ECOFF file. This is a reloc + requested by the linker, and does come from any input file. This + is used to build constructor and destructor tables when linking + with -Ur. */ + +static boolean +ecoff_reloc_link_order (output_bfd, info, output_section, link_order) + bfd *output_bfd; + struct bfd_link_info *info; + asection *output_section; + struct bfd_link_order *link_order; +{ + arelent rel; + struct internal_reloc in; + bfd_size_type external_reloc_size; + bfd_byte *rbuf; + boolean ok; + + /* We set up an arelent to pass to the backend adjust_reloc_out + routine. */ + rel.address = link_order->offset; + + rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc); + if (rel.howto == (const reloc_howto_type *) NULL) + { + bfd_set_error (bfd_error_bad_value); + return false; + } + + if (link_order->type == bfd_section_reloc_link_order) + rel.sym_ptr_ptr = link_order->u.reloc.p->u.section->symbol_ptr_ptr; + else + { + /* We can't set up a reloc against a symbol correctly, because + we have no asymbol structure. Currently no adjust_reloc_out + routine cases. */ + rel.sym_ptr_ptr = (asymbol **) NULL; + } + + /* All ECOFF relocs are in-place. Put the addend into the object + file. */ + + BFD_ASSERT (rel.howto->partial_inplace); + if (link_order->u.reloc.p->addend != 0) + { + bfd_size_type size; + bfd_reloc_status_type rstat; + bfd_byte *buf; + boolean ok; + + size = bfd_get_reloc_size (rel.howto); + buf = (bfd_byte *) bfd_zmalloc (size); + if (buf == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + rstat = _bfd_relocate_contents (rel.howto, output_bfd, + link_order->u.reloc.p->addend, buf); + switch (rstat) + { + case bfd_reloc_ok: + break; + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + if (! ((*info->callbacks->reloc_overflow) + (info, + (link_order->type == bfd_section_reloc_link_order + ? bfd_section_name (output_bfd, + link_order->u.reloc.p->u.section) + : link_order->u.reloc.p->u.name), + rel.howto->name, link_order->u.reloc.p->addend, + (bfd *) NULL, (asection *) NULL, (bfd_vma) 0))) + { + free (buf); + return false; + } + break; + } + ok = bfd_set_section_contents (output_bfd, output_section, (PTR) buf, + (file_ptr) link_order->offset, size); + free (buf); + if (! ok) + return false; + } + + rel.addend = 0; + + /* Move the information into a internal_reloc structure. */ + in.r_vaddr = (rel.address + + bfd_get_section_vma (output_bfd, output_section)); + in.r_type = rel.howto->type; + + if (link_order->type == bfd_symbol_reloc_link_order) + { + struct ecoff_link_hash_entry *h; + + h = ecoff_link_hash_lookup (ecoff_hash_table (info), + link_order->u.reloc.p->u.name, + false, false, true); + if (h != (struct ecoff_link_hash_entry *) NULL + && h->indx != -1) + in.r_symndx = h->indx; + else + { + if (! ((*info->callbacks->unattached_reloc) + (info, link_order->u.reloc.p->u.name, (bfd *) NULL, + (asection *) NULL, (bfd_vma) 0))) + return false; + in.r_symndx = 0; + } + in.r_extern = 1; + } + else + { + CONST char *name; + + name = bfd_get_section_name (output_bfd, + link_order->u.reloc.p->u.section); + if (strcmp (name, ".text") == 0) + in.r_symndx = RELOC_SECTION_TEXT; + else if (strcmp (name, ".rdata") == 0) + in.r_symndx = RELOC_SECTION_RDATA; + else if (strcmp (name, ".data") == 0) + in.r_symndx = RELOC_SECTION_DATA; + else if (strcmp (name, ".sdata") == 0) + in.r_symndx = RELOC_SECTION_SDATA; + else if (strcmp (name, ".sbss") == 0) + in.r_symndx = RELOC_SECTION_SBSS; + else if (strcmp (name, ".bss") == 0) + in.r_symndx = RELOC_SECTION_BSS; + else if (strcmp (name, ".init") == 0) + in.r_symndx = RELOC_SECTION_INIT; + else if (strcmp (name, ".lit8") == 0) + in.r_symndx = RELOC_SECTION_LIT8; + else if (strcmp (name, ".lit4") == 0) + in.r_symndx = RELOC_SECTION_LIT4; + else if (strcmp (name, ".xdata") == 0) + in.r_symndx = RELOC_SECTION_XDATA; + else if (strcmp (name, ".pdata") == 0) + in.r_symndx = RELOC_SECTION_PDATA; + else if (strcmp (name, ".fini") == 0) + in.r_symndx = RELOC_SECTION_FINI; + else if (strcmp (name, ".lita") == 0) + in.r_symndx = RELOC_SECTION_LITA; + else if (strcmp (name, "*ABS*") == 0) + in.r_symndx = RELOC_SECTION_ABS; + else + abort (); + in.r_extern = 0; + } + + /* Let the BFD backend adjust the reloc. */ + (*ecoff_backend (output_bfd)->adjust_reloc_out) (output_bfd, &rel, &in); + + /* Get some memory and swap out the reloc. */ + external_reloc_size = ecoff_backend (output_bfd)->external_reloc_size; + rbuf = (bfd_byte *) malloc (external_reloc_size); + if (rbuf == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + (*ecoff_backend (output_bfd)->swap_reloc_out) (output_bfd, &in, (PTR) rbuf); + + ok = (bfd_seek (output_bfd, + (output_section->rel_filepos + + output_section->reloc_count * external_reloc_size), + SEEK_SET) == 0 + && (bfd_write ((PTR) rbuf, 1, external_reloc_size, output_bfd) + == external_reloc_size)); + + if (ok) + ++output_section->reloc_count; + + free (rbuf); + + return ok; +} diff --git a/gnu/usr.bin/gdb/bfd/elf.c b/gnu/usr.bin/gdb/bfd/elf.c index 2fcf2f143439..af3e202c3979 100644 --- a/gnu/usr.bin/gdb/bfd/elf.c +++ b/gnu/usr.bin/gdb/bfd/elf.c @@ -33,6 +33,7 @@ SECTION #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" #define ARCH_SIZE 0 #include "libelf.h" @@ -41,8 +42,8 @@ SECTION cause invalid hash tables to be generated. (Well, you would if this were being used yet.) */ unsigned long -DEFUN (bfd_elf_hash, (name), - CONST unsigned char *name) +bfd_elf_hash (name) + CONST unsigned char *name; { unsigned long h = 0; unsigned long g; @@ -65,33 +66,32 @@ DEFUN (bfd_elf_hash, (name), buffer. */ static char * -DEFUN (elf_read, (abfd, offset, size), - bfd * abfd AND - long offset AND - int size) +elf_read (abfd, offset, size) + bfd * abfd; + long offset; + int size; { char *buf; if ((buf = bfd_alloc (abfd, size)) == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } if (bfd_seek (abfd, offset, SEEK_SET) == -1) - { - bfd_error = system_call_error; - return NULL; - } + return NULL; if (bfd_read ((PTR) buf, size, 1, abfd) != size) { - bfd_error = system_call_error; + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_file_truncated); return NULL; } return buf; } boolean -DEFUN (elf_mkobject, (abfd), bfd * abfd) +elf_mkobject (abfd) + bfd * abfd; { /* this just does initialization */ /* coff_mkobject zalloc's space for tdata.coff_obj_data ... */ @@ -99,7 +99,7 @@ DEFUN (elf_mkobject, (abfd), bfd * abfd) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)); if (elf_tdata (abfd) == 0) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } /* since everything is done at close time, do we need any @@ -109,9 +109,9 @@ DEFUN (elf_mkobject, (abfd), bfd * abfd) } char * -DEFUN (elf_get_str_section, (abfd, shindex), - bfd * abfd AND - unsigned int shindex) +elf_get_str_section (abfd, shindex) + bfd * abfd; + unsigned int shindex; { Elf_Internal_Shdr **i_shdrp; char *shstrtab = NULL; @@ -135,10 +135,10 @@ DEFUN (elf_get_str_section, (abfd, shindex), } char * -DEFUN (elf_string_from_elf_section, (abfd, shindex, strindex), - bfd * abfd AND - unsigned int shindex AND - unsigned int strindex) +elf_string_from_elf_section (abfd, shindex, strindex) + bfd * abfd; + unsigned int shindex; + unsigned int strindex; { Elf_Internal_Shdr *hdr; @@ -154,6 +154,68 @@ DEFUN (elf_string_from_elf_section, (abfd, shindex, strindex), return ((char *) hdr->rawdata) + strindex; } +/* Make a BFD section from an ELF section. We store a pointer to the + BFD section in the rawdata field of the header. */ + +boolean +_bfd_elf_make_section_from_shdr (abfd, hdr, name) + bfd *abfd; + Elf_Internal_Shdr *hdr; + const char *name; +{ + asection *newsect; + flagword flags; + + if (hdr->rawdata != NULL) + { + BFD_ASSERT (strcmp (name, ((asection *) hdr->rawdata)->name) == 0); + return true; + } + + newsect = bfd_make_section_anyway (abfd, name); + if (newsect == NULL) + return false; + + newsect->filepos = hdr->sh_offset; + + if (! bfd_set_section_vma (abfd, newsect, hdr->sh_addr) + || ! bfd_set_section_size (abfd, newsect, hdr->sh_size) + || ! bfd_set_section_alignment (abfd, newsect, + bfd_log2 (hdr->sh_addralign))) + return false; + + flags = SEC_NO_FLAGS; + if (hdr->sh_type != SHT_NOBITS) + flags |= SEC_HAS_CONTENTS; + if ((hdr->sh_flags & SHF_ALLOC) != 0) + { + flags |= SEC_ALLOC; + if (hdr->sh_type != SHT_NOBITS) + flags |= SEC_LOAD; + } + if ((hdr->sh_flags & SHF_WRITE) == 0) + flags |= SEC_READONLY; + if ((hdr->sh_flags & SHF_EXECINSTR) != 0) + flags |= SEC_CODE; + else if ((flags & SEC_LOAD) != 0) + flags |= SEC_DATA; + + /* The debugging sections appear to be recognized only by name, not + any sort of flag. */ + if (strncmp (name, ".debug", sizeof ".debug" - 1) == 0 + || strncmp (name, ".line", sizeof ".line" - 1) == 0 + || strncmp (name, ".stab", sizeof ".stab" - 1) == 0) + flags |= SEC_DEBUGGING; + + if (! bfd_set_section_flags (abfd, newsect, flags)) + return false; + + hdr->rawdata = (PTR) newsect; + elf_section_data (newsect)->this_hdr = *hdr; + + return true; +} + /* INTERNAL_FUNCTION bfd_elf_find_section @@ -170,9 +232,9 @@ DESCRIPTION */ struct elf_internal_shdr * -DEFUN (bfd_elf_find_section, (abfd, name), - bfd * abfd AND - char *name) +bfd_elf_find_section (abfd, name) + bfd * abfd; + char *name; { Elf_Internal_Shdr **i_shdrp; char *shstrtab; @@ -194,18 +256,6 @@ DEFUN (bfd_elf_find_section, (abfd, name), return 0; } -const struct bfd_elf_arch_map bfd_elf_arch_map[] = { - { bfd_arch_sparc, EM_SPARC }, - { bfd_arch_i386, EM_386 }, - { bfd_arch_m68k, EM_68K }, - { bfd_arch_m88k, EM_88K }, - { bfd_arch_i860, EM_860 }, - { bfd_arch_mips, EM_MIPS }, - { bfd_arch_hppa, EM_HPPA }, -}; - -const int bfd_elf_arch_map_size = sizeof (bfd_elf_arch_map) / sizeof (bfd_elf_arch_map[0]); - const char *const bfd_elf_section_type_names[] = { "SHT_NULL", "SHT_PROGBITS", "SHT_SYMTAB", "SHT_STRTAB", "SHT_RELA", "SHT_HASH", "SHT_DYNAMIC", "SHT_NOTE", @@ -222,23 +272,27 @@ const char *const bfd_elf_section_type_names[] = { function. It just short circuits the reloc if producing relocateable output against an external symbol. */ +/*ARGSUSED*/ bfd_reloc_status_type bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, - output_bfd) + output_bfd, + error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; + char **error_message; { if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 - && reloc_entry->addend == 0) + && (! reloc_entry->howto->partial_inplace + || reloc_entry->addend == 0)) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; @@ -246,3 +300,98 @@ bfd_elf_generic_reloc (abfd, return bfd_reloc_continue; } + +/* Create an entry in an ELF linker hash table. */ + +struct bfd_hash_entry * +_bfd_elf_link_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct elf_link_hash_entry *ret = (struct elf_link_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct elf_link_hash_entry *) NULL) + ret = ((struct elf_link_hash_entry *) + bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry))); + if (ret == (struct elf_link_hash_entry *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return (struct bfd_hash_entry *) ret; + } + + /* Call the allocation method of the superclass. */ + ret = ((struct elf_link_hash_entry *) + _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, + table, string)); + if (ret != (struct elf_link_hash_entry *) NULL) + { + /* Set local fields. */ + ret->indx = -1; + ret->size = 0; + ret->align = 0; + ret->dynindx = -1; + ret->dynstr_index = 0; + ret->weakdef = NULL; + ret->type = STT_NOTYPE; + ret->elf_link_hash_flags = 0; + } + + return (struct bfd_hash_entry *) ret; +} + +/* Initialize an ELF linker hash table. */ + +boolean +_bfd_elf_link_hash_table_init (table, abfd, newfunc) + struct elf_link_hash_table *table; + bfd *abfd; + struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *)); +{ + table->dynobj = NULL; + table->dynsymcount = 0; + table->dynstr = NULL; + table->bucketcount = 0; + return _bfd_link_hash_table_init (&table->root, abfd, newfunc); +} + +/* Create an ELF linker hash table. */ + +struct bfd_link_hash_table * +_bfd_elf_link_hash_table_create (abfd) + bfd *abfd; +{ + struct elf_link_hash_table *ret; + + ret = ((struct elf_link_hash_table *) + bfd_alloc (abfd, sizeof (struct elf_link_hash_table))); + if (ret == (struct elf_link_hash_table *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + + if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc)) + { + bfd_release (abfd, ret); + return NULL; + } + + return &ret->root; +} + +/* This is a hook for the ELF emulation code in the generic linker to + tell the backend linker what file name to use for the DT_NEEDED + entry for a dynamic object. */ + +void +bfd_elf_set_dt_needed_name (abfd, name) + bfd *abfd; + const char *name; +{ + elf_dt_needed_name (abfd) = name; +} diff --git a/gnu/usr.bin/gdb/bfd/format.c b/gnu/usr.bin/gdb/bfd/format.c index 6a80ed7082ae..b4c8471beda1 100644 --- a/gnu/usr.bin/gdb/bfd/format.c +++ b/gnu/usr.bin/gdb/bfd/format.c @@ -1,5 +1,5 @@ /* Generic BFD support for file formats. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -20,20 +20,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* SECTION - File Formats + File formats - A format is a BFD concept of high level file contents. The + A format is a BFD concept of high level file contents type. The formats supported by BFD are: - o bfd_object + o <> The BFD may contain data, symbols, relocations and debug info. - o bfd_archive + o <> The BFD contains other BFDs and an optional index. - o bfd_core + o <> The BFD contains the result of an executable core dump. @@ -44,9 +44,8 @@ SECTION #include "sysdep.h" #include "libbfd.h" -extern bfd_target *target_vector[]; -extern bfd_target *default_vector[]; - +/* IMPORT from targets.c. */ +extern const size_t _bfd_target_vector_entries; /* FUNCTION @@ -56,15 +55,14 @@ SYNOPSIS boolean bfd_check_format(bfd *abfd, bfd_format format); DESCRIPTION - This routine is supplied a BFD and a format. It attempts to - verify if the file attached to the BFD is indeed compatible - with the format specified (ie, one of <>, + Verify if the file attached to the BFD @var{abfd} is compatible + with the format @var{format} (i.e., one of <>, <> or <>). - If the BFD has been set to a specific @var{target} before the - call, only the named target and format combination will be + If the BFD has been set to a specific target before the + call, only the named target and format combination is checked. If the target has not been set, or has been set to - <> then all the known target backends will be + <>, then all the known target backends is interrogated to determine a match. If the default target matches, it is used. If not, exactly one target must recognize the file, or an error results. @@ -72,34 +70,62 @@ DESCRIPTION The function returns <> on success, otherwise <> with one of the following error codes: - o invalid_operation - + o <> - if <> is not one of <>, <> or <>. - o system_call_error - + o <> - if an error occured during a read - even some file mismatches - can cause system_call_errors + can cause bfd_error_system_calls. - o file_not_recognised - - none of the backends recognised the file format + o <> - + none of the backends recognised the file format. - o file_ambiguously_recognized - + o <> - more than one backend recognised the file format. - */ boolean -DEFUN(bfd_check_format,(abfd, format), - bfd *abfd AND - bfd_format format) +bfd_check_format (abfd, format) + bfd *abfd; + bfd_format format; { - bfd_target **target, *save_targ, *right_targ; + return bfd_check_format_matches (abfd, format, NULL); +} + +/* +FUNCTION + bfd_check_format_matches + +SYNOPSIS + boolean bfd_check_format_matches(bfd *abfd, bfd_format format, char ***matching); + +DESCRIPTION + Like <>, except when it returns false with + <> set to <>. In that + case, if @var{matching} is not NULL, it will be filled in with + a NULL-terminated list of the names of the formats that matched, + allocated with <>. + Then the user may choose a format and try again. + + When done with the list that @var{matching} points to, the caller + should free it. +*/ + +boolean +bfd_check_format_matches (abfd, format, matching) + bfd *abfd; + bfd_format format; + char ***matching; +{ + const bfd_target * const *target, *save_targ, *right_targ; + char **matching_vector = NULL; int match_count; if (!bfd_read_p (abfd) || ((int)(abfd->format) < (int)bfd_unknown) || ((int)(abfd->format) >= (int)bfd_type_end)) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return false; } @@ -112,6 +138,19 @@ DEFUN(bfd_check_format,(abfd, format), save_targ = abfd->xvec; match_count = 0; + if (matching) + { + matching_vector = + (char **) malloc (sizeof (char *) * + (_bfd_target_vector_entries + 1)); + if (!matching_vector) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + matching_vector[0] = NULL; + *matching = matching_vector; + } right_targ = 0; @@ -121,33 +160,46 @@ DEFUN(bfd_check_format,(abfd, format), /* If the target type was explicitly specified, just check that target. */ if (!abfd->target_defaulted) { - bfd_seek (abfd, (file_ptr)0, SEEK_SET); /* rewind! */ - + if (bfd_seek (abfd, (file_ptr)0, SEEK_SET) != 0) /* rewind! */ + return false; right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); if (right_targ) { abfd->xvec = right_targ; /* Set the target as returned */ + if (matching) + free (matching_vector); return true; /* File position has moved, BTW */ } } - for (target = target_vector; *target != NULL; target++) { - bfd_target *temp; + for (target = bfd_target_vector; *target != NULL; target++) { + const bfd_target *temp; abfd->xvec = *target; /* Change BFD's target temporarily */ - bfd_seek (abfd, (file_ptr)0, SEEK_SET); - /* If _bfd_check_format neglects to set bfd_error, assume wrong_format. + if (bfd_seek (abfd, (file_ptr)0, SEEK_SET) != 0) + return false; + /* If _bfd_check_format neglects to set bfd_error, assume bfd_error_wrong_format. We didn't used to even pay any attention to bfd_error, so I suspect that some _bfd_check_format might have this problem. */ - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); if (temp) { /* This format checks out as ok! */ right_targ = temp; + if (matching) + { + matching_vector[match_count] = temp->name; + matching_vector[match_count + 1] = NULL; + } match_count++; /* If this is the default target, accept it, even if other targets might match. People who want those other targets have to set the GNUTARGET variable. */ - if (temp == default_vector[0]) + if (temp == bfd_default_vector[0]) { + if (matching) + { + matching_vector[0] = temp->name; + matching_vector[1] = NULL; + } match_count = 1; break; } @@ -160,51 +212,60 @@ DEFUN(bfd_check_format,(abfd, format), */ break; #endif - } else if (bfd_error != wrong_format) { + } else if (bfd_get_error () != bfd_error_wrong_format) { abfd->xvec = save_targ; abfd->format = bfd_unknown; + if (matching && bfd_get_error () != bfd_error_file_ambiguously_recognized) + free (matching_vector); return false; } } if (match_count == 1) { abfd->xvec = right_targ; /* Change BFD's target permanently */ + if (matching) + free (matching_vector); return true; /* File position has moved, BTW */ } abfd->xvec = save_targ; /* Restore original target type */ abfd->format = bfd_unknown; /* Restore original format */ - bfd_error = ((match_count == 0) ? file_not_recognized : - file_ambiguously_recognized); + if (match_count == 0) + { + bfd_set_error (bfd_error_file_not_recognized); + if (matching) + free (matching_vector); + } + else + bfd_set_error (bfd_error_file_ambiguously_recognized); return false; } - /* FUNCTION bfd_set_format SYNOPSIS - boolean bfd_set_format(bfd *, bfd_format); + boolean bfd_set_format(bfd *abfd, bfd_format format); DESCRIPTION - This function sets the file format of the supplied BFD to the - format requested. If the target set in the BFD does not - support the format requested, the format is illegal or the BFD - is not open for writing than an error occurs. + This function sets the file format of the BFD @var{abfd} to the + format @var{format}. If the target set in the BFD does not + support the format requested, the format is invalid, or the BFD + is not open for writing, then an error occurs. */ boolean -DEFUN(bfd_set_format,(abfd, format), - bfd *abfd AND - bfd_format format) +bfd_set_format (abfd, format) + bfd *abfd; + bfd_format format; { if (bfd_read_p (abfd) || ((int)abfd->format < (int)bfd_unknown) || ((int)abfd->format >= (int)bfd_type_end)) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return false; } @@ -228,18 +289,17 @@ FUNCTION bfd_format_string SYNOPSIS - CONST char *bfd_format_string(bfd_format); + CONST char *bfd_format_string(bfd_format format); DESCRIPTION - This function takes one argument, and enumerated type - (bfd_format) and returns a pointer to a const string - <>, <>, <>, <> or <> - depending upon the value of the enumeration. + Return a pointer to a const string + <>, <>, <>, <>, or <>, + depending upon the value of @var{format}. */ CONST char * -DEFUN(bfd_format_string,(format), - bfd_format format) +bfd_format_string (format) + bfd_format format; { if (((int)format <(int) bfd_unknown) || ((int)format >=(int) bfd_type_end)) diff --git a/gnu/usr.bin/gdb/bfd/freebsd386.c b/gnu/usr.bin/gdb/bfd/freebsd386.c index 22cbd6ad1701..9c2690974700 100644 --- a/gnu/usr.bin/gdb/bfd/freebsd386.c +++ b/gnu/usr.bin/gdb/bfd/freebsd386.c @@ -29,6 +29,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ZMAGIC files start at address 0. This does not apply to QMAGIC. */ #define TEXT_START_ADDR 0 +#define PAGE_SIZE 4096 #define SEGMENT_SIZE PAGE_SIZE #define DEFAULT_ARCH bfd_arch_i386 diff --git a/gnu/usr.bin/gdb/bfd/init.c b/gnu/usr.bin/gdb/bfd/init.c index 30a275935c10..3b9326210a0b 100644 --- a/gnu/usr.bin/gdb/bfd/init.c +++ b/gnu/usr.bin/gdb/bfd/init.c @@ -1,5 +1,5 @@ /* bfd initialization stuff - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -22,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "sysdep.h" #include "libbfd.h" -extern void DEFUN_VOID (bfd_section_init); +extern void bfd_section_init (); static boolean initialized = false; @@ -30,8 +30,7 @@ static boolean initialized = false; SECTION Initialization - This is the initialization section - + These are the functions that handle initializing a BFD. */ /* @@ -42,11 +41,12 @@ SYNOPSIS void bfd_init(void); DESCRIPTION - This routine must be called before any other bfd function to + This routine must be called before any other BFD function to initialize magical internal data structures. */ -void DEFUN_VOID(bfd_init) +void +bfd_init () { if (initialized == false) { initialized = true; @@ -60,17 +60,18 @@ void DEFUN_VOID(bfd_init) INTERNAL_FUNCTION bfd_check_init -DESCRIPTION - This routine is called before any other bfd function using - initialized data is used to ensure that the structures have - been initialized. Soon this function will go away, and the bfd - library will assume that bfd_init has been called. - SYNOPSIS void bfd_check_init(void); + +DESCRIPTION + This routine is called before any other BFD function using + initialized data. It ensures that the structures have + been initialized. Soon this function will go away, and the BFD + library will assume that <> has been called. */ -void DEFUN_VOID(bfd_check_init) +void +bfd_check_init () { if (initialized == false) { bfd_init(); diff --git a/gnu/usr.bin/gdb/bfd/libaout.h b/gnu/usr.bin/gdb/bfd/libaout.h index 0d99d0c43dba..74babf2747ab 100644 --- a/gnu/usr.bin/gdb/bfd/libaout.h +++ b/gnu/usr.bin/gdb/bfd/libaout.h @@ -18,10 +18,15 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifndef LIBAOUT_H +#define LIBAOUT_H + /* We try to encapsulate the differences in the various a.out file variants in a few routines, and otherwise share large masses of code. This means we only have to fix bugs in one place, most of the time. */ +#include "bfdlink.h" + /* Parameterize the a.out code based on whether it is being built for a 32-bit architecture or a 64-bit architecture. */ #if ARCH_SIZE==64 @@ -44,11 +49,50 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define BYTES_IN_WORD 4 #endif /* ARCH_SIZE==32 */ -/* Declare these types at file level, since they are used in parameter - lists, which have wierd scope. */ +/* Declare at file level, since used in parameter lists, which have + weird scope. */ struct external_exec; -struct internal_exec; +struct external_nlist; +struct reloc_ext_external; +struct reloc_std_external; + +/* a.out backend linker hash table entries. */ +struct aout_link_hash_entry +{ + struct bfd_link_hash_entry root; + /* Whether this symbol has been written out. */ + boolean written; + /* Symbol index in output file. */ + int indx; +}; + +/* a.out backend linker hash table. */ + +struct aout_link_hash_table +{ + struct bfd_link_hash_table root; +}; + +/* Look up an entry in an a.out link hash table. */ + +#define aout_link_hash_lookup(table, string, create, copy, follow) \ + ((struct aout_link_hash_entry *) \ + bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow))) + +/* Traverse an a.out link hash table. */ + +#define aout_link_hash_traverse(table, func, info) \ + (bfd_link_hash_traverse \ + (&(table)->root, \ + (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \ + (info))) + +/* Get the a.out link hash table from the info structure. This is + just a cast. */ + +#define aout_hash_table(p) ((struct aout_link_hash_table *) ((p)->hash)) + /* Back-end information for various a.out targets. */ struct aout_backend_data { @@ -61,6 +105,9 @@ struct aout_backend_data If not, the text section starts on the next page. */ unsigned char text_includes_header; + /* The value to pass to N_SET_FLAGS. */ + unsigned char exec_hdr_flags; + /* If the text section VMA isn't specified, and we need an absolute address, use this as the default. If we're producing a relocatable file, zero is always used. */ @@ -77,6 +124,39 @@ struct aout_backend_data to the size of the text section in the file for alignment purposes but does *not* get counted in the length of the text section. */ unsigned char exec_header_not_counted; + + /* Callback from the add symbols phase of the linker code to handle + a dynamic object. */ + boolean (*add_dynamic_symbols) PARAMS ((bfd *, struct bfd_link_info *)); + + /* Callback from the add symbols phase of the linker code to handle + adding a single symbol to the global linker hash table. */ + boolean (*add_one_symbol) PARAMS ((struct bfd_link_info *, bfd *, + const char *, flagword, asection *, + bfd_vma, const char *, boolean, + boolean, + struct bfd_link_hash_entry **)); + + /* Called to handle linking a dynamic object. */ + boolean (*link_dynamic_object) PARAMS ((struct bfd_link_info *, bfd *)); + + /* Called for each global symbol being written out by the linker. + This should write out the dynamic symbol information. */ + boolean (*write_dynamic_symbol) PARAMS ((bfd *, struct bfd_link_info *, + struct aout_link_hash_entry *)); + + /* This callback is called by the linker for each reloc against an + external symbol. RELOC is a pointer to the unswapped reloc. If + *SKIP is set to true, the reloc will be skipped. */ + boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + struct aout_link_hash_entry *h, + PTR reloc, boolean *skip)); + + /* Called at the end of a link to finish up any dynamic linking + information. */ + boolean (*finish_dynamic_link) PARAMS ((bfd *, struct bfd_link_info *)); }; #define aout_backend_info(abfd) \ ((CONST struct aout_backend_data *)((abfd)->xvec->backend_data)) @@ -123,10 +203,15 @@ enum machine_type { M_68020 = 2, M_SPARC = 3, /* skip a bunch so we don't run into any of suns numbers */ + /* make these up for the ns32k*/ + M_NS32032 = (64), /* ns32032 running ? */ + M_NS32532 = (64 + 5), /* ns32532 running mach */ + M_386 = 100, M_29K = 101, /* AMD 29000 */ M_386_DYNIX = 102, /* Sequent running dynix */ M_386_NETBSD = 134, /* NetBSD/386 binary */ + M_532_NETBSD = 137, /* MetBSD/523 binary */ M_MIPS1 = 151, /* MIPS R2000/R3000 binary */ M_MIPS2 = 152, /* MIPS R4000/R6000 binary */ M_HP200 = 200, /* HP 200 (68010) BSD binary */ @@ -134,7 +219,7 @@ enum machine_type { M_HPUX = (0x20c % 256)/* HP 200/300 HPUX binary */ }; -#define N_DYNAMIC(exec) ((exec).a_info & 0x8000000) +#define N_DYNAMIC(exec) ((exec).a_info & 0x80000000) #ifndef N_MAGIC # define N_MAGIC(exec) ((exec).a_info & 0xffff) @@ -155,6 +240,12 @@ enum machine_type { | (((flags) & 0xff) << 24)) #endif +#ifndef N_SET_DYNAMIC +# define N_SET_DYNAMIC(exec, dynamic) \ +((exec).a_info = (dynamic) ? ((exec).a_info | 0x80000000) : \ +((exec).a_info & 0x7fffffff)) +#endif + #ifndef N_SET_MAGIC # define N_SET_MAGIC(exec, magic) \ ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff))) @@ -209,19 +300,40 @@ struct aoutdata { /* Segment size - needed for alignment of demand paged files. */ unsigned long segment_size; + /* Zmagic disk block size - need to align the start of the text + section in ZMAGIC binaries. Normally the same as page_size. */ + unsigned long zmagic_disk_block_size; + unsigned exec_bytes_size; unsigned vma_adjusted : 1; /* used when a bfd supports several highly similar formats */ - enum { - default_format = 0, - gnu_encap_format } subformat; + enum + { + default_format = 0, + /* Used on HP 9000/300 running HP/UX. See hp300hpux.c. */ + gnu_encap_format, + /* Used on Linux, 386BSD, etc. See include/aout/aout64.h. */ + q_magic_format + } subformat; - enum { - undecided_magic = 0, - z_magic, - o_magic, - n_magic } magic; + enum + { + undecided_magic = 0, + z_magic, + o_magic, + n_magic + } magic; + + /* The external symbol information. */ + struct external_nlist *external_syms; + bfd_size_type external_sym_count; + char *external_strings; + bfd_size_type external_string_size; + struct aout_link_hash_entry **sym_hashes; + + /* A pointer for shared library information. */ + PTR dynamic_info; }; struct aout_data_struct { @@ -240,27 +352,49 @@ struct aout_data_struct { #define obj_reloc_entry_size(bfd) (adata(bfd).reloc_entry_size) #define obj_symbol_entry_size(bfd) (adata(bfd).symbol_entry_size) #define obj_aout_subformat(bfd) (adata(bfd).subformat) +#define obj_aout_external_syms(bfd) (adata(bfd).external_syms) +#define obj_aout_external_sym_count(bfd) (adata(bfd).external_sym_count) +#define obj_aout_external_strings(bfd) (adata(bfd).external_strings) +#define obj_aout_external_string_size(bfd) (adata(bfd).external_string_size) +#define obj_aout_sym_hashes(bfd) (adata(bfd).sym_hashes) +#define obj_aout_dynamic_info(bfd) (adata(bfd).dynamic_info) /* We take the address of the first element of an asymbol to ensure that the macro is only ever applied to an asymbol */ #define aout_symbol(asymbol) ((aout_symbol_type *)(&(asymbol)->the_bfd)) +/* Information we keep for each a.out section. This is currently only + used by the a.out backend linker. */ + +struct aout_section_data_struct +{ + /* The unswapped relocation entries for this section. */ + PTR relocs; +}; + +#define aout_section_data(s) \ + ((struct aout_section_data_struct *) (s)->used_by_bfd) + /* Prototype declarations for functions defined in aoutx.h */ boolean NAME(aout,squirt_out_relocs) PARAMS ((bfd *abfd, asection *section)); -bfd_target * +boolean +NAME(aout,make_sections) PARAMS ((bfd *)); + +const bfd_target * NAME(aout,some_aout_object_p) PARAMS ((bfd *abfd, - struct internal_exec *execp, - bfd_target * (*callback)(bfd *))); + struct internal_exec *execp, + const bfd_target *(*callback)(bfd *))); boolean NAME(aout,mkobject) PARAMS ((bfd *abfd)); enum machine_type NAME(aout,machine_type) PARAMS ((enum bfd_architecture arch, - unsigned long machine)); + unsigned long machine, + boolean *unknown)); boolean NAME(aout,set_arch_mach) PARAMS ((bfd *abfd, enum bfd_architecture arch, @@ -276,30 +410,44 @@ NAME(aout,set_section_contents) PARAMS ((bfd *abfd, sec_ptr section, asymbol * NAME(aout,make_empty_symbol) PARAMS ((bfd *abfd)); +boolean +NAME(aout,translate_symbol_table) PARAMS ((bfd *, aout_symbol_type *, + struct external_nlist *, + bfd_size_type, char *, + bfd_size_type, + boolean dynamic)); + boolean NAME(aout,slurp_symbol_table) PARAMS ((bfd *abfd)); -void +boolean NAME(aout,write_syms) PARAMS ((bfd *abfd)); void NAME(aout,reclaim_symbol_table) PARAMS ((bfd *abfd)); -unsigned int +long NAME(aout,get_symtab_upper_bound) PARAMS ((bfd *abfd)); -unsigned int +long NAME(aout,get_symtab) PARAMS ((bfd *abfd, asymbol **location)); +void +NAME(aout,swap_ext_reloc_in) PARAMS ((bfd *, struct reloc_ext_external *, + arelent *, asymbol **)); +void +NAME(aout,swap_std_reloc_in) PARAMS ((bfd *, struct reloc_std_external *, + arelent *, asymbol **)); + boolean NAME(aout,slurp_reloc_table) PARAMS ((bfd *abfd, sec_ptr asect, asymbol **symbols)); -unsigned int +long NAME(aout,canonicalize_reloc) PARAMS ((bfd *abfd, sec_ptr section, arelent **relptr, asymbol **symbols)); -unsigned int +long NAME(aout,get_reloc_upper_bound) PARAMS ((bfd *abfd, sec_ptr asect)); void @@ -316,9 +464,6 @@ void NAME(aout,get_symbol_info) PARAMS ((bfd *ignore_abfd, asymbol *symbol, symbol_info *ret)); -boolean -NAME(aout,close_and_cleanup) PARAMS ((bfd *abfd)); - boolean NAME(aout,find_nearest_line) PARAMS ((bfd *abfd, asection *section, asymbol **symbols, bfd_vma offset, CONST char **filename_ptr, @@ -339,6 +484,31 @@ void NAME(aout,swap_exec_header_out) PARAMS ((bfd *abfd, struct internal_exec *execp, struct external_exec *raw_bytes)); +struct bfd_hash_entry * +NAME(aout,link_hash_newfunc) + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); + +boolean +NAME(aout,link_hash_table_init) + PARAMS ((struct aout_link_hash_table *, bfd *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); + +struct bfd_link_hash_table * +NAME(aout,link_hash_table_create) PARAMS ((bfd *)); + +boolean +NAME(aout,link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *)); + +boolean +NAME(aout,final_link) PARAMS ((bfd *, struct bfd_link_info *, + void (*) (bfd *, file_ptr *, file_ptr *, + file_ptr *))); + +boolean +NAME(aout,bfd_free_cached_info) PARAMS ((bfd *)); + /* Prototypes for functions in stab-syms.c. */ CONST char * @@ -346,15 +516,17 @@ aout_stab_name PARAMS ((int code)); /* A.out uses the generic versions of these routines... */ -#define aout_32_get_section_contents bfd_generic_get_section_contents -#define aout_32_close_and_cleanup bfd_generic_close_and_cleanup +#define aout_32_get_section_contents _bfd_generic_get_section_contents -#define aout_64_get_section_contents bfd_generic_get_section_contents -#define aout_64_close_and_cleanup bfd_generic_close_and_cleanup +#define aout_64_get_section_contents _bfd_generic_get_section_contents #ifndef NO_WRITE_HEADER_KLUDGE #define NO_WRITE_HEADER_KLUDGE 0 #endif +#ifndef aout_32_bfd_is_local_label +#define aout_32_bfd_is_local_label bfd_generic_is_local_label +#endif + #ifndef WRITE_HEADERS #define WRITE_HEADERS(abfd, execp) \ { \ @@ -372,22 +544,35 @@ aout_stab_name PARAMS ((int code)); obj_reloc_entry_size (abfd)); \ NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \ \ - bfd_seek (abfd, (file_ptr) 0, SEEK_SET); \ - bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd); \ + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) return false; \ + if (bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd) \ + != EXEC_BYTES_SIZE) \ + return false; \ /* Now write out reloc info, followed by syms and strings */ \ \ - if (bfd_get_symcount (abfd) != 0) \ + if (bfd_get_outsymbols (abfd) != (asymbol **) NULL \ + && bfd_get_symcount (abfd) != 0) \ { \ - bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET); \ + if (bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET) \ + != 0) \ + return false; \ \ - NAME(aout,write_syms)(abfd); \ + if (! NAME(aout,write_syms)(abfd)) return false; \ \ - bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET); \ + if (bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET) \ + != 0) \ + return false; \ \ - if (!NAME(aout,squirt_out_relocs) (abfd, obj_textsec (abfd))) return false; \ - bfd_seek (abfd, (file_ptr)(N_DRELOFF(*execp)), SEEK_SET); \ + if (!NAME(aout,squirt_out_relocs) (abfd, obj_textsec (abfd))) \ + return false; \ + if (bfd_seek (abfd, (file_ptr)(N_DRELOFF(*execp)), SEEK_SET) \ + != 0) \ + return false; \ \ - if (!NAME(aout,squirt_out_relocs)(abfd, obj_datasec (abfd))) return false; \ + if (!NAME(aout,squirt_out_relocs)(abfd, obj_datasec (abfd))) \ + return false; \ } \ } #endif + +#endif /* ! defined (LIBAOUT_H) */ diff --git a/gnu/usr.bin/gdb/bfd/libbfd.c b/gnu/usr.bin/gdb/bfd/libbfd.c index 1bf8f7fb8e02..a66eb6ea1d3a 100644 --- a/gnu/usr.bin/gdb/bfd/libbfd.c +++ b/gnu/usr.bin/gdb/bfd/libbfd.c @@ -1,5 +1,5 @@ /* Assorted BFD support routines, only used internally. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -24,161 +24,151 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* SECTION - libbfd + Internal functions DESCRIPTION - This file contains various routines which are used within BFD. + These routines are used within BFD. They are not intended for export, but are documented here for completeness. */ -boolean -DEFUN(_bfd_dummy_new_section_hook,(ignore, ignore_newsect), - bfd *ignore AND - asection *ignore_newsect) -{ - return true; -} +/* A routine which is used in target vectors for unsupported + operations. */ +/*ARGSUSED*/ boolean -DEFUN(bfd_false ,(ignore), - bfd *ignore) +bfd_false (ignore) + bfd *ignore; { + bfd_set_error (bfd_error_invalid_operation); return false; } +/* A routine which is used in target vectors for supported operations + which do not actually do anything. */ + +/*ARGSUSED*/ boolean -DEFUN(bfd_true,(ignore), - bfd *ignore) +bfd_true (ignore) + bfd *ignore; { return true; } +/* A routine which is used in target vectors for unsupported + operations which return a pointer value. */ + +/*ARGSUSED*/ PTR -DEFUN(bfd_nullvoidptr,(ignore), - bfd *ignore) +bfd_nullvoidptr (ignore) + bfd *ignore; { - return (PTR)NULL; + bfd_set_error (bfd_error_invalid_operation); + return NULL; } +/*ARGSUSED*/ int -DEFUN(bfd_0,(ignore), - bfd *ignore) +bfd_0 (ignore) + bfd *ignore; { return 0; } +/*ARGSUSED*/ unsigned int -DEFUN(bfd_0u,(ignore), - bfd *ignore) +bfd_0u (ignore) + bfd *ignore; { return 0; } +/*ARGUSED*/ +long +bfd_0l (ignore) + bfd *ignore; +{ + return 0; +} + +/* A routine which is used in target vectors for unsupported + operations which return -1 on error. */ + +/*ARGSUSED*/ +long +_bfd_n1 (ignore_abfd) + bfd *ignore_abfd; +{ + bfd_set_error (bfd_error_invalid_operation); + return -1; +} + +/*ARGSUSED*/ void -DEFUN(bfd_void,(ignore), - bfd *ignore) +bfd_void (ignore) + bfd *ignore; { } +/*ARGSUSED*/ boolean -DEFUN(_bfd_dummy_core_file_matches_executable_p,(ignore_core_bfd, ignore_exec_bfd), - bfd *ignore_core_bfd AND - bfd *ignore_exec_bfd) +_bfd_nocore_core_file_matches_executable_p (ignore_core_bfd, ignore_exec_bfd) + bfd *ignore_core_bfd; + bfd *ignore_exec_bfd; { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return false; } -/* of course you can't initialize a function to be the same as another, grr */ +/* Routine to handle core_file_failing_command entry point for targets + without core file support. */ +/*ARGSUSED*/ char * -DEFUN(_bfd_dummy_core_file_failing_command,(ignore_abfd), - bfd *ignore_abfd) +_bfd_nocore_core_file_failing_command (ignore_abfd) + bfd *ignore_abfd; { + bfd_set_error (bfd_error_invalid_operation); return (char *)NULL; } +/* Routine to handle core_file_failing_signal entry point for targets + without core file support. */ + +/*ARGSUSED*/ int -DEFUN(_bfd_dummy_core_file_failing_signal,(ignore_abfd), - bfd *ignore_abfd) +_bfd_nocore_core_file_failing_signal (ignore_abfd) + bfd *ignore_abfd; { + bfd_set_error (bfd_error_invalid_operation); return 0; } -bfd_target * -DEFUN(_bfd_dummy_target,(ignore_abfd), - bfd *ignore_abfd) +/*ARGSUSED*/ +const bfd_target * +_bfd_dummy_target (ignore_abfd) + bfd *ignore_abfd; { + bfd_set_error (bfd_error_wrong_format); return 0; } -/** zalloc -- allocate and clear storage */ +#ifndef bfd_zmalloc +/* allocate and clear storage */ -#ifndef zalloc char * -DEFUN(zalloc,(size), - bfd_size_type size) +bfd_zmalloc (size) + bfd_size_type size; { - char *ptr = (char *) malloc ((size_t)size); + char *ptr = (char *) malloc ((size_t) size); - if ((ptr != NULL) && (size != 0)) - memset(ptr,0, (size_t) size); + if (ptr && size) + memset(ptr, 0, (size_t) size); return ptr; } -#endif - -/* -INTERNAL_FUNCTION - bfd_xmalloc - -SYNOPSIS - PTR bfd_xmalloc( bfd_size_type size); - -DESCRIPTION - Like malloc, but exit if no more memory. - -*/ - -/** There is major inconsistency in how running out of memory is handled. - Some routines return a NULL, and set bfd_error to no_memory. - However, obstack routines can't do this ... */ - - -DEFUN(PTR bfd_xmalloc,(size), - bfd_size_type size) -{ - static CONST char no_memory_message[] = "Virtual memory exhausted!\n"; - PTR ptr; - if (size == 0) size = 1; - ptr = (PTR)malloc((size_t) size); - if (!ptr) - { - write (2, no_memory_message, sizeof(no_memory_message)-1); - exit (-1); - } - return ptr; -} - -/* -INTERNAL_FUNCTION - bfd_xmalloc_by_size_t - -SYNOPSIS - PTR bfd_xmalloc_by_size_t ( size_t size); - -DESCRIPTION - Like malloc, but exit if no more memory. - Uses size_t, so it's suitable for use as obstack_chunk_alloc. - */ -PTR -DEFUN(bfd_xmalloc_by_size_t, (size), - size_t size) -{ - return bfd_xmalloc ((bfd_size_type) size); -} +#endif /* bfd_zmalloc */ /* Some IO code */ @@ -191,20 +181,25 @@ DEFUN(bfd_xmalloc_by_size_t, (size), first octet in the file, NOT the beginning of the archive header. */ static -int DEFUN(real_read,(where, a,b, file), - PTR where AND - int a AND - int b AND - FILE *file) +int +real_read (where, a,b, file) + PTR where; + int a; + int b; + FILE *file; { return fread(where, a,b,file); } + +/* Return value is amount read (FIXME: how are errors and end of file dealt + with? We never call bfd_set_error, which is probably a mistake). */ + bfd_size_type -DEFUN(bfd_read,(ptr, size, nitems, abfd), - PTR ptr AND - bfd_size_type size AND - bfd_size_type nitems AND - bfd *abfd) +bfd_read (ptr, size, nitems, abfd) + PTR ptr; + bfd_size_type size; + bfd_size_type nitems; + bfd *abfd; { int nread; nread = real_read (ptr, 1, (int)(size*nitems), bfd_cache_lookup(abfd)); @@ -212,21 +207,45 @@ DEFUN(bfd_read,(ptr, size, nitems, abfd), if (nread > 0) abfd->where += nread; #endif + + /* Set bfd_error if we did not read as much data as we expected. + + If the read failed due to an error set the bfd_error_system_call, + else set bfd_error_file_truncated. + + A BFD backend may wish to override bfd_error_file_truncated to + provide something more useful (eg. no_symbols or wrong_format). */ + if (nread < (int)(size * nitems)) + { + if (ferror (bfd_cache_lookup (abfd))) + bfd_set_error (bfd_error_system_call); + else + bfd_set_error (bfd_error_file_truncated); + } + return nread; } bfd_size_type -DEFUN(bfd_write,(ptr, size, nitems, abfd), - CONST PTR ptr AND - bfd_size_type size AND - bfd_size_type nitems AND - bfd *abfd) +bfd_write (ptr, size, nitems, abfd) + CONST PTR ptr; + bfd_size_type size; + bfd_size_type nitems; + bfd *abfd; { - int nwrote = fwrite (ptr, 1, (int)(size*nitems), bfd_cache_lookup(abfd)); + int nwrote = fwrite (ptr, 1, (int) (size * nitems), bfd_cache_lookup (abfd)); #ifdef FILE_OFFSET_IS_CHAR_INDEX if (nwrote > 0) abfd->where += nwrote; #endif + if (nwrote != size * nitems) + { +#ifdef ENOSPC + if (nwrote >= 0) + errno = ENOSPC; +#endif + bfd_set_error (bfd_error_system_call); + } return nwrote; } @@ -238,24 +257,25 @@ SYNOPSIS void bfd_write_bigendian_4byte_int(bfd *abfd, int i); DESCRIPTION - Writes a 4 byte integer to the outputing bfd, in big endian - mode regardless of what else is going on. This is useful in + Write a 4 byte integer @var{i} to the output BFD @var{abfd}, in big + endian order regardless of what else is going on. This is useful in archives. */ void -DEFUN(bfd_write_bigendian_4byte_int,(abfd, i), - bfd *abfd AND - int i) +bfd_write_bigendian_4byte_int (abfd, i) + bfd *abfd; + int i; { bfd_byte buffer[4]; bfd_putb32(i, buffer); - bfd_write((PTR)buffer, 4, 1, abfd); + if (bfd_write((PTR)buffer, 4, 1, abfd) != 4) + abort (); } long -DEFUN(bfd_tell,(abfd), - bfd *abfd) +bfd_tell (abfd) + bfd *abfd; { file_ptr ptr; @@ -268,25 +288,28 @@ DEFUN(bfd_tell,(abfd), } int -DEFUN(bfd_flush,(abfd), - bfd *abfd) +bfd_flush (abfd) + bfd *abfd; { return fflush (bfd_cache_lookup(abfd)); } int -DEFUN(bfd_stat,(abfd, statbuf), - bfd *abfd AND - struct stat *statbuf) +bfd_stat (abfd, statbuf) + bfd *abfd; + struct stat *statbuf; { return fstat (fileno(bfd_cache_lookup(abfd)), statbuf); } +/* Returns 0 for success, nonzero for failure (in which case bfd_get_error + can retrieve the error code). */ + int -DEFUN(bfd_seek,(abfd, position, direction), - bfd * CONST abfd AND - CONST file_ptr position AND - CONST int direction) +bfd_seek (abfd, position, direction) + bfd * CONST abfd; + CONST file_ptr position; + CONST int direction; { int result; FILE *f; @@ -302,7 +325,7 @@ DEFUN(bfd_seek,(abfd, position, direction), #ifdef FILE_OFFSET_IS_CHAR_INDEX if (abfd->format != bfd_archive && abfd->my_archive == 0) { -#ifndef NDEBUG +#if 0 /* Explanation for this code: I'm only about 95+% sure that the above conditions are sufficient and that all i/o calls are properly adjusting the `where' field. So this is sort of an `assert' @@ -343,8 +366,11 @@ DEFUN(bfd_seek,(abfd, position, direction), result = fseek (f, file_position, direction); if (result != 0) - /* Force redetermination of `where' field. */ - bfd_tell (abfd); + { + /* Force redetermination of `where' field. */ + bfd_tell (abfd); + bfd_set_error (bfd_error_system_call); + } else { #ifdef FILE_OFFSET_IS_CHAR_INDEX @@ -366,11 +392,11 @@ DEFUN(bfd_seek,(abfd, position, direction), table_length). Updates free_ptr, table, table_length */ boolean -DEFUN(bfd_add_to_string_table,(table, new_string, table_length, free_ptr), - char **table AND - char *new_string AND - unsigned int *table_length AND - char **free_ptr) +bfd_add_to_string_table (table, new_string, table_length, free_ptr) + char **table; + char *new_string; + unsigned int *table_length; + char **free_ptr; { size_t string_length = strlen (new_string) + 1; /* include null here */ char *base = *table; @@ -379,13 +405,13 @@ DEFUN(bfd_add_to_string_table,(table, new_string, table_length, free_ptr), if (base == NULL) { /* Avoid a useless regrow if we can (but of course we still - take it next time */ + take it next time). */ space_length = (string_length < DEFAULT_STRING_SPACE_SIZE ? DEFAULT_STRING_SPACE_SIZE : string_length+1); - base = zalloc ((bfd_size_type) space_length); + base = bfd_zmalloc ((bfd_size_type) space_length); if (base == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } } @@ -397,7 +423,7 @@ DEFUN(bfd_add_to_string_table,(table, new_string, table_length, free_ptr), base = (char *) realloc (base, space_length); if (base == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return false; } @@ -435,22 +461,22 @@ DESCRIPTION mangling performs any necessary endian translations and removes alignment restrictions. Note that types accepted and returned by these macros are identical so they can be swapped - around in macros--for example libaout.h defines GET_WORD to - either bfd_get_32 or bfd_get_64. + around in macros---for example, @file{libaout.h} defines <> + to either <> or <>. - In the put routines, val must be a bfd_vma. If we are on a + In the put routines, @var{val} must be a <>. If we are on a system without prototypes, the caller is responsible for making sure that is true, with a cast if necessary. We don't cast - them in the macro definitions because that would prevent lint - or gcc -Wall from detecting sins such as passing a pointer. - To detect calling these with less than a bfd_vma, use gcc - -Wconversion on a host with 64 bit bfd_vma's. + them in the macro definitions because that would prevent <> + or <> from detecting sins such as passing a pointer. + To detect calling these with less than a <>, use + <> on a host with 64 bit <>'s. . .{* Byte swapping macros for user section data. *} . .#define bfd_put_8(abfd, val, ptr) \ -. (*((unsigned char *)(ptr)) = (unsigned char)val) +. (*((unsigned char *)(ptr)) = (unsigned char)(val)) .#define bfd_put_signed_8 \ . bfd_put_8 .#define bfd_get_8(abfd, ptr) \ @@ -490,15 +516,14 @@ DESCRIPTION /* FUNCTION bfd_h_put_size -FUNCTION bfd_h_get_size DESCRIPTION These macros have the same function as their <> - bretherin, except that they are used for removing information + bretheren, except that they are used for removing information for the header records of object files. Believe it or not, some object files keep their header records in big endian - order, and their data in little endian order. + order and their data in little endian order. . .{* Byte swapping macros for file header data. *} . @@ -543,91 +568,91 @@ DESCRIPTION /* Sign extension to bfd_signed_vma. */ #define COERCE16(x) (((bfd_signed_vma) (x) ^ 0x8000) - 0x8000) #define COERCE32(x) (((bfd_signed_vma) (x) ^ 0x80000000) - 0x80000000) -#define EIGHT_GAZILLION (((HOST_64_BIT)0x80000000) << 32) +#define EIGHT_GAZILLION (((BFD_HOST_64_BIT)0x80000000) << 32) #define COERCE64(x) \ (((bfd_signed_vma) (x) ^ EIGHT_GAZILLION) - EIGHT_GAZILLION) bfd_vma -DEFUN(bfd_getb16,(addr), - register bfd_byte *addr) +bfd_getb16 (addr) + register const bfd_byte *addr; { - return (addr[0] << 8) | addr[1]; + return (addr[0] << 8) | addr[1]; } bfd_vma -DEFUN(bfd_getl16,(addr), - register bfd_byte *addr) +bfd_getl16 (addr) + register const bfd_byte *addr; { - return (addr[1] << 8) | addr[0]; + return (addr[1] << 8) | addr[0]; } bfd_signed_vma -DEFUN(bfd_getb_signed_16,(addr), - register bfd_byte *addr) +bfd_getb_signed_16 (addr) + register const bfd_byte *addr; { - return COERCE16((addr[0] << 8) | addr[1]); + return COERCE16((addr[0] << 8) | addr[1]); } bfd_signed_vma -DEFUN(bfd_getl_signed_16,(addr), - register bfd_byte *addr) +bfd_getl_signed_16 (addr) + register const bfd_byte *addr; { - return COERCE16((addr[1] << 8) | addr[0]); + return COERCE16((addr[1] << 8) | addr[0]); } void -DEFUN(bfd_putb16,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putb16 (data, addr) + bfd_vma data; + register bfd_byte *addr; { - addr[0] = (bfd_byte)(data >> 8); - addr[1] = (bfd_byte )data; + addr[0] = (bfd_byte)(data >> 8); + addr[1] = (bfd_byte )data; } void -DEFUN(bfd_putl16,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putl16 (data, addr) + bfd_vma data; + register bfd_byte *addr; { - addr[0] = (bfd_byte )data; - addr[1] = (bfd_byte)(data >> 8); + addr[0] = (bfd_byte )data; + addr[1] = (bfd_byte)(data >> 8); } bfd_vma bfd_getb32 (addr) - register bfd_byte *addr; + register const bfd_byte *addr; { - return (((((bfd_vma)addr[0] << 8) | addr[1]) << 8) - | addr[2]) << 8 | addr[3]; + return (((((bfd_vma)addr[0] << 8) | addr[1]) << 8) + | addr[2]) << 8 | addr[3]; } bfd_vma bfd_getl32 (addr) - register bfd_byte *addr; + register const bfd_byte *addr; { - return (((((bfd_vma)addr[3] << 8) | addr[2]) << 8) - | addr[1]) << 8 | addr[0]; + return (((((bfd_vma)addr[3] << 8) | addr[2]) << 8) + | addr[1]) << 8 | addr[0]; } bfd_signed_vma bfd_getb_signed_32 (addr) - register bfd_byte *addr; + register const bfd_byte *addr; { - return COERCE32((((((bfd_vma)addr[0] << 8) | addr[1]) << 8) - | addr[2]) << 8 | addr[3]); + return COERCE32((((((bfd_vma)addr[0] << 8) | addr[1]) << 8) + | addr[2]) << 8 | addr[3]); } bfd_signed_vma bfd_getl_signed_32 (addr) - register bfd_byte *addr; + register const bfd_byte *addr; { - return COERCE32((((((bfd_vma)addr[3] << 8) | addr[2]) << 8) - | addr[1]) << 8 | addr[0]); + return COERCE32((((((bfd_vma)addr[3] << 8) | addr[2]) << 8) + | addr[1]) << 8 | addr[0]); } bfd_vma -DEFUN(bfd_getb64,(addr), - register bfd_byte *addr) +bfd_getb64 (addr) + register const bfd_byte *addr; { #ifdef BFD64 bfd_vma low, high; @@ -647,14 +672,12 @@ DEFUN(bfd_getb64,(addr), BFD_FAIL(); return 0; #endif - } bfd_vma -DEFUN(bfd_getl64,(addr), - register bfd_byte *addr) +bfd_getl64 (addr) + register const bfd_byte *addr; { - #ifdef BFD64 bfd_vma low, high; high= (((((((addr[7] << 8) | @@ -676,8 +699,8 @@ DEFUN(bfd_getl64,(addr), } bfd_signed_vma -DEFUN(bfd_getb_signed_64,(addr), - register bfd_byte *addr) +bfd_getb_signed_64 (addr) + register const bfd_byte *addr; { #ifdef BFD64 bfd_vma low, high; @@ -697,14 +720,12 @@ DEFUN(bfd_getb_signed_64,(addr), BFD_FAIL(); return 0; #endif - } bfd_signed_vma -DEFUN(bfd_getl_signed_64,(addr), - register bfd_byte *addr) +bfd_getl_signed_64 (addr) + register const bfd_byte *addr; { - #ifdef BFD64 bfd_vma low, high; high= (((((((addr[7] << 8) | @@ -722,13 +743,12 @@ DEFUN(bfd_getl_signed_64,(addr), BFD_FAIL(); return 0; #endif - } void -DEFUN(bfd_putb32,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putb32 (data, addr) + bfd_vma data; + register bfd_byte *addr; { addr[0] = (bfd_byte)(data >> 24); addr[1] = (bfd_byte)(data >> 16); @@ -737,19 +757,20 @@ DEFUN(bfd_putb32,(data, addr), } void -DEFUN(bfd_putl32,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putl32 (data, addr) + bfd_vma data; + register bfd_byte *addr; { addr[0] = (bfd_byte)data; addr[1] = (bfd_byte)(data >> 8); addr[2] = (bfd_byte)(data >> 16); addr[3] = (bfd_byte)(data >> 24); } + void -DEFUN(bfd_putb64,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putb64 (data, addr) + bfd_vma data; + register bfd_byte *addr; { #ifdef BFD64 addr[0] = (bfd_byte)(data >> (7*8)); @@ -763,13 +784,12 @@ DEFUN(bfd_putb64,(data, addr), #else BFD_FAIL(); #endif - } void -DEFUN(bfd_putl64,(data, addr), - bfd_vma data AND - register bfd_byte *addr) +bfd_putl64 (data, addr) + bfd_vma data; + register bfd_byte *addr; { #ifdef BFD64 addr[7] = (bfd_byte)(data >> (7*8)); @@ -783,19 +803,17 @@ DEFUN(bfd_putl64,(data, addr), #else BFD_FAIL(); #endif - } - /* Default implementation */ boolean -DEFUN(bfd_generic_get_section_contents, (abfd, section, location, offset, count), - bfd *abfd AND - sec_ptr section AND - PTR location AND - file_ptr offset AND - bfd_size_type count) +_bfd_generic_get_section_contents (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; { if (count == 0) return true; @@ -811,32 +829,33 @@ DEFUN(bfd_generic_get_section_contents, (abfd, section, location, offset, count) in read-write files, though. See other set_section_contents functions to see why it doesn't work for new sections. */ boolean -DEFUN(bfd_generic_set_section_contents, (abfd, section, location, offset, count), - bfd *abfd AND - sec_ptr section AND - PTR location AND - file_ptr offset AND - bfd_size_type count) +_bfd_generic_set_section_contents (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; { - if (count == 0) - return true; - if ((bfd_size_type)(offset+count) > bfd_get_section_size_after_reloc(section) - || bfd_seek(abfd, (file_ptr)(section->filepos + offset), SEEK_SET) == -1 - || bfd_write(location, (bfd_size_type)1, count, abfd) != count) - return (false); /* on error */ - return (true); + if (count == 0) + return true; + + if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) == -1 + || bfd_write (location, (bfd_size_type) 1, count, abfd) != count) + return false; + + return true; } /* INTERNAL_FUNCTION bfd_log2 -DESCRIPTION - Return the log base 2 of the value supplied, rounded up. eg an - arg of 1025 would return 11. - SYNOPSIS unsigned int bfd_log2(bfd_vma x); + +DESCRIPTION + Return the log base 2 of the value supplied, rounded up. E.g., an + @var{x} of 1025 returns 11. */ unsigned @@ -848,3 +867,14 @@ bfd_log2(x) result++; return result; } + +boolean +bfd_generic_is_local_label (abfd, sym) + bfd *abfd; + asymbol *sym; +{ + char locals_prefix = (bfd_get_symbol_leading_char (abfd) == '_') ? 'L' : '.'; + + return (sym->name[0] == locals_prefix); +} + diff --git a/gnu/usr.bin/gdb/bfd/libbfd.h b/gnu/usr.bin/gdb/bfd/libbfd.h index fcd5bbca8de8..908f08aa98f7 100644 --- a/gnu/usr.bin/gdb/bfd/libbfd.h +++ b/gnu/usr.bin/gdb/bfd/libbfd.h @@ -1,8 +1,12 @@ /* libbfd.h -- Declarations used by bfd library *implementation*. (This include file is not for users of the library.) - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Cygnus Support. +** NOTE: libbfd.h is a GENERATED file. Don't change it; instead, +** change libbfd-in.h or the other BFD source files processed to +** generate this file. + This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify @@ -19,7 +23,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - /* Align an address upward to a boundary, expressed as a number of bytes. E.g. align to an 8-byte boundary with argument of 8. */ #define BFD_ALIGN(this, boundary) \ @@ -44,7 +47,8 @@ struct artdata { carsym *symdefs; /* the symdef entries */ symindex symdef_count; /* how many there are */ char *extended_names; /* clever intel extension */ - time_t armap_timestamp; /* Timestamp value written into armap. + /* when more compilers are standard C, this can be a time_t */ + long armap_timestamp; /* Timestamp value written into armap. This is used for BSD archives to check that the timestamp is recent enough for the BSD linker to not complain, @@ -52,6 +56,7 @@ struct artdata { archive. */ file_ptr armap_datepos; /* Position within archive to seek to rewrite the date field. */ + PTR tdata; /* Backend specific information. */ }; #define bfd_ardata(bfd) ((bfd)->tdata.aout_ar_data) @@ -65,14 +70,14 @@ struct areltdata { #define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size) -char *zalloc PARAMS ((bfd_size_type size)); +char *bfd_zmalloc PARAMS ((bfd_size_type size)); /* These routines allocate and free things on the BFD's obstack. Note that realloc can never occur in place. */ PTR bfd_alloc PARAMS ((bfd *abfd, size_t size)); PTR bfd_zalloc PARAMS ((bfd *abfd, size_t size)); -PTR bfd_realloc PARAMS ((bfd *abfd, PTR orig, size_t new)); +PTR bfd_realloc PARAMS ((bfd *abfd, PTR orig, size_t size)); void bfd_alloc_grow PARAMS ((bfd *abfd, PTR thing, size_t size)); PTR bfd_alloc_finish PARAMS ((bfd *abfd)); PTR bfd_alloc_by_size_t PARAMS ((bfd *abfd, size_t wanted)); @@ -92,17 +97,19 @@ int bfd_flush PARAMS ((bfd *abfd)); int bfd_stat PARAMS ((bfd *abfd, struct stat *)); bfd * _bfd_create_empty_archive_element_shell PARAMS ((bfd *obfd)); -bfd * look_for_bfd_in_cache PARAMS ((bfd *arch_bfd, file_ptr index)); +bfd * _bfd_look_for_bfd_in_cache PARAMS ((bfd *arch_bfd, file_ptr index)); +boolean _bfd_add_bfd_to_archive_cache PARAMS ((bfd *, file_ptr, bfd *)); boolean _bfd_generic_mkarchive PARAMS ((bfd *abfd)); -struct areltdata * snarf_ar_hdr PARAMS ((bfd *abfd)); -bfd_target * bfd_generic_archive_p PARAMS ((bfd *abfd)); +struct areltdata *_bfd_snarf_ar_hdr PARAMS ((bfd *abfd)); +const bfd_target *bfd_generic_archive_p PARAMS ((bfd *abfd)); boolean bfd_slurp_armap PARAMS ((bfd *abfd)); boolean bfd_slurp_bsd_armap_f2 PARAMS ((bfd *abfd)); #define bfd_slurp_bsd_armap bfd_slurp_armap #define bfd_slurp_coff_armap bfd_slurp_armap boolean _bfd_slurp_extended_name_table PARAMS ((bfd *abfd)); boolean _bfd_write_archive_contents PARAMS ((bfd *abfd)); -bfd * new_bfd PARAMS (()); +bfd *_bfd_get_elt_at_filepos PARAMS ((bfd *archive, file_ptr filepos)); +bfd * _bfd_new_bfd PARAMS ((void)); #define DEFAULT_STRING_SPACE_SIZE 0x2000 boolean bfd_add_to_string_table PARAMS ((char **table, char *new_string, @@ -114,15 +121,12 @@ boolean bfd_true PARAMS ((bfd *ignore)); PTR bfd_nullvoidptr PARAMS ((bfd *ignore)); int bfd_0 PARAMS ((bfd *ignore)); unsigned int bfd_0u PARAMS ((bfd *ignore)); +long bfd_0l PARAMS ((bfd *ignore)); +long _bfd_n1 PARAMS ((bfd *ignore)); void bfd_void PARAMS ((bfd *ignore)); -bfd * new_bfd_contained_in PARAMS ((bfd *)); -boolean _bfd_dummy_new_section_hook PARAMS ((bfd *ignore, asection *newsect)); -char * _bfd_dummy_core_file_failing_command PARAMS ((bfd *abfd)); -int _bfd_dummy_core_file_failing_signal PARAMS ((bfd *abfd)); -boolean _bfd_dummy_core_file_matches_executable_p PARAMS ((bfd *core_bfd, - bfd *exec_bfd)); -bfd_target * _bfd_dummy_target PARAMS ((bfd *abfd)); +bfd *_bfd_new_bfd_contained_in PARAMS ((bfd *)); +const bfd_target *_bfd_dummy_target PARAMS ((bfd *abfd)); void bfd_dont_truncate_arname PARAMS ((bfd *abfd, CONST char *filename, char *hdr)); @@ -142,14 +146,230 @@ bfd * bfd_generic_openr_next_archived_file PARAMS ((bfd *archive, int bfd_generic_stat_arch_elt PARAMS ((bfd *, struct stat *)); -boolean bfd_generic_get_section_contents PARAMS ((bfd *abfd, sec_ptr section, - PTR location, file_ptr offset, - bfd_size_type count)); + +/* Generic routines to use for BFD_JUMP_TABLE_GENERIC. Use + BFD_JUMP_TABLE_GENERIC (_bfd_generic). */ -boolean bfd_generic_set_section_contents PARAMS ((bfd *abfd, sec_ptr section, - PTR location, file_ptr offset, - bfd_size_type count)); +#define _bfd_generic_close_and_cleanup bfd_true +#define _bfd_generic_bfd_free_cached_info bfd_true +#define _bfd_generic_new_section_hook \ + ((boolean (*) PARAMS ((bfd *, asection *))) bfd_true) +extern boolean _bfd_generic_get_section_contents + PARAMS ((bfd *, asection *, PTR location, file_ptr offset, + bfd_size_type count)); +/* Generic routines to use for BFD_JUMP_TABLE_COPY. Use + BFD_JUMP_TABLE_COPY (_bfd_generic). */ + +#define _bfd_generic_bfd_copy_private_bfd_data \ + ((boolean (*) PARAMS ((bfd *, bfd *))) bfd_true) +#define _bfd_generic_bfd_copy_private_section_data \ + ((boolean (*) PARAMS ((bfd *, asection *, bfd *, asection *))) bfd_true) + +/* Routines to use for BFD_JUMP_TABLE_CORE when there is no core file + support. Use BFD_JUMP_TABLE_CORE (_bfd_nocore). */ + +extern char *_bfd_nocore_core_file_failing_command PARAMS ((bfd *)); +extern int _bfd_nocore_core_file_failing_signal PARAMS ((bfd *)); +extern boolean _bfd_nocore_core_file_matches_executable_p + PARAMS ((bfd *, bfd *)); + +/* Routines to use for BFD_JUMP_TABLE_ARCHIVE when there is no archive + file support. Use BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive). */ + +#define _bfd_noarchive_slurp_armap bfd_false +#define _bfd_noarchive_slurp_extended_name_table bfd_false +#define _bfd_noarchive_truncate_arname \ + ((void (*) PARAMS ((bfd *, const char *, char *))) bfd_void) +#define _bfd_noarchive_write_armap \ + ((boolean (*) \ + PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int))) \ + bfd_false) +#define _bfd_noarchive_openr_next_archived_file \ + ((bfd *(*) PARAMS ((bfd *, bfd *))) bfd_nullvoidptr) +#define _bfd_noarchive_generic_stat_arch_elt bfd_generic_stat_arch_elt + +/* Routines to use for BFD_JUMP_TABLE_ARCHIVE to get BSD style + archives. Use BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd). */ + +#define _bfd_archive_bsd_slurp_armap bfd_slurp_bsd_armap +#define _bfd_archive_bsd_slurp_extended_name_table \ + _bfd_slurp_extended_name_table +#define _bfd_archive_bsd_truncate_arname bfd_bsd_truncate_arname +#define _bfd_archive_bsd_write_armap bsd_write_armap +#define _bfd_archive_bsd_openr_next_archived_file \ + bfd_generic_openr_next_archived_file +#define _bfd_archive_bsd_generic_stat_arch_elt \ + bfd_generic_stat_arch_elt + +/* Routines to use for BFD_JUMP_TABLE_ARCHIVE to get COFF style + archives. Use BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff). */ + +#define _bfd_archive_coff_slurp_armap bfd_slurp_coff_armap +#define _bfd_archive_coff_slurp_extended_name_table \ + _bfd_slurp_extended_name_table +#define _bfd_archive_coff_truncate_arname bfd_dont_truncate_arname +#define _bfd_archive_coff_write_armap coff_write_armap +#define _bfd_archive_coff_openr_next_archived_file \ + bfd_generic_openr_next_archived_file +#define _bfd_archive_coff_generic_stat_arch_elt \ + bfd_generic_stat_arch_elt + +/* Routines to use for BFD_JUMP_TABLE_SYMBOLS where there is no symbol + support. Use BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols). */ + +#define _bfd_nosymbols_get_symtab_upper_bound _bfd_n1 +#define _bfd_nosymbols_get_symtab \ + ((long (*) PARAMS ((bfd *, asymbol **))) _bfd_n1) +#define _bfd_nosymbols_make_empty_symbol \ + ((asymbol *(*) PARAMS ((bfd *))) bfd_nullvoidptr) +#define _bfd_nosymbols_print_symbol \ + ((void (*) PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type))) bfd_void) +#define _bfd_nosymbols_get_symbol_info \ + ((void (*) PARAMS ((bfd *, asymbol *, symbol_info *))) bfd_void) +#define _bfd_nosymbols_bfd_is_local_label \ + ((boolean (*) PARAMS ((bfd *, asymbol *))) bfd_false) +#define _bfd_nosymbols_get_lineno \ + ((alent *(*) PARAMS ((bfd *, asymbol *))) bfd_nullvoidptr) +#define _bfd_nosymbols_find_nearest_line \ + ((boolean (*) \ + PARAMS ((bfd *, asection *, asymbol **, bfd_vma, const char **, \ + const char **, unsigned int *))) \ + bfd_false) +#define _bfd_nosymbols_bfd_make_debug_symbol \ + ((asymbol *(*) PARAMS ((bfd *, PTR, unsigned long))) bfd_nullvoidptr) + +/* Routines to use for BFD_JUMP_TABLE_RELOCS when there is no reloc + support. Use BFD_JUMP_TABLE_RELOCS (_bfd_norelocs). */ + +#define _bfd_norelocs_get_reloc_upper_bound \ + ((long (*) PARAMS ((bfd *, asection *))) _bfd_n1) +#define _bfd_norelocs_canonicalize_reloc \ + ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) _bfd_n1) +#define _bfd_norelocs_bfd_reloc_type_lookup \ + ((const reloc_howto_type *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) \ + bfd_nullvoidptr) + +/* Routines to use for BFD_JUMP_TABLE_WRITE for targets which may not + be written. Use BFD_JUMP_TABLE_WRITE (_bfd_nowrite). */ + +#define _bfd_nowrite_set_arch_mach \ + ((boolean (*) PARAMS ((bfd *, enum bfd_architecture, unsigned long))) \ + bfd_false) +#define _bfd_nowrite_set_section_contents \ + ((boolean (*) PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type))) \ + bfd_false) + +/* Generic routines to use for BFD_JUMP_TABLE_WRITE. Use + BFD_JUMP_TABLE_WRITE (_bfd_generic). */ + +#define _bfd_generic_set_arch_mach bfd_default_set_arch_mach +extern boolean _bfd_generic_set_section_contents + PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type)); + +/* Routines to use for BFD_JUMP_TABLE_LINK for targets which do not + support linking. Use BFD_JUMP_TABLE_LINK (_bfd_nolink). */ + +#define _bfd_nolink_sizeof_headers ((int (*) PARAMS ((bfd *, boolean))) bfd_0) +#define _bfd_nolink_bfd_get_relocated_section_contents \ + ((bfd_byte *(*) \ + PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, \ + bfd_byte *, boolean, asymbol **))) \ + bfd_nullvoidptr) +#define _bfd_nolink_bfd_relax_section \ + ((boolean (*) \ + PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *))) \ + bfd_false) +#define _bfd_nolink_bfd_link_hash_table_create \ + ((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr) +#define _bfd_nolink_bfd_link_add_symbols \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) +#define _bfd_nolink_bfd_final_link \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) + +/* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not + have dynamic symbols or relocs. Use BFD_JUMP_TABLE_DYNAMIC + (_bfd_nodynamic). */ + +#define _bfd_nodynamic_get_dynamic_symtab_upper_bound _bfd_n1 +#define _bfd_nodynamic_canonicalize_dynamic_symtab \ + ((long (*) PARAMS ((bfd *, asymbol **))) _bfd_n1) +#define _bfd_nodynamic_get_dynamic_reloc_upper_bound _bfd_n1 +#define _bfd_nodynamic_canonicalize_dynamic_reloc \ + ((long (*) PARAMS ((bfd *, arelent **, asymbol **))) _bfd_n1) + +/* Generic routine to determine of the given symbol is a local + label. */ +extern boolean bfd_generic_is_local_label PARAMS ((bfd *, asymbol *)); + +/* A routine to create entries for a bfd_link_hash_table. */ +extern struct bfd_hash_entry *_bfd_link_hash_newfunc + PARAMS ((struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string)); + +/* Initialize a bfd_link_hash_table. */ +extern boolean _bfd_link_hash_table_init + PARAMS ((struct bfd_link_hash_table *, bfd *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); + +/* Generic link hash table creation routine. */ +extern struct bfd_link_hash_table *_bfd_generic_link_hash_table_create + PARAMS ((bfd *)); + +/* Generic add symbol routine. */ +extern boolean _bfd_generic_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Generic add symbol routine. This version is used by targets for + which the linker must collect constructors and destructors by name, + as the collect2 program does. */ +extern boolean _bfd_generic_link_add_symbols_collect + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Generic archive add symbol routine. */ +extern boolean _bfd_generic_link_add_archive_symbols + PARAMS ((bfd *, struct bfd_link_info *, + boolean (*checkfn) (bfd *, struct bfd_link_info *, boolean *))); + +/* Forward declaration to avoid prototype errors. */ +typedef struct bfd_link_hash_entry _bfd_link_hash_entry; + +/* Generic routine to add a single symbol. */ +extern boolean _bfd_generic_link_add_one_symbol + PARAMS ((struct bfd_link_info *, bfd *, const char *name, flagword, + asection *, bfd_vma, const char *, boolean copy, + boolean constructor, struct bfd_link_hash_entry **)); + +/* Generic link routine. */ +extern boolean _bfd_generic_final_link + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Generic reloc_link_order processing routine. */ +extern boolean _bfd_generic_reloc_link_order + PARAMS ((bfd *, struct bfd_link_info *, asection *, + struct bfd_link_order *)); + +/* Default link order processing routine. */ +extern boolean _bfd_default_link_order + PARAMS ((bfd *, struct bfd_link_info *, asection *, + struct bfd_link_order *)); + +/* Count the number of reloc entries in a link order list. */ +extern unsigned int _bfd_count_link_order_relocs + PARAMS ((struct bfd_link_order *)); + +/* Final link relocation routine. */ +extern bfd_reloc_status_type _bfd_final_link_relocate + PARAMS ((const reloc_howto_type *, bfd *, asection *, bfd_byte *, + bfd_vma address, bfd_vma value, bfd_vma addend)); + +/* Relocate a particular location by a howto and a value. */ +extern bfd_reloc_status_type _bfd_relocate_contents + PARAMS ((const reloc_howto_type *, bfd *, bfd_vma, bfd_byte *)); + /* Macros to tell if bfds are read or write enabled. Note that bfds open for read may be scribbled into if the fd passed @@ -183,20 +403,16 @@ extern bfd *bfd_last_cache; #define stoi(x) ((int)(x)) #endif -/* Generic routine for close_and_cleanup is really just bfd_true. */ -#define bfd_generic_close_and_cleanup bfd_true +/* List of supported target vectors, and the default vector (if + bfd_default_vector[0] is NULL, there is no default). */ +extern const bfd_target * const bfd_target_vector[]; +extern const bfd_target * const bfd_default_vector[]; /* And more follows */ void bfd_check_init PARAMS ((void)); -PTR -bfd_xmalloc PARAMS (( bfd_size_type size)); - -PTR -bfd_xmalloc_by_size_t PARAMS (( size_t size)); - void bfd_write_bigendian_4byte_int PARAMS ((bfd *abfd, int i)); @@ -211,42 +427,41 @@ extern bfd *bfd_last_cache; (FILE*)(bfd_last_cache->iostream): \ bfd_cache_lookup_worker(x)) boolean -bfd_cache_close PARAMS ((bfd *)); +bfd_cache_init PARAMS ((bfd *abfd)); + +boolean +bfd_cache_close PARAMS ((bfd *abfd)); FILE* -bfd_open_file PARAMS ((bfd *)); +bfd_open_file PARAMS ((bfd *abfd)); FILE * -bfd_cache_lookup_worker PARAMS ((bfd *)); +bfd_cache_lookup_worker PARAMS ((bfd *abfd)); -void +boolean bfd_constructor_entry PARAMS ((bfd *abfd, asymbol **symbol_ptr_ptr, CONST char*type)); -CONST struct reloc_howto_struct * +const struct reloc_howto_struct * bfd_default_reloc_type_lookup - PARAMS ((bfd *abfd AND - bfd_reloc_code_real_type code)); + PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); boolean bfd_generic_relax_section PARAMS ((bfd *abfd, asection *section, - asymbol **symbols)); + struct bfd_link_info *, + boolean *)); bfd_byte * bfd_generic_get_relocated_section_contents PARAMS ((bfd *abfd, - struct bfd_seclet *seclet, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, bfd_byte *data, - boolean relocateable)); - -boolean -bfd_generic_seclet_link - PARAMS ((bfd *abfd, - PTR data, - boolean relocateable)); + boolean relocateable, + asymbol **symbols)); extern bfd_arch_info_type bfd_default_arch_struct; boolean @@ -254,11 +469,11 @@ bfd_default_set_arch_mach PARAMS ((bfd *abfd, enum bfd_architecture arch, unsigned long mach)); -void +void bfd_arch_init PARAMS ((void)); void -bfd_arch_linkin PARAMS ((bfd_arch_info_type *)); +bfd_arch_linkin PARAMS ((bfd_arch_info_type *ptr)); CONST bfd_arch_info_type * bfd_default_compatible @@ -266,7 +481,7 @@ bfd_default_compatible CONST bfd_arch_info_type *b)); boolean -bfd_default_scan PARAMS ((CONST struct bfd_arch_info *, CONST char *)); +bfd_default_scan PARAMS ((CONST struct bfd_arch_info *info, CONST char *string)); struct elf_internal_shdr * bfd_elf_find_section PARAMS ((bfd *abfd, char *name)); diff --git a/gnu/usr.bin/gdb/bfd/libcoff.h b/gnu/usr.bin/gdb/bfd/libcoff.h index 2aa6ad4b1615..a564f118641b 100644 --- a/gnu/usr.bin/gdb/bfd/libcoff.h +++ b/gnu/usr.bin/gdb/bfd/libcoff.h @@ -1,5 +1,5 @@ /* BFD COFF object file private structure. - Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -75,20 +75,20 @@ typedef struct coff_tdata #define coffsymbol(asymbol) ((coff_symbol_type *)(&((asymbol)->the_bfd))) /* Functions in coffgen.c. */ -extern bfd_target *coff_object_p PARAMS ((bfd *)); +extern const bfd_target *coff_object_p PARAMS ((bfd *)); extern struct sec *coff_section_from_bfd_index PARAMS ((bfd *, int)); -extern unsigned int coff_get_symtab_upper_bound PARAMS ((bfd *)); -extern unsigned int coff_get_symtab PARAMS ((bfd *, asymbol **)); +extern long coff_get_symtab_upper_bound PARAMS ((bfd *)); +extern long coff_get_symtab PARAMS ((bfd *, asymbol **)); extern int coff_count_linenumbers PARAMS ((bfd *)); extern struct coff_symbol_struct *coff_symbol_from PARAMS ((bfd *, asymbol *)); -extern void coff_renumber_symbols PARAMS ((bfd *)); +extern boolean coff_renumber_symbols PARAMS ((bfd *)); extern void coff_mangle_symbols PARAMS ((bfd *)); -extern void coff_write_symbols PARAMS ((bfd *)); -extern void coff_write_linenumbers PARAMS ((bfd *)); +extern boolean coff_write_symbols PARAMS ((bfd *)); +extern boolean coff_write_linenumbers PARAMS ((bfd *)); extern alent *coff_get_lineno PARAMS ((bfd *, asymbol *)); extern asymbol *coff_section_symbol PARAMS ((bfd *, char *)); extern struct coff_ptr_struct *coff_get_normalized_symtab PARAMS ((bfd *)); -extern unsigned int coff_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); +extern long coff_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); extern asymbol *coff_make_empty_symbol PARAMS ((bfd *)); extern void coff_print_symbol PARAMS ((bfd *, PTR filep, asymbol *, bfd_print_symbol_type how)); @@ -104,30 +104,42 @@ extern boolean coff_find_nearest_line PARAMS ((bfd *, CONST char **functionname_ptr, unsigned int *line_ptr)); extern int coff_sizeof_headers PARAMS ((bfd *, boolean reloc)); -extern boolean bfd_coff_reloc16_relax_section PARAMS ((bfd *, - asection *, - asymbol **)); +extern boolean bfd_coff_reloc16_relax_section + PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *)); extern bfd_byte *bfd_coff_reloc16_get_relocated_section_contents - PARAMS ((bfd *, struct bfd_seclet *, bfd_byte *, boolean relocateable)); + PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *, boolean relocateable, asymbol **)); extern bfd_vma bfd_coff_reloc16_get_value PARAMS ((arelent *, - struct bfd_seclet *)); + struct bfd_link_info *, + asection *)); +extern void bfd_perform_slip PARAMS ((bfd *abfd, unsigned int slip, + asection *input_section, + bfd_vma val)); /* And more taken from the source .. */ -typedef struct coff_ptr_struct +typedef struct coff_ptr_struct { /* Remembers the offset from the first symbol in the file for this symbol. Generated by coff_renumber_symbols. */ unsigned int offset; + /* Should the value of this symbol be renumbered. Used for + XCOFF C_BSTAT symbols. Set by coff_slurp_symbol_table. */ +unsigned int fix_value : 1; + /* Should the tag field of this symbol be renumbered. Created by coff_pointerize_aux. */ -char fix_tag; +unsigned int fix_tag : 1; /* Should the endidx field of this symbol be renumbered. Created by coff_pointerize_aux. */ -char fix_end; +unsigned int fix_end : 1; + + /* Should the x_csect.x_scnlen field be renumbered. + Created by coff_slurp_symbol_table. */ +unsigned int fix_scnlen : 1; /* The container for the symbol structure as read and translated from the file. */ @@ -155,13 +167,15 @@ struct lineno_cache_entry *lineno; /* Have the line numbers been relocated yet ? */ boolean done_lineno; } coff_symbol_type; -typedef struct +typedef struct { void (*_bfd_coff_swap_aux_in) PARAMS (( - bfd *abfd , + bfd *abfd, PTR ext, int type, - int class , + int class, + int indaux, + int numaux, PTR in)); void (*_bfd_coff_swap_sym_in) PARAMS (( @@ -179,6 +193,8 @@ typedef struct PTR in, int type, int class, + int indaux, + int numaux, PTR ext)); unsigned int (*_bfd_coff_swap_sym_out) PARAMS (( @@ -257,23 +273,25 @@ typedef struct struct internal_syment *sym)); void (*_bfd_coff_reloc16_extra_cases) PARAMS (( bfd *abfd, - struct bfd_seclet *seclet, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, arelent *reloc, bfd_byte *data, unsigned int *src_ptr, unsigned int *dst_ptr)); int (*_bfd_coff_reloc16_estimate) PARAMS (( + bfd *abfd, asection *input_section, - asymbol **symbols, arelent *r, - unsigned int shrink)); + unsigned int shrink, + struct bfd_link_info *link_info)); } bfd_coff_backend_data; #define coff_backend_info(abfd) ((bfd_coff_backend_data *) (abfd)->xvec->backend_data) -#define bfd_coff_swap_aux_in(a,e,t,c,i) \ - ((coff_backend_info (a)->_bfd_coff_swap_aux_in) (a,e,t,c,i)) +#define bfd_coff_swap_aux_in(a,e,t,c,ind,num,i) \ + ((coff_backend_info (a)->_bfd_coff_swap_aux_in) (a,e,t,c,ind,num,i)) #define bfd_coff_swap_sym_in(a,e,i) \ ((coff_backend_info (a)->_bfd_coff_swap_sym_in) (a,e,i)) @@ -287,8 +305,8 @@ typedef struct #define bfd_coff_swap_lineno_out(abfd, i, o) \ ((coff_backend_info (abfd)->_bfd_coff_swap_lineno_out) (abfd, i, o)) -#define bfd_coff_swap_aux_out(abfd, i, t,c,o) \ - ((coff_backend_info (abfd)->_bfd_coff_swap_aux_out) (abfd, i,t,c, o)) +#define bfd_coff_swap_aux_out(a,i,t,c,ind,num,o) \ + ((coff_backend_info (a)->_bfd_coff_swap_aux_out) (a,i,t,c,ind,num,o)) #define bfd_coff_swap_sym_out(abfd, i,o) \ ((coff_backend_info (abfd)->_bfd_coff_swap_sym_out) (abfd, i, o)) @@ -341,12 +359,11 @@ typedef struct #define bfd_coff_symname_in_debug(abfd, sym)\ ((coff_backend_info (abfd)->_bfd_coff_symname_in_debug) (abfd, sym)) -#define bfd_coff_reloc16_extra_cases(abfd, seclet, reloc, data, src_ptr, dst_ptr)\ +#define bfd_coff_reloc16_extra_cases(abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)\ ((coff_backend_info (abfd)->_bfd_coff_reloc16_extra_cases)\ - (abfd, seclet, reloc, data, src_ptr, dst_ptr)) + (abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)) -#define bfd_coff_reloc16_estimate(abfd, section, symbols, reloc, shrink)\ +#define bfd_coff_reloc16_estimate(abfd, section, reloc, shrink, link_info)\ ((coff_backend_info (abfd)->_bfd_coff_reloc16_estimate)\ - (section, symbols, reloc, shrink)) - - + (abfd, section, reloc, shrink, link_info)) + diff --git a/gnu/usr.bin/gdb/bfd/libecoff.h b/gnu/usr.bin/gdb/bfd/libecoff.h index ad3e8f223aa4..2f7b852872a3 100644 --- a/gnu/usr.bin/gdb/bfd/libecoff.h +++ b/gnu/usr.bin/gdb/bfd/libecoff.h @@ -18,6 +18,12 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "bfdlink.h" + +#ifndef ECOFF_H +#include "coff/ecoff.h" +#endif + /* This is the backend information kept for ECOFF files. This structure is constant for a particular backend. The first element is the COFF backend data structure, so that ECOFF targets can use @@ -32,57 +38,36 @@ struct ecoff_backend_data bfd_coff_backend_data coff; /* Supported architecture. */ enum bfd_architecture arch; - /* Symbol table magic number. */ - int sym_magic; /* Initial portion of armap string. */ const char *armap_start; - /* Alignment of debugging information. E.g., 4. */ - bfd_size_type debug_align; /* The page boundary used to align sections in a demand-paged executable file. E.g., 0x1000. */ bfd_vma round; + /* True if the .rdata section is part of the text segment, as on the + Alpha. False if .rdata is part of the data segment, as on the + MIPS. */ + boolean rdata_in_text; /* Bitsize of constructor entries. */ unsigned int constructor_bitsize; /* Reloc to use for constructor entries. */ CONST struct reloc_howto_struct *constructor_reloc; - /* Sizes of external symbolic information. */ - bfd_size_type external_hdr_size; - bfd_size_type external_dnr_size; - bfd_size_type external_pdr_size; - bfd_size_type external_sym_size; - bfd_size_type external_opt_size; - bfd_size_type external_fdr_size; - bfd_size_type external_rfd_size; - bfd_size_type external_ext_size; - /* Functions to swap in external symbolic data. */ - void (*swap_hdr_in) PARAMS ((bfd *, PTR, HDRR *)); - void (*swap_dnr_in) PARAMS ((bfd *, PTR, DNR *)); - void (*swap_pdr_in) PARAMS ((bfd *, PTR, PDR *)); - void (*swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)); - void (*swap_opt_in) PARAMS ((bfd *, PTR, OPTR *)); - void (*swap_fdr_in) PARAMS ((bfd *, PTR, FDR *)); - void (*swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *)); - void (*swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)); - /* Functions to swap out external symbolic data. */ - void (*swap_hdr_out) PARAMS ((bfd *, const HDRR *, PTR)); - void (*swap_dnr_out) PARAMS ((bfd *, const DNR *, PTR)); - void (*swap_pdr_out) PARAMS ((bfd *, const PDR *, PTR)); - void (*swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR)); - void (*swap_opt_out) PARAMS ((bfd *, const OPTR *, PTR)); - void (*swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR)); - void (*swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR)); - void (*swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR)); - /* It so happens that the auxiliary type information has the same - type and format for all known ECOFF targets. I don't see any - reason that that should change, so at least for now the auxiliary - swapping information is not in this table. */ + /* How to swap debugging information. */ + struct ecoff_debug_swap debug_swap; /* External reloc size. */ bfd_size_type external_reloc_size; /* Reloc swapping functions. */ void (*swap_reloc_in) PARAMS ((bfd *, PTR, struct internal_reloc *)); void (*swap_reloc_out) PARAMS ((bfd *, const struct internal_reloc *, PTR)); /* Backend reloc tweaking. */ - void (*finish_reloc) PARAMS ((bfd *, struct internal_reloc *, arelent *)); + void (*adjust_reloc_in) PARAMS ((bfd *, const struct internal_reloc *, + arelent *)); + void (*adjust_reloc_out) PARAMS ((bfd *, const arelent *, + struct internal_reloc *)); + /* Relocate section contents while linking. */ + boolean (*relocate_section) PARAMS ((bfd *output_bfd, struct bfd_link_info *, + bfd *input_bfd, asection *input_section, + bfd_byte *contents, + PTR external_relocs)); }; /* This is the target specific information kept for ECOFF files. */ @@ -95,7 +80,7 @@ typedef struct ecoff_tdata ecoff_compute_section_file_positions. */ file_ptr reloc_filepos; - /* The symbol table file position, set by ecoff_mkobject_hook. */ + /* The symbol table file position, set by _bfd_ecoff_mkobject_hook. */ file_ptr sym_filepos; /* The start and end of the text segment. Only valid for an @@ -119,38 +104,26 @@ typedef struct ecoff_tdata unsigned long fprmask; unsigned long cprmask[4]; - /* The size of the unswapped ECOFF symbolic information. */ - bfd_size_type raw_size; + /* The ECOFF symbolic debugging information. */ + struct ecoff_debug_info debug_info; /* The unswapped ECOFF symbolic information. */ PTR raw_syments; - /* The swapped ECOFF symbolic header. */ - HDRR symbolic_header; - - /* Pointers to the unswapped symbolic information. */ - unsigned char *line; - PTR external_dnr; /* struct dnr_ext */ - PTR external_pdr; /* struct pdr_ext */ - PTR external_sym; /* struct sym_ext */ - PTR external_opt; /* struct opt_ext */ - union aux_ext *external_aux; - char *ss; - char *ssext; - PTR external_fdr; /* struct fdr_ext */ - PTR external_rfd; /* struct rfd_ext */ - PTR external_ext; /* struct ext_ext */ - - /* The swapped FDR information. */ - FDR *fdr; - - /* The FDR index. This is set for an input BFD to a link so that - the external symbols can set their FDR index correctly. */ - unsigned int ifdbase; - /* The canonical BFD symbols. */ struct ecoff_symbol_struct *canonical_symbols; + /* A mapping from external symbol numbers to entries in the linker + hash table, used when linking. */ + struct ecoff_link_hash_entry **sym_hashes; + + /* A mapping from reloc symbol indices to sections, used when + linking. */ + asection **symndx_to_section; + + /* True if this BFD was written by the backend linker. */ + boolean linker; + } ecoff_data_type; /* Each canonical asymbol really looks like this. */ @@ -182,84 +155,143 @@ typedef struct ecoff_symbol_struct #define ecoff_get_sym_index(symbol) ((unsigned long) (symbol)->udata) #define ecoff_set_sym_index(symbol, idx) ((symbol)->udata = (PTR) (idx)) +/* When generating MIPS embedded PIC code, the linker relaxes the code + to turn PC relative branches into longer code sequences when the PC + relative branch is out of range. This involves reading the relocs + in bfd_relax_section as well as in bfd_final_link, and requires the + code to keep track of which relocs have been expanded. A pointer + to this structure is put in the used_by_bfd pointer of a section to + keep track of this information. The user_by_bfd pointer will be + NULL if the information was not needed. */ + +struct ecoff_section_tdata +{ + /* The unswapped relocs for this section. These are stored in + memory so the input file does not have to be read twice. */ + PTR external_relocs; + + /* The contents of the section. These bytes may or may not be saved + in memory, but if it is this is a pointer to them. */ + bfd_byte *contents; + + /* Offset adjustments for PC relative branches. A number other than + 1 is an addend for a PC relative branch, or a switch table entry + which is the difference of two .text locations; this addend + arises because the branch or difference crosses one or more + branches which were expanded into a larger code sequence. A 1 + means that this branch was itself expanded into a larger code + sequence. 1 is not a possible offset, since all offsets must be + multiples of the instruction size, which is 4; also, the only + relocs with non-zero offsets will be PC relative branches or + switch table entries within the same object file. If this field + is NULL, no branches were expanded and no offsets are required. + Otherwise there are as many entries as there are relocs in the + section, and the entry for any reloc that is not PC relative is + zero. */ + long *offsets; +}; + +/* An accessor macro for the ecoff_section_tdata structure. */ +#define ecoff_section_data(abfd, sec) \ + ((struct ecoff_section_tdata *) (sec)->used_by_bfd) + +/* ECOFF linker hash table entries. */ + +struct ecoff_link_hash_entry +{ + struct bfd_link_hash_entry root; + /* Symbol index in output file. */ + long indx; + /* BFD that ext field value came from. */ + bfd *abfd; + /* ECOFF external symbol information. */ + EXTR esym; + /* Nonzero if this symbol has been written out. */ + char written; + /* Nonzero if this symbol was referred to as small undefined. */ + char small; +}; + +/* ECOFF linker hash table. */ + +struct ecoff_link_hash_table +{ + struct bfd_link_hash_table root; +}; + /* Make an ECOFF object. */ -extern boolean ecoff_mkobject PARAMS ((bfd *)); +extern boolean _bfd_ecoff_mkobject PARAMS ((bfd *)); /* Read in the ECOFF symbolic debugging information. */ -extern boolean ecoff_slurp_symbolic_info PARAMS ((bfd *)); +extern boolean _bfd_ecoff_slurp_symbolic_info + PARAMS ((bfd *, asection *, struct ecoff_debug_info *)); /* Generic ECOFF BFD backend vectors. */ -extern asymbol *ecoff_make_empty_symbol PARAMS ((bfd *abfd)); -extern unsigned int ecoff_get_symtab_upper_bound PARAMS ((bfd *abfd)); -extern unsigned int ecoff_get_symtab PARAMS ((bfd *abfd, - asymbol **alocation)); -extern void ecoff_get_symbol_info PARAMS ((bfd *abfd, - asymbol *symbol, - symbol_info *ret)); -extern void ecoff_print_symbol PARAMS ((bfd *abfd, PTR filep, - asymbol *symbol, - bfd_print_symbol_type how)); -extern unsigned int ecoff_canonicalize_reloc PARAMS ((bfd *abfd, - asection *section, - arelent **relptr, - asymbol **symbols)); -extern boolean ecoff_find_nearest_line PARAMS ((bfd *abfd, - asection *section, - asymbol **symbols, - bfd_vma offset, - CONST char **filename_ptr, - CONST char **fnname_ptr, - unsigned int *retline_ptr)); -extern boolean ecoff_bfd_seclet_link PARAMS ((bfd *abfd, PTR data, - boolean relocateable)); -extern boolean ecoff_set_arch_mach PARAMS ((bfd *abfd, - enum bfd_architecture arch, - unsigned long machine)); -extern int ecoff_sizeof_headers PARAMS ((bfd *abfd, boolean reloc)); -extern boolean ecoff_set_section_contents PARAMS ((bfd *abfd, - asection *section, - PTR location, - file_ptr offset, - bfd_size_type count)); -extern boolean ecoff_get_section_contents PARAMS ((bfd *abfd, - asection *section, - PTR location, - file_ptr offset, - bfd_size_type count)); -extern boolean ecoff_write_object_contents PARAMS ((bfd *abfd)); -extern boolean ecoff_slurp_armap PARAMS ((bfd *abfd)); -extern boolean ecoff_write_armap PARAMS ((bfd *abfd, unsigned int elength, - struct orl *map, - unsigned int orl_count, - int stridx)); -#define ecoff_slurp_extended_name_table _bfd_slurp_extended_name_table -extern bfd_target *ecoff_archive_p PARAMS ((bfd *abfd)); -#define ecoff_get_lineno \ - ((alent *(*) PARAMS ((bfd *, asymbol *))) bfd_nullvoidptr) -#define ecoff_truncate_arname bfd_dont_truncate_arname -#define ecoff_openr_next_archived_file bfd_generic_openr_next_archived_file -#define ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt -#define ecoff_get_reloc_upper_bound coff_get_reloc_upper_bound -#define ecoff_close_and_cleanup bfd_generic_close_and_cleanup -#define ecoff_bfd_debug_info_start bfd_void -#define ecoff_bfd_debug_info_end bfd_void -#define ecoff_bfd_debug_info_accumulate \ - ((void (*) PARAMS ((bfd *, struct sec *))) bfd_void) -#define ecoff_bfd_get_relocated_section_contents \ - bfd_generic_get_relocated_section_contents -#define ecoff_bfd_relax_section bfd_generic_relax_section -#define ecoff_bfd_make_debug_symbol \ - ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) + +extern boolean _bfd_ecoff_write_object_contents PARAMS ((bfd *abfd)); +extern const bfd_target *_bfd_ecoff_archive_p PARAMS ((bfd *abfd)); + +#define _bfd_ecoff_close_and_cleanup _bfd_generic_close_and_cleanup +#define _bfd_ecoff_bfd_free_cached_info _bfd_generic_bfd_free_cached_info +extern boolean _bfd_ecoff_new_section_hook + PARAMS ((bfd *, asection *)); +extern boolean _bfd_ecoff_get_section_contents + PARAMS ((bfd *, asection *, PTR location, file_ptr, bfd_size_type)); + +extern boolean _bfd_ecoff_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *)); +#define _bfd_ecoff_bfd_copy_private_section_data \ + _bfd_generic_bfd_copy_private_section_data + +extern boolean _bfd_ecoff_slurp_armap PARAMS ((bfd *abfd)); +#define _bfd_ecoff_slurp_extended_name_table _bfd_slurp_extended_name_table +#define _bfd_ecoff_truncate_arname bfd_dont_truncate_arname +extern boolean _bfd_ecoff_write_armap + PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int)); +#define _bfd_ecoff_openr_next_archived_file \ + bfd_generic_openr_next_archived_file +#define _bfd_ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt + +extern long _bfd_ecoff_get_symtab_upper_bound PARAMS ((bfd *abfd)); +extern long _bfd_ecoff_get_symtab PARAMS ((bfd *abfd, asymbol **alocation)); +extern asymbol *_bfd_ecoff_make_empty_symbol PARAMS ((bfd *abfd)); +extern void _bfd_ecoff_print_symbol + PARAMS ((bfd *, PTR filep, asymbol *, bfd_print_symbol_type)); +extern void _bfd_ecoff_get_symbol_info + PARAMS ((bfd *, asymbol *, symbol_info *)); +#define _bfd_ecoff_bfd_is_local_label bfd_generic_is_local_label +#define _bfd_ecoff_get_lineno _bfd_nosymbols_get_lineno +extern boolean _bfd_ecoff_find_nearest_line + PARAMS ((bfd *, asection *, asymbol **, bfd_vma offset, + const char **filename_ptr, const char **fnname_ptr, + unsigned int *retline_ptr)); +#define _bfd_ecoff_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol + +#define _bfd_ecoff_get_reloc_upper_bound coff_get_reloc_upper_bound +extern long _bfd_ecoff_canonicalize_reloc + PARAMS ((bfd *, asection *, arelent **, asymbol **symbols)); +/* ecoff_bfd_reloc_type_lookup defined by backend. */ + +extern boolean _bfd_ecoff_set_arch_mach + PARAMS ((bfd *, enum bfd_architecture, unsigned long machine)); +extern boolean _bfd_ecoff_set_section_contents + PARAMS ((bfd *, asection *, PTR location, file_ptr, bfd_size_type)); + +extern int _bfd_ecoff_sizeof_headers PARAMS ((bfd *abfd, boolean reloc)); +/* ecoff_bfd_get_relocated_section_contents defined by backend. */ +/* ecoff_bfd_relax_section defined by backend. */ +extern struct bfd_link_hash_table *_bfd_ecoff_bfd_link_hash_table_create + PARAMS ((bfd *)); +extern boolean _bfd_ecoff_bfd_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +extern boolean _bfd_ecoff_bfd_final_link + PARAMS ((bfd *, struct bfd_link_info *)); /* Hook functions for the generic COFF section reading code. */ -extern PTR ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr)); -extern asection *ecoff_make_section_hook PARAMS ((bfd *abfd, char *name)); -extern boolean ecoff_new_section_hook PARAMS ((bfd *abfd, - asection *section)); -#define ecoff_set_alignment_hook \ + +extern PTR _bfd_ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr)); +extern asection *_bfd_ecoff_make_section_hook PARAMS ((bfd *abfd, char *name)); +#define _bfd_ecoff_set_alignment_hook \ ((void (*) PARAMS ((bfd *, asection *, PTR))) bfd_void) -extern boolean ecoff_set_arch_mach_hook PARAMS ((bfd *abfd, PTR filehdr)); -extern long ecoff_sec_to_styp_flags PARAMS ((CONST char *name, - flagword flags)); -extern flagword ecoff_styp_to_sec_flags PARAMS ((bfd *abfd, PTR hdr)); -extern boolean ecoff_slurp_symbol_table PARAMS ((bfd *abfd)); +extern boolean _bfd_ecoff_set_arch_mach_hook PARAMS ((bfd *abfd, PTR filehdr)); +extern flagword _bfd_ecoff_styp_to_sec_flags PARAMS ((bfd *abfd, PTR hdr)); +extern boolean _bfd_ecoff_slurp_symbol_table PARAMS ((bfd *abfd)); diff --git a/gnu/usr.bin/gdb/bfd/libelf.h b/gnu/usr.bin/gdb/bfd/libelf.h index 187c51a29c0b..cc6d8b81d38e 100644 --- a/gnu/usr.bin/gdb/bfd/libelf.h +++ b/gnu/usr.bin/gdb/bfd/libelf.h @@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "elf/common.h" #include "elf/internal.h" #include "elf/external.h" +#include "bfdlink.h" /* If size isn't specified as 64 or 32, NAME macro should fail. */ #ifndef NAME @@ -42,36 +43,331 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define ElfNAME(X) NAME(Elf,X) #define elfNAME(X) NAME(elf,X) +/* Information held for an ELF symbol. The first field is the + corresponding asymbol. Every symbol is an ELF file is actually a + pointer to this structure, although it is often handled as a + pointer to an asymbol. */ + typedef struct { + /* The BFD symbol. */ asymbol symbol; + /* ELF symbol information. */ Elf_Internal_Sym internal_elf_sym; + /* Backend specific information. */ union { unsigned int hppa_arg_reloc; + PTR mips_extr; PTR any; } tc_data; } elf_symbol_type; + +/* ELF linker hash table entries. */ + +struct elf_link_hash_entry +{ + struct bfd_link_hash_entry root; + + /* Symbol index in output file. This is initialized to -1. It is + set to -2 if the symbol is used by a reloc. */ + long indx; + + /* Symbol size. */ + bfd_size_type size; + + /* Symbol alignment (common symbols only). */ + bfd_size_type align; + + /* Symbol index as a dynamic symbol. Initialized to -1, and remains + -1 if this is not a dynamic symbol. */ + long dynindx; + + /* String table index in .dynstr if this is a dynamic symbol. */ + unsigned long dynstr_index; + + /* If this is a weak defined symbol from a dynamic object, this + field points to a defined symbol with the same value, if there is + one. Otherwise it is NULL. */ + struct elf_link_hash_entry *weakdef; + + /* Symbol type (STT_NOTYPE, STT_OBJECT, etc.). */ + char type; + + /* Some flags; legal values follow. */ + unsigned char elf_link_hash_flags; + /* Symbol is referenced by a non-shared object. */ +#define ELF_LINK_HASH_REF_REGULAR 01 + /* Symbol is defined by a non-shared object. */ +#define ELF_LINK_HASH_DEF_REGULAR 02 + /* Symbol is referenced by a shared object. */ +#define ELF_LINK_HASH_REF_DYNAMIC 04 + /* Symbol is defined by a shared object. */ +#define ELF_LINK_HASH_DEF_DYNAMIC 010 + /* Symbol is referenced by two or more shared objects. */ +#define ELF_LINK_HASH_REF_DYNAMIC_MULTIPLE 020 + /* Symbol is defined by two or more shared objects. */ +#define ELF_LINK_HASH_DEF_DYNAMIC_MULTIPLE 040 + /* Dynamic symbol has been adjustd. */ +#define ELF_LINK_HASH_DYNAMIC_ADJUSTED 0100 + /* Symbol is defined as weak. */ +#define ELF_LINK_HASH_DEFINED_WEAK 0200 +}; + +/* ELF linker hash table. */ + +struct elf_link_hash_table +{ + struct bfd_link_hash_table root; + /* The first dynamic object found during a link. We create several + special input sections when linking against dynamic objects, and + we simply attach them to the first one found. */ + bfd *dynobj; + /* The number of symbols found in the link which must be put into + the .dynsym section. */ + size_t dynsymcount; + /* The string table of dynamic symbols, which becomes the .dynstr + section. */ + struct strtab *dynstr; + /* The number of buckets in the hash table in the .hash section. + This is based on the number of dynamic symbols. */ + size_t bucketcount; +}; + +/* Look up an entry in an ELF linker hash table. */ + +#define elf_link_hash_lookup(table, string, create, copy, follow) \ + ((struct elf_link_hash_entry *) \ + bfd_link_hash_lookup (&(table)->root, (string), (create), \ + (copy), (follow))) + +/* Traverse an ELF linker hash table. */ + +#define elf_link_hash_traverse(table, func, info) \ + (bfd_link_hash_traverse \ + (&(table)->root, \ + (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \ + (info))) + +/* Get the ELF linker hash table from a link_info structure. */ + +#define elf_hash_table(p) ((struct elf_link_hash_table *) ((p)->hash)) + +/* Constant information held for an ELF backend. */ struct elf_backend_data { + /* Whether the backend uses REL or RELA relocations. FIXME: some + ELF backends use both. When we need to support one, this whole + approach will need to be changed. */ int use_rela_p; + + /* Whether this backend is 64 bits or not. FIXME: Who cares? */ int elf_64_p; + + /* The architecture for this backend. */ enum bfd_architecture arch; + + /* The ELF machine code (EM_xxxx) for this backend. */ + int elf_machine_code; + + /* The maximum page size for this backend. */ + bfd_vma maxpagesize; + + /* This is true if the linker should act like collect and gather + global constructors and destructors by name. This is true for + MIPS ELF because the Irix 5 tools can not handle the .init + section. */ + boolean collect; + + /* A function to translate an ELF RELA relocation to a BFD arelent + structure. */ void (*elf_info_to_howto) PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); + + /* A function to translate an ELF REL relocation to a BFD arelent + structure. */ void (*elf_info_to_howto_rel) PARAMS ((bfd *, arelent *, Elf_Internal_Rel *)); - bfd_vma maxpagesize; - void (*write_relocs) PARAMS ((bfd *, asection *, PTR)); + /* A function to determine whether a symbol is global when + partitioning the symbol table into local and global symbols. + This should be NULL for most targets, in which case the correct + thing will be done. MIPS ELF, at least on the Irix 5, has + special requirements. */ + boolean (*elf_backend_sym_is_global) PARAMS ((bfd *, asymbol *)); + + /* The remaining functions are hooks which are called only if they + are not NULL. */ + + /* A function to permit a backend specific check on whether a + particular BFD format is relevant for an object file, and to + permit the backend to set any global information it wishes. When + this is called elf_elfheader is set, but anything else should be + used with caution. If this returns false, the check_format + routine will return a bfd_error_wrong_format error. */ + boolean (*elf_backend_object_p) PARAMS ((bfd *)); + + /* A function to do additional symbol processing when reading the + ELF symbol table. This is where any processor-specific special + section indices are handled. */ void (*elf_backend_symbol_processing) PARAMS ((bfd *, asymbol *)); - boolean (*elf_backend_symbol_table_processing) PARAMS ((bfd *, elf_symbol_type *, int)); - boolean (*elf_backend_section_processing) PARAMS ((bfd *, Elf32_Internal_Shdr *)); - boolean (*elf_backend_section_from_shdr) PARAMS ((bfd *, Elf32_Internal_Shdr *, char *)); - boolean (*elf_backend_fake_sections) PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *)); - boolean (*elf_backend_section_from_bfd_section) PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *, int *)); + + /* A function to do additional symbol processing after reading the + entire ELF symbol table. */ + boolean (*elf_backend_symbol_table_processing) PARAMS ((bfd *, + elf_symbol_type *, + int)); + + /* A function to do additional processing on the ELF section header + just before writing it out. This is used to set the flags and + type fields for some sections, or to actually write out data for + unusual sections. */ + boolean (*elf_backend_section_processing) PARAMS ((bfd *, + Elf32_Internal_Shdr *)); + + /* A function to handle unusual section types when creating BFD + sections from ELF sections. */ + boolean (*elf_backend_section_from_shdr) PARAMS ((bfd *, + Elf32_Internal_Shdr *, + char *)); + + /* A function to set up the ELF section header for a BFD section in + preparation for writing it out. This is where the flags and type + fields are set for unusual sections. */ + boolean (*elf_backend_fake_sections) PARAMS ((bfd *, Elf32_Internal_Shdr *, + asection *)); + + /* A function to get the ELF section index for a BFD section. If + this returns true, the section was found. If it is a normal ELF + section, *RETVAL should be left unchanged. If it is not a normal + ELF section *RETVAL should be set to the SHN_xxxx index. */ + boolean (*elf_backend_section_from_bfd_section) + PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *, int *retval)); + + /* If this field is not NULL, it is called by the add_symbols phase + of a link just before adding a symbol to the global linker hash + table. It may modify any of the fields as it wishes. If *NAME + is set to NULL, the symbol will be skipped rather than being + added to the hash table. This function is responsible for + handling all processor dependent symbol bindings and section + indices, and must set at least *FLAGS and *SEC for each processor + dependent case; failure to do so will cause a link error. */ + boolean (*elf_add_symbol_hook) + PARAMS ((bfd *abfd, struct bfd_link_info *info, + const Elf_Internal_Sym *, const char **name, + flagword *flags, asection **sec, bfd_vma *value)); + + /* If this field is not NULL, it is called by the elf_link_output_sym + phase of a link for each symbol which will appear in the object file. */ + boolean (*elf_backend_link_output_symbol_hook) + PARAMS ((bfd *, struct bfd_link_info *info, const char *, + Elf_Internal_Sym *, asection *)); + + /* The CREATE_DYNAMIC_SECTIONS function is called by the ELF backend + linker the first time it encounters a dynamic object in the link. + This function must create any sections required for dynamic + linking. The ABFD argument is a dynamic object. The .interp, + .dynamic, .dynsym, .dynstr, and .hash functions have already been + created, and this function may modify the section flags if + desired. This function will normally create the .got and .plt + sections, but different backends have different requirements. */ + boolean (*elf_backend_create_dynamic_sections) + PARAMS ((bfd *abfd, struct bfd_link_info *info)); + + /* The ADJUST_DYNAMIC_SYMBOL function is called by the ELF backend + linker for every symbol which is defined by a dynamic object and + referenced by a regular object. This is called after all the + input files have been seen, but before the SIZE_DYNAMIC_SECTIONS + function has been called. The hash table entry should be + bfd_link_hash_defined, and it should be defined in a section from + a dynamic object. Dynamic object sections are not included in + the final link, and this function is responsible for changing the + value to something which the rest of the link can deal with. + This will normally involve adding an entry to the .plt or .got or + some such section, and setting the symbol to point to that. */ + boolean (*elf_backend_adjust_dynamic_symbol) + PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h)); + + /* The SIZE_DYNAMIC_SECTIONS function is called by the ELF backend + linker after all the linker input files have been seen but before + the sections sizes have been set. This is called after + ADJUST_DYNAMIC_SYMBOL has been called on all appropriate symbols. + It is only called when linking against a dynamic object. It must + set the sizes of the dynamic sections, and may fill in their + contents as well. The generic ELF linker can handle the .dynsym, + .dynstr and .hash sections. This function must handle the + .interp section and any sections created by the + CREATE_DYNAMIC_SECTIONS entry point. */ + boolean (*elf_backend_size_dynamic_sections) + PARAMS ((bfd *output_bfd, struct bfd_link_info *info)); + + /* The RELOCATE_SECTION function is called by the ELF backend linker + to handle the relocations for a section. + + The relocs are always passed as Rela structures; if the section + actually uses Rel structures, the r_addend field will always be + zero. + + This function is responsible for adjust the section contents as + necessary, and (if using Rela relocs and generating a + relocateable output file) adjusting the reloc addend as + necessary. + + This function does not have to worry about setting the reloc + address or the reloc symbol index. + + LOCAL_SYMS is a pointer to the swapped in local symbols. + + LOCAL_SECTIONS is an array giving the section in the input file + corresponding to the st_shndx field of each local symbol. + + The global hash table entry for the global symbols can be found + via elf_sym_hashes (input_bfd). + + When generating relocateable output, this function must handle + STB_LOCAL/STT_SECTION symbols specially. The output symbol is + going to be the section symbol corresponding to the output + section, which means that the addend must be adjusted + accordingly. */ + boolean (*elf_backend_relocate_section) + PARAMS ((bfd *output_bfd, struct bfd_link_info *info, + bfd *input_bfd, asection *input_section, bfd_byte *contents, + Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms, + asection **local_sections, char *output_names)); + + /* The FINISH_DYNAMIC_SYMBOL function is called by the ELF backend + linker just before it writes a symbol out to the .dynsym section. + The processor backend may make any required adjustment to the + symbol. It may also take the opportunity to set contents of the + dynamic sections. Note that FINISH_DYNAMIC_SYMBOL is called on + all .dynsym symbols, while ADJUST_DYNAMIC_SYMBOL is only called + on those symbols which are defined by a dynamic object. */ + boolean (*elf_backend_finish_dynamic_symbol) + PARAMS ((bfd *output_bfd, struct bfd_link_info *info, + struct elf_link_hash_entry *h, Elf_Internal_Sym *sym)); + + /* The FINISH_DYNAMIC_SECTIONS function is called by the ELF backend + linker just before it writes all the dynamic sections out to the + output file. The FINISH_DYNAMIC_SYMBOL will have been called on + all dynamic symbols. */ + boolean (*elf_backend_finish_dynamic_sections) + PARAMS ((bfd *output_bfd, struct bfd_link_info *info)); + + /* A function to do any beginning processing needed for the ELF file + before building the ELF headers and computing file positions. */ + void (*elf_backend_begin_write_processing) + PARAMS ((bfd *, struct bfd_link_info *)); + + /* A function to do any final processing needed for the ELF file + before writing it out. */ + void (*elf_backend_final_write_processing) + PARAMS ((bfd *, struct bfd_link_info *)); + + /* The swapping table to use when dealing with ECOFF information. + Used for the MIPS ELF .mdebug section. */ + const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap; }; struct elf_sym_extra @@ -81,21 +377,29 @@ struct elf_sym_extra typedef struct elf_sym_extra Elf_Sym_Extra; -struct bfd_elf_arch_map { - enum bfd_architecture bfd_arch; - int elf_arch; -}; - -extern const struct bfd_elf_arch_map bfd_elf_arch_map[]; -extern const int bfd_elf_arch_map_size; +/* Information stored for each BFD section in an ELF file. This + structure is allocated by elf_new_section_hook. */ struct bfd_elf_section_data { + /* The ELF header for this section. */ Elf_Internal_Shdr this_hdr; + /* The ELF header for the reloc section associated with this + section, if any. */ Elf_Internal_Shdr rel_hdr; - int this_idx, rel_idx; + /* The ELF section number of this section. Only used for an output + file. */ + int this_idx; + /* The ELF section number of the reloc section associated with this + section, if any. Only used for an output file. */ + int rel_idx; + /* Used by the backend linker to store the symbol hash table entries + associated with relocs against global symbols. */ + struct elf_link_hash_entry **rel_hashes; + /* A pointer to the unswapped external relocs; this may be NULL. */ + PTR relocs; }; + #define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd) -#define shdr_name(abfd,shdr) (elf_shstrtab (abfd)->tab + (shdr)->sh_name) #define get_elf_backend_data(abfd) \ ((struct elf_backend_data *) (abfd)->xvec->backend_data) @@ -118,20 +422,38 @@ struct elf_obj_tdata struct strtab *strtab_ptr; int num_locals; int num_globals; - Elf_Internal_Sym *internal_syms; - elf_symbol_type *symbols; /* elf_symbol_type */ Elf_Sym_Extra *sym_extra; asymbol **section_syms; /* STT_SECTION symbols for each section */ int num_section_syms; /* number of section_syms allocated */ Elf_Internal_Shdr symtab_hdr; Elf_Internal_Shdr shstrtab_hdr; Elf_Internal_Shdr strtab_hdr; - int symtab_section, shstrtab_section, strtab_section; + Elf_Internal_Shdr dynsymtab_hdr; + Elf_Internal_Shdr dynstrtab_hdr; + int symtab_section, shstrtab_section, strtab_section, dynsymtab_section; file_ptr next_file_pos; void *prstatus; /* The raw /proc prstatus structure */ void *prpsinfo; /* The raw /proc prpsinfo structure */ bfd_vma gp; /* The gp value (MIPS only, for now) */ int gp_size; /* The gp size (MIPS only, for now) */ + + /* A mapping from external symbols to entries in the linker hash + table, used when linking. This is indexed by the symbol index + minus the sh_info field of the symbol table header. */ + struct elf_link_hash_entry **sym_hashes; + + /* The linker ELF emulation code needs to let the backend ELF linker + know what filename should be used for a dynamic object if the + dynamic object is found using a search. This field is used to + hold that information. */ + const char *dt_needed_name; + + /* Irix 5 often screws up the symbol table, sorting local symbols + after global symbols. This flag is set if the symbol table in + this BFD appears to be screwed up. If it is, we ignore the + sh_info field in the symbol table header, and always read all the + symbols. */ + boolean bad_symtab; }; #define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data) @@ -139,6 +461,7 @@ struct elf_obj_tdata #define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr) #define elf_shstrtab(bfd) (elf_tdata(bfd) -> strtab_ptr) #define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section) +#define elf_dynsymtab(bfd) (elf_tdata(bfd) -> dynsymtab_section) #define elf_num_locals(bfd) (elf_tdata(bfd) -> num_locals) #define elf_num_globals(bfd) (elf_tdata(bfd) -> num_globals) #define elf_sym_extra(bfd) (elf_tdata(bfd) -> sym_extra) @@ -146,11 +469,12 @@ struct elf_obj_tdata #define elf_num_section_syms(bfd) (elf_tdata(bfd) -> num_section_syms) #define core_prpsinfo(bfd) (elf_tdata(bfd) -> prpsinfo) #define core_prstatus(bfd) (elf_tdata(bfd) -> prstatus) -#define obj_symbols(bfd) (elf_tdata(bfd) -> symbols) -#define obj_internal_syms(bfd) (elf_tdata(bfd) -> internal_syms) #define elf_gp(bfd) (elf_tdata(bfd) -> gp) #define elf_gp_size(bfd) (elf_tdata(bfd) -> gp_size) - +#define elf_sym_hashes(bfd) (elf_tdata(bfd) -> sym_hashes) +#define elf_dt_needed_name(bfd) (elf_tdata(bfd) -> dt_needed_name) +#define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab) + extern char * elf_string_from_elf_section PARAMS ((bfd *, unsigned, unsigned)); extern char * elf_get_str_section PARAMS ((bfd *, unsigned)); @@ -165,15 +489,27 @@ extern bfd_reloc_status_type bfd_elf_generic_reloc PARAMS ((bfd *, asymbol *, PTR, asection *, - bfd *)); + bfd *, + char **)); extern boolean bfd_elf_mkobject PARAMS ((bfd *)); extern Elf_Internal_Shdr *bfd_elf_find_section PARAMS ((bfd *, char *)); +extern boolean _bfd_elf_make_section_from_shdr + PARAMS ((bfd *abfd, Elf_Internal_Shdr *hdr, const char *name)); +extern struct bfd_hash_entry *_bfd_elf_link_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +extern struct bfd_link_hash_table *_bfd_elf_link_hash_table_create + PARAMS ((bfd *)); +extern boolean _bfd_elf_link_hash_table_init + PARAMS ((struct elf_link_hash_table *, bfd *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); extern boolean bfd_elf32_write_object_contents PARAMS ((bfd *)); extern boolean bfd_elf64_write_object_contents PARAMS ((bfd *)); -extern bfd_target *bfd_elf32_object_p PARAMS ((bfd *)); -extern bfd_target *bfd_elf32_core_file_p PARAMS ((bfd *)); +extern const bfd_target *bfd_elf32_object_p PARAMS ((bfd *)); +extern const bfd_target *bfd_elf32_core_file_p PARAMS ((bfd *)); extern char *bfd_elf32_core_file_failing_command PARAMS ((bfd *)); extern int bfd_elf32_core_file_failing_signal PARAMS ((bfd *)); extern boolean bfd_elf32_core_file_matches_executable_p PARAMS ((bfd *, @@ -182,12 +518,13 @@ extern boolean bfd_elf32_set_section_contents PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type)); -extern unsigned int bfd_elf32_get_symtab_upper_bound PARAMS ((bfd *)); -extern unsigned int bfd_elf32_get_symtab PARAMS ((bfd *, asymbol **)); -extern unsigned int bfd_elf32_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); -extern unsigned int bfd_elf32_canonicalize_reloc PARAMS ((bfd *, sec_ptr, - arelent **, - asymbol **)); +extern long bfd_elf32_get_symtab_upper_bound PARAMS ((bfd *)); +extern long bfd_elf32_get_symtab PARAMS ((bfd *, asymbol **)); +extern long bfd_elf32_get_dynamic_symtab_upper_bound PARAMS ((bfd *)); +extern long bfd_elf32_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **)); +extern long bfd_elf32_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); +extern long bfd_elf32_canonicalize_reloc PARAMS ((bfd *, sec_ptr, + arelent **, asymbol **)); extern asymbol *bfd_elf32_make_empty_symbol PARAMS ((bfd *)); extern void bfd_elf32_print_symbol PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type)); @@ -204,13 +541,36 @@ extern boolean bfd_elf32_find_nearest_line PARAMS ((bfd *, asection *, extern int bfd_elf32_sizeof_headers PARAMS ((bfd *, boolean)); extern void bfd_elf32__write_relocs PARAMS ((bfd *, asection *, PTR)); extern boolean bfd_elf32_new_section_hook PARAMS ((bfd *, asection *)); +extern boolean bfd_elf32_bfd_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +extern boolean bfd_elf32_bfd_final_link + PARAMS ((bfd *, struct bfd_link_info *)); + +extern void bfd_elf32_swap_symbol_in + PARAMS ((bfd *, Elf32_External_Sym *, Elf_Internal_Sym *)); +extern void bfd_elf32_swap_symbol_out + PARAMS ((bfd *, Elf_Internal_Sym *, Elf32_External_Sym *)); +extern void bfd_elf32_swap_reloc_in + PARAMS ((bfd *, Elf32_External_Rel *, Elf_Internal_Rel *)); +extern void bfd_elf32_swap_reloc_out + PARAMS ((bfd *, Elf_Internal_Rel *, Elf32_External_Rel *)); +extern void bfd_elf32_swap_reloca_in + PARAMS ((bfd *, Elf32_External_Rela *, Elf_Internal_Rela *)); +extern void bfd_elf32_swap_reloca_out + PARAMS ((bfd *, Elf_Internal_Rela *, Elf32_External_Rela *)); +extern void bfd_elf32_swap_dyn_in + PARAMS ((bfd *, const Elf32_External_Dyn *, Elf_Internal_Dyn *)); +extern void bfd_elf32_swap_dyn_out + PARAMS ((bfd *, const Elf_Internal_Dyn *, Elf32_External_Dyn *)); +extern boolean bfd_elf32_add_dynamic_entry + PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma)); /* If the target doesn't have reloc handling written yet: */ extern void bfd_elf32_no_info_to_howto PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); -extern bfd_target *bfd_elf64_object_p PARAMS ((bfd *)); -extern bfd_target *bfd_elf64_core_file_p PARAMS ((bfd *)); +extern const bfd_target *bfd_elf64_object_p PARAMS ((bfd *)); +extern const bfd_target *bfd_elf64_core_file_p PARAMS ((bfd *)); extern char *bfd_elf64_core_file_failing_command PARAMS ((bfd *)); extern int bfd_elf64_core_file_failing_signal PARAMS ((bfd *)); extern boolean bfd_elf64_core_file_matches_executable_p PARAMS ((bfd *, @@ -219,12 +579,13 @@ extern boolean bfd_elf64_set_section_contents PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type)); -extern unsigned int bfd_elf64_get_symtab_upper_bound PARAMS ((bfd *)); -extern unsigned int bfd_elf64_get_symtab PARAMS ((bfd *, asymbol **)); -extern unsigned int bfd_elf64_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); -extern unsigned int bfd_elf64_canonicalize_reloc PARAMS ((bfd *, sec_ptr, - arelent **, - asymbol **)); +extern long bfd_elf64_get_symtab_upper_bound PARAMS ((bfd *)); +extern long bfd_elf64_get_symtab PARAMS ((bfd *, asymbol **)); +extern long bfd_elf64_get_dynamic_symtab_upper_bound PARAMS ((bfd *)); +extern long bfd_elf64_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **)); +extern long bfd_elf64_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr)); +extern long bfd_elf64_canonicalize_reloc PARAMS ((bfd *, sec_ptr, + arelent **, asymbol **)); extern asymbol *bfd_elf64_make_empty_symbol PARAMS ((bfd *)); extern void bfd_elf64_print_symbol PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type)); @@ -241,6 +602,29 @@ extern boolean bfd_elf64_find_nearest_line PARAMS ((bfd *, asection *, extern int bfd_elf64_sizeof_headers PARAMS ((bfd *, boolean)); extern void bfd_elf64__write_relocs PARAMS ((bfd *, asection *, PTR)); extern boolean bfd_elf64_new_section_hook PARAMS ((bfd *, asection *)); +extern boolean bfd_elf64_bfd_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +extern boolean bfd_elf64_bfd_final_link + PARAMS ((bfd *, struct bfd_link_info *)); + +extern void bfd_elf64_swap_symbol_in + PARAMS ((bfd *, Elf64_External_Sym *, Elf_Internal_Sym *)); +extern void bfd_elf64_swap_symbol_out + PARAMS ((bfd *, Elf_Internal_Sym *, Elf64_External_Sym *)); +extern void bfd_elf64_swap_reloc_in + PARAMS ((bfd *, Elf64_External_Rel *, Elf_Internal_Rel *)); +extern void bfd_elf64_swap_reloc_out + PARAMS ((bfd *, Elf_Internal_Rel *, Elf64_External_Rel *)); +extern void bfd_elf64_swap_reloca_in + PARAMS ((bfd *, Elf64_External_Rela *, Elf_Internal_Rela *)); +extern void bfd_elf64_swap_reloca_out + PARAMS ((bfd *, Elf_Internal_Rela *, Elf64_External_Rela *)); +extern void bfd_elf64_swap_dyn_in + PARAMS ((bfd *, const Elf64_External_Dyn *, Elf_Internal_Dyn *)); +extern void bfd_elf64_swap_dyn_out + PARAMS ((bfd *, const Elf_Internal_Dyn *, Elf64_External_Dyn *)); +extern boolean bfd_elf64_add_dynamic_entry + PARAMS ((struct bfd_link_info *, bfd_vma, bfd_vma)); /* If the target doesn't have reloc handling written yet: */ extern void bfd_elf64_no_info_to_howto PARAMS ((bfd *, arelent *, diff --git a/gnu/usr.bin/gdb/bfd/opncls.c b/gnu/usr.bin/gdb/bfd/opncls.c index 42858c25919e..fb93153d29af 100644 --- a/gnu/usr.bin/gdb/bfd/opncls.c +++ b/gnu/usr.bin/gdb/bfd/opncls.c @@ -1,5 +1,5 @@ /* opncls.c -- open and close a BFD. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -22,29 +22,34 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "sysdep.h" #include "libbfd.h" #include "obstack.h" -extern void bfd_cache_init PARAMS ((bfd *)); -FILE *bfd_open_file PARAMS ((bfd *)); /* fdopen is a loser -- we should use stdio exclusively. Unfortunately if we do that we can't use fcntl. */ -#define obstack_chunk_alloc bfd_xmalloc_by_size_t +#define obstack_chunk_alloc malloc #define obstack_chunk_free free /* Return a new BFD. All BFD's are allocated through this routine. */ bfd * -new_bfd PARAMS ((void)) +_bfd_new_bfd () { bfd *nbfd; - nbfd = (bfd *)zalloc (sizeof (bfd)); + nbfd = (bfd *)bfd_zmalloc (sizeof (bfd)); if (!nbfd) - return 0; + { + bfd_set_error (bfd_error_no_memory); + return 0; + } bfd_check_init(); - obstack_begin((PTR)&nbfd->memory, 128); + if (!obstack_begin(&nbfd->memory, 128)) + { + bfd_set_error (bfd_error_no_memory); + return 0; + } nbfd->arch_info = &bfd_default_arch_struct; @@ -69,12 +74,12 @@ new_bfd PARAMS ((void)) /* Allocate a new BFD as a member of archive OBFD. */ bfd * -new_bfd_contained_in (obfd) +_bfd_new_bfd_contained_in (obfd) bfd *obfd; { bfd *nbfd; - nbfd = new_bfd(); + nbfd = _bfd_new_bfd(); nbfd->xvec = obfd->xvec; nbfd->my_archive = obfd; nbfd->direction = read_direction; @@ -84,7 +89,7 @@ new_bfd_contained_in (obfd) /* SECTION - Opening and Closing BFDs + Opening and closing BFDs */ @@ -93,33 +98,36 @@ FUNCTION bfd_openr SYNOPSIS - bfd *bfd_openr(CONST char *filename, CONST char*target); + bfd *bfd_openr(CONST char *filename, CONST char *target); DESCRIPTION - This function opens the file supplied (using <>) with the target - supplied, it returns a pointer to the created BFD. + Open the file @var{filename} (using <>) with the target + @var{target}. Return a pointer to the created BFD. - If NULL is returned then an error has occured. Possible errors - are <>, <> or <> error. + Calls <>, so @var{target} is interpreted as by + that function. + + If <> is returned then an error has occured. Possible errors + are <>, <> or <> error. */ bfd * -DEFUN(bfd_openr, (filename, target), - CONST char *filename AND - CONST char *target) +bfd_openr (filename, target) + CONST char *filename; + CONST char *target; { bfd *nbfd; - bfd_target *target_vec; + const bfd_target *target_vec; - nbfd = new_bfd(); + nbfd = _bfd_new_bfd(); if (nbfd == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } target_vec = bfd_find_target (target, nbfd); if (target_vec == NULL) { - bfd_error = invalid_target; + bfd_set_error (bfd_error_invalid_target); return NULL; } @@ -127,7 +135,7 @@ DEFUN(bfd_openr, (filename, target), nbfd->direction = read_direction; if (bfd_open_file (nbfd) == NULL) { - bfd_error = system_call_error; /* File didn't exist, or some such */ + bfd_set_error (bfd_error_system_call); /* File didn't exist, or some such */ bfd_release(nbfd,0); return NULL; } @@ -151,36 +159,35 @@ SYNOPSIS bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd); DESCRIPTION - bfd_fdopenr is to bfd_fopenr much like fdopen is to fopen. + <> is to <> much like <> is to <>. It opens a BFD on a file already described by the @var{fd} supplied. - When the file is later bfd_closed, the file descriptor will be closed. + When the file is later <>d, the file descriptor will be closed. If the caller desires that this file descriptor be cached by BFD (opened as needed, closed as needed to free descriptors for other opens), with the supplied @var{fd} used as an initial - file descriptor (but subject to closure at any time), set - bfd->cacheable nonzero in the returned BFD. The default is to + file descriptor (but subject to closure at any time), call + bfd_set_cacheable(bfd, 1) on the returned BFD. The default is to assume no cacheing; the file descriptor will remain open until - bfd_close, and will not be affected by BFD operations on other + <>, and will not be affected by BFD operations on other files. - Possible errors are no_memory, invalid_target and system_call - error. + Possible errors are <>, <> and <>. */ bfd * -DEFUN(bfd_fdopenr,(filename, target, fd), - CONST char *filename AND - CONST char *target AND - int fd) +bfd_fdopenr (filename, target, fd) + CONST char *filename; + CONST char *target; + int fd; { bfd *nbfd; - bfd_target *target_vec; + const bfd_target *target_vec; int fdflags; - bfd_error = system_call_error; + bfd_set_error (bfd_error_system_call); #ifdef NO_FCNTL fdflags = O_RDWR; /* Assume full access */ @@ -189,16 +196,16 @@ DEFUN(bfd_fdopenr,(filename, target, fd), #endif if (fdflags == -1) return NULL; - nbfd = new_bfd(); + nbfd = _bfd_new_bfd(); if (nbfd == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } target_vec = bfd_find_target (target, nbfd); if (target_vec == NULL) { - bfd_error = invalid_target; + bfd_set_error (bfd_error_invalid_target); return NULL; } #if defined(VMS) || defined(__GO32__) @@ -232,7 +239,8 @@ DEFUN(bfd_fdopenr,(filename, target, fd), default: abort (); } - bfd_cache_init (nbfd); + if (! bfd_cache_init (nbfd)) + return NULL; return nbfd; } @@ -250,29 +258,29 @@ SYNOPSIS bfd *bfd_openw(CONST char *filename, CONST char *target); DESCRIPTION - Creates a BFD, associated with file @var{filename}, using the - file format @var{target}, and returns a pointer to it. + Create a BFD, associated with file @var{filename}, using the + file format @var{target}, and return a pointer to it. - Possible errors are system_call_error, no_memory, - invalid_target. + Possible errors are <>, <>, + <>. */ bfd * -DEFUN(bfd_openw,(filename, target), - CONST char *filename AND - CONST char *target) +bfd_openw (filename, target) + CONST char *filename; + CONST char *target; { bfd *nbfd; - bfd_target *target_vec; + const bfd_target *target_vec; - bfd_error = system_call_error; + bfd_set_error (bfd_error_system_call); /* nbfd has to point to head of malloc'ed block so that bfd_close may reclaim it correctly. */ - nbfd = new_bfd(); + nbfd = _bfd_new_bfd(); if (nbfd == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } @@ -283,7 +291,7 @@ DEFUN(bfd_openw,(filename, target), nbfd->direction = write_direction; if (bfd_open_file (nbfd) == NULL) { - bfd_error = system_call_error; /* File not writeable, etc */ + bfd_set_error (bfd_error_system_call); /* File not writeable, etc */ (void) obstack_free (&nbfd->memory, (PTR)0); return NULL; } @@ -296,11 +304,11 @@ FUNCTION bfd_close SYNOPSIS - boolean bfd_close(bfd *); + boolean bfd_close(bfd *abfd); DESCRIPTION - This function closes a BFD. If the BFD was open for writing, + Close a BFD. If the BFD was open for writing, then pending operations are completed and the file written out and closed. If the created file is executable, then <> is called to mark it as such. @@ -308,7 +316,7 @@ DESCRIPTION All memory attached to the BFD's obstacks is released. The file descriptor associated with the BFD is closed (even - if it was passed in to BFD by bfd_fdopenr). + if it was passed in to BFD by <>). RETURNS <> is returned if all is ok, otherwise <>. @@ -316,8 +324,8 @@ RETURNS boolean -DEFUN(bfd_close,(abfd), - bfd *abfd) +bfd_close (abfd) + bfd *abfd; { boolean ret; @@ -361,7 +369,7 @@ SYNOPSIS boolean bfd_close_all_done(bfd *); DESCRIPTION - This function closes a BFD. It differs from <> + Close a BFD. Differs from <> since it does not complete any pending operations. This routine would be used if the application had just used BFD for swapping and didn't want to use any of the writing code. @@ -377,8 +385,8 @@ RETURNS */ boolean -DEFUN(bfd_close_all_done,(abfd), - bfd *abfd) +bfd_close_all_done (abfd) + bfd *abfd; { boolean ret; @@ -417,14 +425,13 @@ SYNOPSIS bfd_size_type bfd_alloc_size(bfd *abfd); DESCRIPTION - Return the number of bytes in the obstacks connected to the - supplied BFD. + Return the number of bytes in the obstacks connected to @var{abfd}. */ bfd_size_type -DEFUN(bfd_alloc_size,(abfd), - bfd *abfd) +bfd_alloc_size (abfd) + bfd *abfd; { struct _obstack_chunk *chunk = abfd->memory.chunk; size_t size = 0; @@ -445,7 +452,7 @@ SYNOPSIS bfd *bfd_create(CONST char *filename, bfd *templ); DESCRIPTION - This routine creates a new BFD in the manner of + Create a new BFD in the manner of <>, but without opening a file. The new BFD takes the target from the target used by @var{template}. The format is always set to <>. @@ -453,13 +460,13 @@ DESCRIPTION */ bfd * -DEFUN(bfd_create,(filename, templ), - CONST char *filename AND - bfd *templ) +bfd_create (filename, templ) + CONST char *filename; + bfd *templ; { - bfd *nbfd = new_bfd(); + bfd *nbfd = _bfd_new_bfd(); if (nbfd == (bfd *)NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return (bfd *)NULL; } nbfd->filename = filename; @@ -479,56 +486,63 @@ SYNOPSIS PTR bfd_alloc_by_size_t(bfd *abfd, size_t wanted); DESCRIPTION - This function allocates a block of memory in the obstack - attatched to <> and returns a pointer to it. + Allocate a block of @var{wanted} bytes of memory in the obstack + attatched to <> and return a pointer to it. */ PTR -DEFUN(bfd_alloc_by_size_t,(abfd, size), - bfd *abfd AND - size_t size) +bfd_alloc_by_size_t (abfd, size) + bfd *abfd; + size_t size; { - PTR res = obstack_alloc(&(abfd->memory), size); - return res; + return obstack_alloc(&(abfd->memory), size); } -DEFUN(void bfd_alloc_grow,(abfd, ptr, size), - bfd *abfd AND - PTR ptr AND - size_t size) +void +bfd_alloc_grow (abfd, ptr, size) + bfd *abfd; + PTR ptr; + size_t size; { (void) obstack_grow(&(abfd->memory), ptr, size); } -DEFUN(PTR bfd_alloc_finish,(abfd), - bfd *abfd) + +PTR +bfd_alloc_finish (abfd) + bfd *abfd; { return obstack_finish(&(abfd->memory)); } -DEFUN(PTR bfd_alloc, (abfd, size), - bfd *abfd AND - size_t size) +PTR +bfd_alloc (abfd, size) + bfd *abfd; + size_t size; { return bfd_alloc_by_size_t(abfd, (size_t)size); } -DEFUN(PTR bfd_zalloc,(abfd, size), - bfd *abfd AND - size_t size) +PTR +bfd_zalloc (abfd, size) + bfd *abfd; + size_t size; { PTR res; res = bfd_alloc(abfd, size); - memset(res, 0, (size_t)size); + if (res) + memset(res, 0, (size_t)size); return res; } -DEFUN(PTR bfd_realloc,(abfd, old, size), - bfd *abfd AND - PTR old AND - size_t size) +PTR +bfd_realloc (abfd, old, size) + bfd *abfd; + PTR old; + size_t size; { PTR res = bfd_alloc(abfd, size); - memcpy(res, old, (size_t)size); + if (res) + memcpy(res, old, (size_t)size); return res; } diff --git a/gnu/usr.bin/gdb/bfd/reloc.c b/gnu/usr.bin/gdb/bfd/reloc.c index f2dd5201d44b..9c65be945d5b 100644 --- a/gnu/usr.bin/gdb/bfd/reloc.c +++ b/gnu/usr.bin/gdb/bfd/reloc.c @@ -22,18 +22,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION Relocations - BFD maintains relocations in much the same was as it maintains - symbols; they are left alone until required, then read in - en-mass and traslated into an internal form. There is a common - routine <> which acts upon the - canonical form to do the actual fixup. + BFD maintains relocations in much the same way it maintains + symbols: they are left alone until required, then read in + en-mass and translated into an internal form. A common + routine <> acts upon the + canonical form to do the fixup. - Note that relocations are maintained on a per section basis, - whilst symbols are maintained on a per BFD basis. + Relocations are maintained on a per section basis, + while symbols are maintained on a per BFD basis. - All a back end has to do to fit the BFD interface is to create - as many <> as there are relocations - in a particular section, and fill in the right bits: + All that a back end has to do to fit the BFD interface is to create + a <> for each relocation + in a particular section, and fill in the right bits of the structures. @menu @* typedef arelent:: @@ -43,8 +43,8 @@ SECTION */ #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" -#include "seclet.h" /* DOCDD INODE @@ -57,7 +57,7 @@ SUBSECTION CODE_FRAGMENT . -.typedef enum bfd_reloc_status +.typedef enum bfd_reloc_status .{ . {* No errors detected *} . bfd_reloc_ok, @@ -71,10 +71,10 @@ CODE_FRAGMENT . {* Used by special functions *} . bfd_reloc_continue, . -. {* Unused *} +. {* Unsupported relocation size requested. *} . bfd_reloc_notsupported, . -. {* Unsupported relocation size requested. *} +. {* Unused *} . bfd_reloc_other, . . {* The symbol to relocate against was undefined. *} @@ -82,13 +82,14 @@ CODE_FRAGMENT . . {* The relocation was performed, but may not be ok - presently . generated only when linking i960 coff files with i960 b.out -. symbols. *} +. symbols. If this type is returned, the error_message argument +. to bfd_perform_relocation will be set. *} . bfd_reloc_dangerous . } . bfd_reloc_status_type; . . -.typedef struct reloc_cache_entry +.typedef struct reloc_cache_entry .{ . {* A pointer into the canonical table of pointers *} . struct symbol_cache_entry **sym_ptr_ptr; @@ -97,10 +98,10 @@ CODE_FRAGMENT . bfd_size_type address; . . {* addend for relocation value *} -. bfd_vma addend; +. bfd_vma addend; . . {* Pointer to how to perform the required relocation *} -. CONST struct reloc_howto_struct *howto; +. const struct reloc_howto_struct *howto; . .} arelent; @@ -109,14 +110,14 @@ CODE_FRAGMENT /* DESCRIPTION - Here is a description of each of the fields within a relent: + Here is a description of each of the fields within an <>: - o sym_ptr_ptr + o <> The symbol table pointer points to a pointer to the symbol - associated with the relocation request. This would naturally - be the pointer into the table returned by the back end's - get_symtab action. @xref{Symbols}. The symbol is referenced + associated with the relocation request. It is + the pointer into the table returned by the back end's + <> action. @xref{Symbols}. The symbol is referenced through a pointer to a pointer so that tools like the linker can fix up all the symbols of the same name by modifying only one pointer. The relocation routine looks in the symbol and @@ -124,19 +125,19 @@ DESCRIPTION value of the symbol as the initial relocation offset. If the symbol pointer is zero, then the section provided is looked up. - o address + o <
> - The address field gives the offset in bytes from the base of + The <
> field gives the offset in bytes from the base of the section data which owns the relocation record to the first byte of relocatable information. The actual data relocated - will be relative to this point - for example, a relocation + will be relative to this point; for example, a relocation type which modifies the bottom two bytes of a four byte word would not touch the first byte pointed to in a big endian world. - o addend + o <> - The addend is a value provided by the back end to be added (!) + The <> is a value provided by the back end to be added (!) to the relocation offset. Its interpretation is dependent upon the howto. For example, on the 68k the code: @@ -156,12 +157,12 @@ DESCRIPTION | rts - This could create a reloc pointing to foo, but leave the - offset in the data (something like) + This could create a reloc pointing to <>, but leave the + offset in the data, something like: |RELOCATION RECORDS FOR [.text]: -|offset type value +|offset type value |00000006 32 _foo | |00000000 4e56 fffc ; linkw fp,#-4 @@ -181,32 +182,32 @@ DESCRIPTION | jmp r1 - This should create two relocs, both pointing to _foo, and with + This should create two relocs, both pointing to <<_foo>>, and with 0x12340000 in their addend field. The data would consist of: |RELOCATION RECORDS FOR [.text]: -|offset type value +|offset type value |00000002 HVRT16 _foo+0x12340000 |00000006 LVRT16 _foo+0x12340000 - +| |00000000 5da05678 ; or.u r13,r0,0x5678 |00000004 1c4d5678 ; ld.b r2,r13,0x5678 |00000008 f400c001 ; jmp r1 The relocation routine digs out the value from the data, adds - it to the addend to get the original offset and then adds the - value of _foo. Note that all 32 bits have to be kept around + it to the addend to get the original offset, and then adds the + value of <<_foo>>. Note that all 32 bits have to be kept around somewhere, to cope with carry from bit 15 to bit 16. One further example is the sparc and the a.out format. The sparc has a similar problem to the 88k, in that some instructions don't have room for an entire offset, but on the - sparc the parts are created odd sized lumps. The designers of - the a.out format chose not to use the data within the section + sparc the parts are created in odd sized lumps. The designers of + the a.out format chose to not use the data within the section for storing part of the offset; all the offset is kept within - the reloc. Any thing in the data should be ignored. + the reloc. Anything in the data should be ignored. | save %sp,-112,%sp | sethi %hi(_foo+0x12345678),%g2 @@ -214,15 +215,15 @@ DESCRIPTION | ret | restore - Both relocs contains a pointer to foo, and the offsets would + Both relocs contain a pointer to <>, and the offsets contain junk. |RELOCATION RECORDS FOR [.text]: -|offset type value +|offset type value |00000004 HI22 _foo+0x12345678 |00000008 LO10 _foo+0x12345678 - +| |00000000 9de3bf90 ; save %sp,-112,%sp |00000004 05000000 ; sethi %hi(_foo+0),%g2 |00000008 f048a000 ; ldsb [%g2+%lo(_foo+0)],%i0 @@ -230,16 +231,16 @@ DESCRIPTION |00000010 81e80000 ; restore - o howto + o <> - The howto field can be imagined as a - relocation instruction. It is a pointer to a struct which - contains information on what to do with all the other + The <> field can be imagined as a + relocation instruction. It is a pointer to a structure which + contains information on what to do with all of the other information in the reloc record and data section. A back end would normally have a relocation instruction set and turn relocations into pointers to the correct structure on input - but it would be possible to create each howto field on demand. - + */ /* @@ -272,22 +273,25 @@ CODE_FRAGMENT */ /* -SUBSUBSECTION +SUBSUBSECTION <> The <> is a structure which contains all the - information that BFD needs to know to tie up a back end's data. + information that libbfd needs to know to tie up a back end's data. CODE_FRAGMENT .struct symbol_cache_entry; {* Forward declaration *} . -.typedef CONST struct reloc_howto_struct -.{ +.typedef unsigned char bfd_byte; +.typedef struct reloc_howto_struct reloc_howto_type; +. +.struct reloc_howto_struct +.{ . {* The type field has mainly a documetary use - the back end can -. to what it wants with it, though the normally the back end's -. external idea of what a reloc number would be would be stored -. in this field. For example, the a PC relative word relocation -. in a coff environment would have the type 023 - because that's +. do what it wants with it, though normally the back end's +. external idea of what a reloc number is stored +. in this field. For example, a PC relative word relocation +. in a coff environment has the type 023 - because that's . what the outside world calls a R_PCRWORD reloc. *} . unsigned int type; . @@ -296,16 +300,8 @@ CODE_FRAGMENT . unsigned int rightshift; . . {* The size of the item to be relocated. This is *not* a -. power-of-two measure. -. 0 : one byte -. 1 : two bytes -. 2 : four bytes -. 3 : nothing done (unless special_function is nonzero) -. 4 : eight bytes -. -2 : two bytes, result should be subtracted from the -. data instead of added -. There is currently no trivial way to extract a "number of -. bytes" from a howto pointer. *} +. power-of-two measure. To get the number of bytes operated +. on by a type of relocation, use bfd_get_reloc_size. *} . int size; . . {* The number of bits in the item to be relocated. This is used @@ -330,13 +326,14 @@ CODE_FRAGMENT . called rather than the normal function. This allows really . strange relocation methods to be accomodated (e.g., i960 callj . instructions). *} -. bfd_reloc_status_type (*special_function) +. bfd_reloc_status_type (*special_function) . PARAMS ((bfd *abfd, . arelent *reloc_entry, . struct symbol_cache_entry *symbol, . PTR data, -. asection *input_section, -. bfd *output_bfd)); +. asection *input_section, +. bfd *output_bfd, +. char **error_message)); . . {* The textual name of the relocation type. *} . char *name; @@ -345,7 +342,7 @@ CODE_FRAGMENT . relocations rather than the data - this flag signals this.*} . boolean partial_inplace; . -. {* The src_mask is used to select what parts of the read in data +. {* The src_mask selects which parts of the read in data . are to be used in the relocation sum. E.g., if this was an 8 bit . bit of data which we read and relocated, this would be . 0x000000ff. When we have relocs which have an addend, such as @@ -354,27 +351,27 @@ CODE_FRAGMENT . the mask would be 0x00000000. *} . bfd_vma src_mask; . -. {* The dst_mask is what parts of the instruction are replaced +. {* The dst_mask selects which parts of the instruction are replaced . into the instruction. In most cases src_mask == dst_mask, . except in the above special case, where dst_mask would be . 0x000000ff, and src_mask would be 0x00000000. *} -. bfd_vma dst_mask; +. bfd_vma dst_mask; . . {* When some formats create PC relative instructions, they leave . the value of the pc of the place being relocated in the offset . slot of the instruction, so that a PC relative relocation can . be made just by adding in an ordinary offset (e.g., sun3 a.out). . Some formats leave the displacement part of an instruction -. empty (e.g., m88k bcs), this flag signals the fact.*} +. empty (e.g., m88k bcs); this flag signals the fact.*} . boolean pcrel_offset; . -.} reloc_howto_type; +.}; */ /* FUNCTION - the HOWTO macro + The HOWTO Macro DESCRIPTION The HOWTO define is horrible and will go away. @@ -385,7 +382,7 @@ DESCRIPTION DESCRIPTION And will be replaced with the totally magic way. But for the - moment, we are compatible, so do it this way.. + moment, we are compatible, so do it this way. .#define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN) @@ -403,20 +400,46 @@ DESCRIPTION . relocation = symbol->value; \ . } \ . } \ -.} +.} */ +/* +FUNCTION + bfd_get_reloc_size + +SYNOPSIS + int bfd_get_reloc_size (const reloc_howto_type *); + +DESCRIPTION + For a reloc_howto_type that operates on a fixed number of bytes, + this returns the number of bytes operated on. + */ + +int +bfd_get_reloc_size (howto) + const reloc_howto_type *howto; +{ + switch (howto->size) + { + case 0: return 1; + case 1: return 2; + case 2: return 4; + case 3: return 0; + case 4: return 8; + case -2: return 4; + default: abort (); + } +} + /* TYPEDEF - reloc_chain + arelent_chain DESCRIPTION - How relocs are tied together + How relocs are tied together in an <>: -.typedef unsigned char bfd_byte; -. .typedef struct relent_chain { . arelent relent; . struct relent_chain *next; @@ -427,59 +450,59 @@ DESCRIPTION /* -FUNCTION +FUNCTION bfd_perform_relocation SYNOPSIS bfd_reloc_status_type bfd_perform_relocation - (bfd * abfd, - arelent *reloc_entry, - PTR data, - asection *input_section, - bfd *output_bfd); + (bfd *abfd, + arelent *reloc_entry, + PTR data, + asection *input_section, + bfd *output_bfd, + char **error_message); DESCRIPTION - If an output_bfd is supplied to this function the generated - image will be relocatable, the relocations are copied to the - output file after they have been changed to reflect the new - state of the world. There are two ways of reflecting the - results of partial linkage in an output file; by modifying the - output data in place, and by modifying the relocation record. - Some native formats (e.g., basic a.out and basic coff) have no - way of specifying an addend in the relocation type, so the - addend has to go in the output data. This is no big deal - since in these formats the output data slot will always be big - enough for the addend. Complex reloc types with addends were - invented to solve just this problem. + If @var{output_bfd} is supplied to this function, the + generated image will be relocatable; the relocations are + copied to the output file after they have been changed to + reflect the new state of the world. There are two ways of + reflecting the results of partial linkage in an output file: + by modifying the output data in place, and by modifying the + relocation record. Some native formats (e.g., basic a.out and + basic coff) have no way of specifying an addend in the + relocation type, so the addend has to go in the output data. + This is no big deal since in these formats the output data + slot will always be big enough for the addend. Complex reloc + types with addends were invented to solve just this problem. + The @var{error_message} argument is set to an error message if + this return @code{bfd_reloc_dangerous}. */ bfd_reloc_status_type -DEFUN(bfd_perform_relocation,(abfd, - reloc_entry, - data, - input_section, - output_bfd), - bfd *abfd AND - arelent *reloc_entry AND - PTR data AND - asection *input_section AND - bfd *output_bfd) +bfd_perform_relocation (abfd, reloc_entry, data, input_section, output_bfd, + error_message) + bfd *abfd; + arelent *reloc_entry; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; { bfd_vma relocation; bfd_reloc_status_type flag = bfd_reloc_ok; - bfd_size_type addr = reloc_entry->address ; + bfd_size_type addr = reloc_entry->address; bfd_vma output_base = 0; - reloc_howto_type *howto = reloc_entry->howto; - asection *reloc_target_output_section ; - + const reloc_howto_type *howto = reloc_entry->howto; + asection *reloc_target_output_section; asymbol *symbol; - symbol = *( reloc_entry->sym_ptr_ptr); - if ((symbol->section == &bfd_abs_section) - && output_bfd != (bfd *)NULL) + symbol = *(reloc_entry->sym_ptr_ptr); + if (bfd_is_abs_section (symbol->section) + && output_bfd != (bfd *) NULL) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; @@ -488,7 +511,7 @@ DEFUN(bfd_perform_relocation,(abfd, /* If we are not producing relocateable output, return an error if the symbol is not defined. An undefined weak symbol is considered to have a value of zero (SVR4 ABI, p. 4-27). */ - if (symbol->section == &bfd_und_section + if (bfd_is_und_section (symbol->section) && (symbol->flags & BSF_WEAK) == 0 && output_bfd == (bfd *) NULL) flag = bfd_reloc_undefined; @@ -500,7 +523,8 @@ DEFUN(bfd_perform_relocation,(abfd, { bfd_reloc_status_type cont; cont = howto->special_function (abfd, reloc_entry, symbol, data, - input_section, output_bfd); + input_section, output_bfd, + error_message); if (cont != bfd_reloc_continue) return cont; } @@ -522,7 +546,7 @@ DEFUN(bfd_perform_relocation,(abfd, reloc_target_output_section = symbol->section->output_section; /* Convert input-section-relative symbol value to absolute. */ - if (output_bfd && howto->partial_inplace==false) + if (output_bfd && howto->partial_inplace == false) output_base = 0; else output_base = reloc_target_output_section->vma; @@ -565,28 +589,28 @@ DEFUN(bfd_perform_relocation,(abfd, actually does. I don't want to change it, because it seems far too likely that something will break. */ - relocation -= + relocation -= input_section->output_section->vma + input_section->output_offset; if (howto->pcrel_offset == true) relocation -= reloc_entry->address; } - if (output_bfd!= (bfd *)NULL) + if (output_bfd != (bfd *) NULL) { - if ( howto->partial_inplace == false) + if (howto->partial_inplace == false) { /* This is a partial relocation, and we want to apply the relocation to the reloc entry rather than the raw data. Modify the reloc inplace to reflect what we now know. */ reloc_entry->addend = relocation; - reloc_entry->address += input_section->output_offset; + reloc_entry->address += input_section->output_offset; return flag; } else { /* This is a partial relocation, but inplace, so modify the - reloc record a bit. + reloc record a bit. If we've relocated with a symbol with a section, change into a ref to the section belonging to the symbol. */ @@ -594,9 +618,83 @@ DEFUN(bfd_perform_relocation,(abfd, reloc_entry->address += input_section->output_offset; /* WTF?? */ - if (abfd->xvec->flavour == bfd_target_coff_flavour) + if (abfd->xvec->flavour == bfd_target_coff_flavour + && strcmp (abfd->xvec->name, "aixcoff-rs6000") != 0 + && strcmp (abfd->xvec->name, "coff-Intel-little") != 0 + && strcmp (abfd->xvec->name, "coff-Intel-big") != 0) { +#if 1 + /* For m68k-coff, the addend was being subtracted twice during + relocation with -r. Removing the line below this comment + fixes that problem; see PR 2953. + +However, Ian wrote the following, regarding removing the line below, +which explains why it is still enabled: --djm + +If you put a patch like that into BFD you need to check all the COFF +linkers. I am fairly certain that patch will break coff-i386 (e.g., +SCO); see coff_i386_reloc in coff-i386.c where I worked around the +problem in a different way. There may very well be a reason that the +code works as it does. + +Hmmm. The first obvious point is that bfd_perform_relocation should +not have any tests that depend upon the flavour. It's seem like +entirely the wrong place for such a thing. The second obvious point +is that the current code ignores the reloc addend when producing +relocateable output for COFF. That's peculiar. In fact, I really +have no idea what the point of the line you want to remove is. + +A typical COFF reloc subtracts the old value of the symbol and adds in +the new value to the location in the object file (if it's a pc +relative reloc it adds the difference between the symbol value and the +location). When relocating we need to preserve that property. + +BFD handles this by setting the addend to the negative of the old +value of the symbol. Unfortunately it handles common symbols in a +non-standard way (it doesn't subtract the old value) but that's a +different story (we can't change it without losing backward +compatibility with old object files) (coff-i386 does subtract the old +value, to be compatible with existing coff-i386 targets, like SCO). + +So everything works fine when not producing relocateable output. When +we are producing relocateable output, logically we should do exactly +what we do when not producing relocateable output. Therefore, your +patch is correct. In fact, it should probably always just set +reloc_entry->addend to 0 for all cases, since it is, in fact, going to +add the value into the object file. This won't hurt the COFF code, +which doesn't use the addend; I'm not sure what it will do to other +formats (the thing to check for would be whether any formats both use +the addend and set partial_inplace). + +When I wanted to make coff-i386 produce relocateable output, I ran +into the problem that you are running into: I wanted to remove that +line. Rather than risk it, I made the coff-i386 relocs use a special +function; it's coff_i386_reloc in coff-i386.c. The function +specifically adds the addend field into the object file, knowing that +bfd_perform_relocation is not going to. If you remove that line, then +coff-i386.c will wind up adding the addend field in twice. It's +trivial to fix; it just needs to be done. + +The problem with removing the line is just that it may break some +working code. With BFD it's hard to be sure of anything. The right +way to deal with this is simply to build and test at least all the +supported COFF targets. It should be straightforward if time and disk +space consuming. For each target: + 1) build the linker + 2) generate some executable, and link it using -r (I would + probably use paranoia.o and link against newlib/libc.a, which + for all the supported targets would be available in + /usr/cygnus/progressive/H-host/target/lib/libc.a). + 3) make the change to reloc.c + 4) rebuild the linker + 5) repeat step 2 + 6) if the resulting object files are the same, you have at least + made it no worse + 7) if they are different you have to figure out which version is + right +*/ relocation -= reloc_entry->addend; +#endif reloc_entry->addend = 0; } else @@ -605,7 +703,7 @@ DEFUN(bfd_perform_relocation,(abfd, } } } - else + else { reloc_entry->addend = 0; } @@ -633,14 +731,14 @@ DEFUN(bfd_perform_relocation,(abfd, { /* Assumes two's complement. */ bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1; - bfd_signed_vma reloc_signed_min = ~ reloc_signed_max; + bfd_signed_vma reloc_signed_min = ~reloc_signed_max; /* The above right shift is incorrect for a signed value. Fix it up by forcing on the upper bits. */ if (howto->rightshift > howto->bitpos && (bfd_signed_vma) relocation < 0) - check |= ((bfd_vma) -1 - &~ ((bfd_vma) -1 + check |= ((bfd_vma) - 1 + & ~((bfd_vma) - 1 >> (howto->rightshift - howto->bitpos))); if ((bfd_signed_vma) check > reloc_signed_max || (bfd_signed_vma) check < reloc_signed_min) @@ -653,7 +751,7 @@ DEFUN(bfd_perform_relocation,(abfd, overflow if howto->bitsize is the number of bits in bfd_vma. */ bfd_vma reloc_unsigned_max = - (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; + (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; if ((bfd_vma) check > reloc_unsigned_max) flag = bfd_reloc_overflow; @@ -666,8 +764,8 @@ DEFUN(bfd_perform_relocation,(abfd, bfd_vma. */ bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; - if (((bfd_vma) check &~ reloc_bits) != 0 - && ((bfd_vma) check &~ reloc_bits) != (-1 &~ reloc_bits)) + if (((bfd_vma) check & ~reloc_bits) != 0 + && ((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits)) { /* The above right shift is incorrect for a signed value. See if turning on the upper bits fixes the @@ -675,10 +773,10 @@ DEFUN(bfd_perform_relocation,(abfd, if (howto->rightshift > howto->bitpos && (bfd_signed_vma) relocation < 0) { - check |= ((bfd_vma) -1 - &~ ((bfd_vma) -1 + check |= ((bfd_vma) - 1 + & ~((bfd_vma) - 1 >> (howto->rightshift - howto->bitpos))); - if (((bfd_vma) check &~ reloc_bits) != (-1 &~ reloc_bits)) + if (((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits)) flag = bfd_reloc_overflow; } else @@ -690,17 +788,41 @@ DEFUN(bfd_perform_relocation,(abfd, abort (); } } - - /* + + /* Either we are relocating all the way, or we don't want to apply the relocation to the reloc entry (probably because there isn't any room in the output format to describe addends to relocs) */ - relocation >>= howto->rightshift; + + /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler + (OSF version 1.3, compiler version 3.11). It miscompiles the + following program: + + struct str + { + unsigned int i0; + } s = { 0 }; + + int + main () + { + unsigned long x; + + x = 0x100000000; + x <<= (unsigned long) s.i0; + if (x == 0) + printf ("failed\n"); + else + printf ("succeeded (%lx)\n", x); + } + */ + + relocation >>= (bfd_vma) howto->rightshift; /* Shift everything up to where it's going to be used */ - - relocation <<= howto->bitpos; + + relocation <<= (bfd_vma) howto->bitpos; /* Wait for the day when all have the mask in them */ @@ -714,23 +836,23 @@ DEFUN(bfd_perform_relocation,(abfd, A part 1 B part 2 R result - + Do this: i i i i i o o o o o from bfd_get and S S S S S to get the size offset we want + r r r r r r r r r r to get the final value to place and D D D D D to chop to right size ----------------------- - A A A A A + A A A A A And this: ... i i i i i o o o o o from bfd_get and N N N N N get instruction ----------------------- ... B B B B B - - And then: - B B B B B - or A A A A A + + And then: + B B B B B + or A A A A A ----------------------- R R R R R R R R R R put into bfd_put */ @@ -738,65 +860,319 @@ DEFUN(bfd_perform_relocation,(abfd, #define DOIT(x) \ x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask)) - switch (howto->size) - { - case 0: - { - char x = bfd_get_8(abfd, (char *)data + addr); - DOIT(x); - bfd_put_8(abfd,x, (unsigned char *) data + addr); - } - break; + switch (howto->size) + { + case 0: + { + char x = bfd_get_8 (abfd, (char *) data + addr); + DOIT (x); + bfd_put_8 (abfd, x, (unsigned char *) data + addr); + } + break; - case 1: - if (relocation) - { - short x = bfd_get_16(abfd, (bfd_byte *)data + addr); - DOIT(x); - bfd_put_16(abfd, x, (unsigned char *)data + addr); - } - break; - case 2: - if (relocation) - { - long x = bfd_get_32 (abfd, (bfd_byte *) data + addr); - DOIT (x); - bfd_put_32 (abfd, x, (bfd_byte *)data + addr); - } - break; - case -2: - { - long x = bfd_get_32(abfd, (bfd_byte *) data + addr); - relocation = -relocation; - DOIT(x); - bfd_put_32(abfd,x, (bfd_byte *)data + addr); - } - break; + case 1: + if (relocation) + { + short x = bfd_get_16 (abfd, (bfd_byte *) data + addr); + DOIT (x); + bfd_put_16 (abfd, x, (unsigned char *) data + addr); + } + break; + case 2: + if (relocation) + { + long x = bfd_get_32 (abfd, (bfd_byte *) data + addr); + DOIT (x); + bfd_put_32 (abfd, x, (bfd_byte *) data + addr); + } + break; + case -2: + { + long x = bfd_get_32 (abfd, (bfd_byte *) data + addr); + relocation = -relocation; + DOIT (x); + bfd_put_32 (abfd, x, (bfd_byte *) data + addr); + } + break; - case 3: - /* Do nothing */ - break; + case 3: + /* Do nothing */ + break; - case 4: + case 4: #ifdef BFD64 - if (relocation) - { - bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data + addr); - DOIT (x); - bfd_put_64 (abfd, x, (bfd_byte *) data + addr); - } + if (relocation) + { + bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data + addr); + DOIT (x); + bfd_put_64 (abfd, x, (bfd_byte *) data + addr); + } #else - abort (); + abort (); #endif - break; - default: - return bfd_reloc_other; - } + break; + default: + return bfd_reloc_other; + } return flag; } +/* This relocation routine is used by some of the backend linkers. + They do not construct asymbol or arelent structures, so there is no + reason for them to use bfd_perform_relocation. Also, + bfd_perform_relocation is so hacked up it is easier to write a new + function than to try to deal with it. + This routine does a final relocation. It should not be used when + generating relocateable output. + + FIXME: This routine ignores any special_function in the HOWTO, + since the existing special_function values have been written for + bfd_perform_relocation. + + HOWTO is the reloc howto information. + INPUT_BFD is the BFD which the reloc applies to. + INPUT_SECTION is the section which the reloc applies to. + CONTENTS is the contents of the section. + ADDRESS is the address of the reloc within INPUT_SECTION. + VALUE is the value of the symbol the reloc refers to. + ADDEND is the addend of the reloc. */ + +bfd_reloc_status_type +_bfd_final_link_relocate (howto, input_bfd, input_section, contents, address, + value, addend) + const reloc_howto_type *howto; + bfd *input_bfd; + asection *input_section; + bfd_byte *contents; + bfd_vma address; + bfd_vma value; + bfd_vma addend; +{ + bfd_vma relocation; + + /* Sanity check the address. */ + if (address > input_section->_cooked_size) + return bfd_reloc_outofrange; + + /* This function assumes that we are dealing with a basic relocation + against a symbol. We want to compute the value of the symbol to + relocate to. This is just VALUE, the value of the symbol, plus + ADDEND, any addend associated with the reloc. */ + relocation = value + addend; + + /* If the relocation is PC relative, we want to set RELOCATION to + the distance between the symbol (currently in RELOCATION) and the + location we are relocating. Some targets (e.g., i386-aout) + arrange for the contents of the section to be the negative of the + offset of the location within the section; for such targets + pcrel_offset is false. Other targets (e.g., m88kbcs or ELF) + simply leave the contents of the section as zero; for such + targets pcrel_offset is true. If pcrel_offset is false we do not + need to subtract out the offset of the location within the + section (which is just ADDRESS). */ + if (howto->pc_relative) + { + relocation -= (input_section->output_section->vma + + input_section->output_offset); + if (howto->pcrel_offset) + relocation -= address; + } + + return _bfd_relocate_contents (howto, input_bfd, relocation, + contents + address); +} + +/* Relocate a given location using a given value and howto. */ + +bfd_reloc_status_type +_bfd_relocate_contents (howto, input_bfd, relocation, location) + const reloc_howto_type *howto; + bfd *input_bfd; + bfd_vma relocation; + bfd_byte *location; +{ + int size; + bfd_vma x; + boolean overflow; + + /* If the size is negative, negate RELOCATION. This isn't very + general. */ + if (howto->size < 0) + relocation = -relocation; + + /* Get the value we are going to relocate. */ + size = bfd_get_reloc_size (howto); + switch (size) + { + default: + case 0: + abort (); + case 1: + x = bfd_get_8 (input_bfd, location); + break; + case 2: + x = bfd_get_16 (input_bfd, location); + break; + case 4: + x = bfd_get_32 (input_bfd, location); + break; + case 8: +#ifdef BFD64 + x = bfd_get_64 (input_bfd, location); +#else + abort (); +#endif + break; + } + + /* Check for overflow. FIXME: We may drop bits during the addition + which we don't check for. We must either check at every single + operation, which would be tedious, or we must do the computations + in a type larger than bfd_vma, which would be inefficient. */ + overflow = false; + if (howto->complain_on_overflow != complain_overflow_dont) + { + bfd_vma check; + bfd_signed_vma signed_check; + bfd_vma add; + bfd_signed_vma signed_add; + + if (howto->rightshift == 0) + { + check = relocation; + signed_check = (bfd_signed_vma) relocation; + } + else + { + /* Drop unwanted bits from the value we are relocating to. */ + check = relocation >> howto->rightshift; + + /* If this is a signed value, the rightshift just dropped + leading 1 bits (assuming twos complement). */ + if ((bfd_signed_vma) relocation >= 0) + signed_check = check; + else + signed_check = (check + | ((bfd_vma) - 1 + & ~((bfd_vma) - 1 >> howto->rightshift))); + } + + /* Get the value from the object file. */ + add = x & howto->src_mask; + + /* Get the value from the object file with an appropriate sign. + The expression involving howto->src_mask isolates the upper + bit of src_mask. If that bit is set in the value we are + adding, it is negative, and we subtract out that number times + two. If src_mask includes the highest possible bit, then we + can not get the upper bit, but that does not matter since + signed_add needs no adjustment to become negative in that + case. */ + signed_add = add; + if ((add & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0) + signed_add -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1; + + /* Add the value from the object file, shifted so that it is a + straight number. */ + if (howto->bitpos == 0) + { + check += add; + signed_check += signed_add; + } + else + { + check += add >> howto->bitpos; + + /* For the signed case we use ADD, rather than SIGNED_ADD, + to avoid warnings from SVR4 cc. This is OK since we + explictly handle the sign bits. */ + if (signed_add >= 0) + signed_check += add >> howto->bitpos; + else + signed_check += ((add >> howto->bitpos) + | ((bfd_vma) - 1 + & ~((bfd_vma) - 1 >> howto->bitpos))); + } + + switch (howto->complain_on_overflow) + { + case complain_overflow_signed: + { + /* Assumes two's complement. */ + bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1; + bfd_signed_vma reloc_signed_min = ~reloc_signed_max; + + if (signed_check > reloc_signed_max + || signed_check < reloc_signed_min) + overflow = true; + } + break; + case complain_overflow_unsigned: + { + /* Assumes two's complement. This expression avoids + overflow if howto->bitsize is the number of bits in + bfd_vma. */ + bfd_vma reloc_unsigned_max = + (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; + + if (check > reloc_unsigned_max) + overflow = true; + } + break; + case complain_overflow_bitfield: + { + /* Assumes two's complement. This expression avoids + overflow if howto->bitsize is the number of bits in + bfd_vma. */ + bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; + + if ((check & ~reloc_bits) != 0 + && (((bfd_vma) signed_check & ~reloc_bits) + != (-1 & ~reloc_bits))) + overflow = true; + } + break; + default: + abort (); + } + } + + /* Put RELOCATION in the right bits. */ + relocation >>= (bfd_vma) howto->rightshift; + relocation <<= (bfd_vma) howto->bitpos; + + /* Add RELOCATION to the right bits of X. */ + x = ((x & ~howto->dst_mask) + | (((x & howto->src_mask) + relocation) & howto->dst_mask)); + + /* Put the relocated value back in the object file. */ + switch (size) + { + default: + case 0: + abort (); + case 1: + bfd_put_8 (input_bfd, x, location); + break; + case 2: + bfd_put_16 (input_bfd, x, location); + break; + case 4: + bfd_put_32 (input_bfd, x, location); + break; + case 8: +#ifdef BFD64 + bfd_put_64 (input_bfd, x, location); +#else + abort (); +#endif + break; + } + + return overflow ? bfd_reloc_overflow : bfd_reloc_ok; +} /* DOCDD @@ -804,7 +1180,7 @@ INODE howto manager, , typedef arelent, Relocations SECTION - The howto manager + The howto manager When an application wants to create a relocation, but doesn't know what the target machine might call it, it can find out by @@ -828,12 +1204,14 @@ DESCRIPTION CODE_FRAGMENT . -.typedef enum bfd_reloc_code_real +.typedef enum bfd_reloc_code_real .{ . {* Basic absolute relocations *} . BFD_RELOC_64, . BFD_RELOC_32, -. BFD_RELOC_16, +. BFD_RELOC_26, +. BFD_RELOC_16, +. BFD_RELOC_14, . BFD_RELOC_8, . . {* PC-relative relocations *} @@ -858,6 +1236,10 @@ CODE_FRAGMENT . {* 32-bit pc-relative, shifted right 2 bits (i.e., 30-bit . word displacement, e.g. for SPARC) *} . BFD_RELOC_32_PCREL_S2, +. {* signed 16-bit pc-relative, shifted right 2 bits (e.g. for MIPS) *} +. BFD_RELOC_16_PCREL_S2, +. {* this is used on the Alpha *} +. BFD_RELOC_23_PCREL_S2, . . {* High 22 bits of 32-bit value, placed into lower 22 bits of . target word; simple reloc. *} @@ -865,6 +1247,13 @@ CODE_FRAGMENT . {* Low 10 bits. *} . BFD_RELOC_LO10, . +. {* For systems that allocate a Global Pointer register, these are +. displacements off that register. These relocation types are +. handled specially, because the value the register will have is +. decided relatively late. *} +. BFD_RELOC_GPREL16, +. BFD_RELOC_GPREL32, +. . {* Reloc types used for i960/b.out. *} . BFD_RELOC_I960_CALLJ, . @@ -889,14 +1278,67 @@ CODE_FRAGMENT . BFD_RELOC_SPARC_BASE13, . BFD_RELOC_SPARC_BASE22, . +. {* some relocations we're using for sparc v9 +. -- subject to change *} +. BFD_RELOC_SPARC_10, +. BFD_RELOC_SPARC_11, +.#define BFD_RELOC_SPARC_64 BFD_RELOC_64 +. BFD_RELOC_SPARC_OLO10, +. BFD_RELOC_SPARC_HH22, +. BFD_RELOC_SPARC_HM10, +. BFD_RELOC_SPARC_LM22, +. BFD_RELOC_SPARC_PC_HH22, +. BFD_RELOC_SPARC_PC_HM10, +. BFD_RELOC_SPARC_PC_LM22, +. BFD_RELOC_SPARC_WDISP16, +. BFD_RELOC_SPARC_WDISP19, +. BFD_RELOC_SPARC_GLOB_JMP, +. BFD_RELOC_SPARC_LO7, +. +. {* Alpha ECOFF relocations. Some of these treat the symbol or "addend" +. in some special way. *} +. {* For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when +. writing; when reading, it will be the absolute section symbol. The +. addend is the displacement in bytes of the "lda" instruction from +. the "ldah" instruction (which is at the address of this reloc). *} +. BFD_RELOC_ALPHA_GPDISP_HI16, +. {* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as +. with GPDISP_HI16 relocs. The addend is ignored when writing the +. relocations out, and is filled in with the file's GP value on +. reading, for convenience. *} +. BFD_RELOC_ALPHA_GPDISP_LO16, +. +. {* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference; +. the assembler turns it into a LDQ instruction to load the address of +. the symbol, and then fills in a register in the real instruction. +. +. The LITERAL reloc, at the LDQ instruction, refers to the .lita +. section symbol. The addend is ignored when writing, but is filled +. in with the file's GP value on reading, for convenience, as with the +. GPDISP_LO16 reloc. +. +. The LITUSE reloc, on the instruction using the loaded address, gives +. information to the linker that it might be able to use to optimize +. away some literal section references. The symbol is ignored (read +. as the absolute section symbol), and the "addend" indicates the type +. of instruction using the register: +. 1 - "memory" fmt insn +. 2 - byte-manipulation (byte offset reg) +. 3 - jsr (target of branch) +. +. The GNU linker currently doesn't do any of this optimizing. *} +. BFD_RELOC_ALPHA_LITERAL, +. BFD_RELOC_ALPHA_LITUSE, +. +. {* The HINT relocation indicates a value that should be filled into the +. "hint" field of a jmp/jsr/ret instruction, for possible branch- +. prediction logic which may be provided on some processors. *} +. BFD_RELOC_ALPHA_HINT, . . {* Bits 27..2 of the relocation address shifted right 2 bits; . simple reloc otherwise. *} . BFD_RELOC_MIPS_JMP, . -. {* signed 16-bit pc-relative, shifted right 2 bits (e.g. for MIPS) *} -. BFD_RELOC_16_PCREL_S2, -. . {* High 16 bits of 32-bit value; simple reloc. *} . BFD_RELOC_HI16, . {* High 16 bits of 32-bit value but the low 16 bits will be sign @@ -906,106 +1348,21 @@ CODE_FRAGMENT . BFD_RELOC_HI16_S, . {* Low 16 bits. *} . BFD_RELOC_LO16, +. {* Like BFD_RELOC_HI16_S, but PC relative. *} +. BFD_RELOC_PCREL_HI16_S, +. {* Like BFD_RELOC_LO16, but PC relative. *} +. BFD_RELOC_PCREL_LO16, . -. {* 16 bit relocation relative to the global pointer. *} -. BFD_RELOC_MIPS_GPREL, +. {* relocation relative to the global pointer. *} +.#define BFD_RELOC_MIPS_GPREL BFD_RELOC_GPREL16 . -. {* These are, so far, specific to HPPA processors. I'm not sure that some -. don't duplicate other reloc types, such as BFD_RELOC_32 and _32_PCREL. -. Also, many more were in the list I got that don't fit in well in the -. model BFD uses, so I've omitted them for now. If we do make this reloc -. type get used for code that really does implement the funky reloc types, -. they'll have to be added to this list. *} -. BFD_RELOC_HPPA_32, -. BFD_RELOC_HPPA_11, -. BFD_RELOC_HPPA_14, -. BFD_RELOC_HPPA_17, +. {* Relocation against a MIPS literal section. *} +. BFD_RELOC_MIPS_LITERAL, . -. BFD_RELOC_HPPA_L21, -. BFD_RELOC_HPPA_R11, -. BFD_RELOC_HPPA_R14, -. BFD_RELOC_HPPA_R17, -. BFD_RELOC_HPPA_LS21, -. BFD_RELOC_HPPA_RS11, -. BFD_RELOC_HPPA_RS14, -. BFD_RELOC_HPPA_RS17, -. BFD_RELOC_HPPA_LD21, -. BFD_RELOC_HPPA_RD11, -. BFD_RELOC_HPPA_RD14, -. BFD_RELOC_HPPA_RD17, -. BFD_RELOC_HPPA_LR21, -. BFD_RELOC_HPPA_RR14, -. BFD_RELOC_HPPA_RR17, -. -. BFD_RELOC_HPPA_GOTOFF_11, -. BFD_RELOC_HPPA_GOTOFF_14, -. BFD_RELOC_HPPA_GOTOFF_L21, -. BFD_RELOC_HPPA_GOTOFF_R11, -. BFD_RELOC_HPPA_GOTOFF_R14, -. BFD_RELOC_HPPA_GOTOFF_LS21, -. BFD_RELOC_HPPA_GOTOFF_RS11, -. BFD_RELOC_HPPA_GOTOFF_RS14, -. BFD_RELOC_HPPA_GOTOFF_LD21, -. BFD_RELOC_HPPA_GOTOFF_RD11, -. BFD_RELOC_HPPA_GOTOFF_RD14, -. BFD_RELOC_HPPA_GOTOFF_LR21, -. BFD_RELOC_HPPA_GOTOFF_RR14, -. -. BFD_RELOC_HPPA_DLT_32, -. BFD_RELOC_HPPA_DLT_11, -. BFD_RELOC_HPPA_DLT_14, -. BFD_RELOC_HPPA_DLT_L21, -. BFD_RELOC_HPPA_DLT_R11, -. BFD_RELOC_HPPA_DLT_R14, -. -. BFD_RELOC_HPPA_ABS_CALL_11, -. BFD_RELOC_HPPA_ABS_CALL_14, -. BFD_RELOC_HPPA_ABS_CALL_17, -. BFD_RELOC_HPPA_ABS_CALL_L21, -. BFD_RELOC_HPPA_ABS_CALL_R11, -. BFD_RELOC_HPPA_ABS_CALL_R14, -. BFD_RELOC_HPPA_ABS_CALL_R17, -. BFD_RELOC_HPPA_ABS_CALL_LS21, -. BFD_RELOC_HPPA_ABS_CALL_RS11, -. BFD_RELOC_HPPA_ABS_CALL_RS14, -. BFD_RELOC_HPPA_ABS_CALL_RS17, -. BFD_RELOC_HPPA_ABS_CALL_LD21, -. BFD_RELOC_HPPA_ABS_CALL_RD11, -. BFD_RELOC_HPPA_ABS_CALL_RD14, -. BFD_RELOC_HPPA_ABS_CALL_RD17, -. BFD_RELOC_HPPA_ABS_CALL_LR21, -. BFD_RELOC_HPPA_ABS_CALL_RR14, -. BFD_RELOC_HPPA_ABS_CALL_RR17, -. -. BFD_RELOC_HPPA_PCREL_CALL_11, -. BFD_RELOC_HPPA_PCREL_CALL_12, -. BFD_RELOC_HPPA_PCREL_CALL_14, -. BFD_RELOC_HPPA_PCREL_CALL_17, -. BFD_RELOC_HPPA_PCREL_CALL_L21, -. BFD_RELOC_HPPA_PCREL_CALL_R11, -. BFD_RELOC_HPPA_PCREL_CALL_R14, -. BFD_RELOC_HPPA_PCREL_CALL_R17, -. BFD_RELOC_HPPA_PCREL_CALL_LS21, -. BFD_RELOC_HPPA_PCREL_CALL_RS11, -. BFD_RELOC_HPPA_PCREL_CALL_RS14, -. BFD_RELOC_HPPA_PCREL_CALL_RS17, -. BFD_RELOC_HPPA_PCREL_CALL_LD21, -. BFD_RELOC_HPPA_PCREL_CALL_RD11, -. BFD_RELOC_HPPA_PCREL_CALL_RD14, -. BFD_RELOC_HPPA_PCREL_CALL_RD17, -. BFD_RELOC_HPPA_PCREL_CALL_LR21, -. BFD_RELOC_HPPA_PCREL_CALL_RR14, -. BFD_RELOC_HPPA_PCREL_CALL_RR17, -. -. BFD_RELOC_HPPA_PLABEL_32, -. BFD_RELOC_HPPA_PLABEL_11, -. BFD_RELOC_HPPA_PLABEL_14, -. BFD_RELOC_HPPA_PLABEL_L21, -. BFD_RELOC_HPPA_PLABEL_R11, -. BFD_RELOC_HPPA_PLABEL_R14, -. -. BFD_RELOC_HPPA_UNWIND_ENTRY, -. BFD_RELOC_HPPA_UNWIND_ENTRIES, +. {* MIPS ELF relocations. *} +. BFD_RELOC_MIPS_GOT16, +. BFD_RELOC_MIPS_CALL16, +.#define BFD_RELOC_MIPS_GPREL32 BFD_RELOC_GPREL32 . . {* i386/elf relocations *} . BFD_RELOC_386_GOT32, @@ -1017,6 +1374,29 @@ CODE_FRAGMENT . BFD_RELOC_386_GOTOFF, . BFD_RELOC_386_GOTPC, . +. {* ns32k relocations *} +. BFD_RELOC_NS32K_IMM_8, +. BFD_RELOC_NS32K_IMM_16, +. BFD_RELOC_NS32K_IMM_32, +. BFD_RELOC_NS32K_IMM_8_PCREL, +. BFD_RELOC_NS32K_IMM_16_PCREL, +. BFD_RELOC_NS32K_IMM_32_PCREL, +. BFD_RELOC_NS32K_DISP_8, +. BFD_RELOC_NS32K_DISP_16, +. BFD_RELOC_NS32K_DISP_32, +. BFD_RELOC_NS32K_DISP_8_PCREL, +. BFD_RELOC_NS32K_DISP_16_PCREL, +. BFD_RELOC_NS32K_DISP_32_PCREL, +. +. {* PowerPC/POWER (RS/6000) relocs. *} +. {* 26 bit relative branch. Low two bits must be zero. High 24 +. bits installed in bits 6 through 29 of instruction. *} +. BFD_RELOC_PPC_B26, +. {* 26 bit absolute branch, like BFD_RELOC_PPC_B26 but absolute. *} +. BFD_RELOC_PPC_BA26, +. {* 16 bit TOC relative reference. *} +. BFD_RELOC_PPC_TOC16, +. . {* this must be the highest numeric value *} . BFD_RELOC_UNUSED . } bfd_reloc_code_real_type; @@ -1024,31 +1404,31 @@ CODE_FRAGMENT /* -SECTION +FUNCTION bfd_reloc_type_lookup SYNOPSIS - CONST struct reloc_howto_struct * + const struct reloc_howto_struct * bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code); DESCRIPTION - This routine returns a pointer to a howto struct which when - invoked, will perform the supplied relocation on data from the + Return a pointer to a howto structure which, when + invoked, will perform the relocation @var{code} on data from the architecture noted. */ -CONST struct reloc_howto_struct * -DEFUN(bfd_reloc_type_lookup,(abfd, code), - bfd *abfd AND - bfd_reloc_code_real_type code) +const struct reloc_howto_struct * +bfd_reloc_type_lookup (abfd, code) + bfd *abfd; + bfd_reloc_code_real_type code; { return BFD_SEND (abfd, reloc_type_lookup, (abfd, code)); } static reloc_howto_type bfd_howto_32 = - HOWTO(0, 00,2,32,false,0,complain_overflow_bitfield,0,"VRT32", false,0xffffffff,0xffffffff,true); +HOWTO (0, 00, 2, 32, false, 0, complain_overflow_bitfield, 0, "VRT32", false, 0xffffffff, 0xffffffff, true); /* @@ -1056,9 +1436,8 @@ INTERNAL_FUNCTION bfd_default_reloc_type_lookup SYNOPSIS - CONST struct reloc_howto_struct *bfd_default_reloc_type_lookup - (bfd *abfd AND - bfd_reloc_code_real_type code); + const struct reloc_howto_struct *bfd_default_reloc_type_lookup + (bfd *abfd, bfd_reloc_code_real_type code); DESCRIPTION Provides a default relocation lookup routine for any architecture. @@ -1066,30 +1445,31 @@ DESCRIPTION */ -CONST struct reloc_howto_struct * -DEFUN(bfd_default_reloc_type_lookup, (abfd, code), - bfd *abfd AND - bfd_reloc_code_real_type code) +const struct reloc_howto_struct * +bfd_default_reloc_type_lookup (abfd, code) + bfd *abfd; + bfd_reloc_code_real_type code; { - switch (code) + switch (code) { case BFD_RELOC_CTOR: /* The type of reloc used in a ctor, which will be as wide as the address - so either a 64, 32, or 16 bitter. */ - switch (bfd_get_arch_info (abfd)->bits_per_address) { - case 64: - BFD_FAIL(); - case 32: - return &bfd_howto_32; - case 16: - BFD_FAIL(); - default: - BFD_FAIL(); - } + switch (bfd_get_arch_info (abfd)->bits_per_address) + { + case 64: + BFD_FAIL (); + case 32: + return &bfd_howto_32; + case 16: + BFD_FAIL (); + default: + BFD_FAIL (); + } default: - BFD_FAIL(); + BFD_FAIL (); } - return (CONST struct reloc_howto_struct *)NULL; + return (const struct reloc_howto_struct *) NULL; } @@ -1101,25 +1481,26 @@ SYNOPSIS boolean bfd_generic_relax_section (bfd *abfd, asection *section, - asymbol **symbols); + struct bfd_link_info *, + boolean *); DESCRIPTION Provides default handling for relaxing for back ends which don't do relaxing -- i.e., does nothing. */ +/*ARGSUSED*/ boolean -DEFUN(bfd_generic_relax_section,(abfd, section, symbols), - bfd *abfd AND - asection *section AND - asymbol **symbols) +bfd_generic_relax_section (abfd, section, link_info, again) + bfd *abfd; + asection *section; + struct bfd_link_info *link_info; + boolean *again; { - - return false; - + *again = false; + return true; } - /* INTERNAL_FUNCTION bfd_generic_get_relocated_section_contents @@ -1127,9 +1508,11 @@ INTERNAL_FUNCTION SYNOPSIS bfd_byte * bfd_generic_get_relocated_section_contents (bfd *abfd, - struct bfd_seclet *seclet, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, bfd_byte *data, - boolean relocateable); + boolean relocateable, + asymbol **symbols); DESCRIPTION Provides default handling of relocation effort for back ends @@ -1138,88 +1521,115 @@ DESCRIPTION */ bfd_byte * -DEFUN(bfd_generic_get_relocated_section_contents,(abfd, - seclet, - data, - relocateable), - bfd *abfd AND - struct bfd_seclet *seclet AND - bfd_byte *data AND - boolean relocateable) +bfd_generic_get_relocated_section_contents (abfd, link_info, link_order, data, + relocateable, symbols) + bfd *abfd; + struct bfd_link_info *link_info; + struct bfd_link_order *link_order; + bfd_byte *data; + boolean relocateable; + asymbol **symbols; { - extern bfd_error_vector_type bfd_error_vector; - /* Get enough memory to hold the stuff */ - bfd *input_bfd = seclet->u.indirect.section->owner; - asection *input_section = seclet->u.indirect.section; + bfd *input_bfd = link_order->u.indirect.section->owner; + asection *input_section = link_order->u.indirect.section; + long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); + arelent **reloc_vector = NULL; + long reloc_count; + if (reloc_size < 0) + goto error_return; + + reloc_vector = (arelent **) malloc (reloc_size); + if (reloc_vector == NULL && reloc_size != 0) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } - size_t reloc_size = bfd_get_reloc_upper_bound(input_bfd, input_section); - arelent **reloc_vector = (arelent **) alloca(reloc_size); - /* read in the section */ - bfd_get_section_contents(input_bfd, - input_section, - data, - 0, - input_section->_raw_size); - -/* We're not relaxing the section, so just copy the size info */ + if (!bfd_get_section_contents (input_bfd, + input_section, + (PTR) data, + 0, + input_section->_raw_size)) + goto error_return; + + /* We're not relaxing the section, so just copy the size info */ input_section->_cooked_size = input_section->_raw_size; input_section->reloc_done = true; - - if (bfd_canonicalize_reloc(input_bfd, - input_section, - reloc_vector, - seclet->u.indirect.symbols) ) - { - arelent **parent; - for (parent = reloc_vector; * parent != (arelent *)NULL; - parent++) - { - bfd_reloc_status_type r= - bfd_perform_relocation(input_bfd, - *parent, - data, - input_section, - relocateable ? abfd : (bfd *) NULL); - - if (relocateable) + reloc_count = bfd_canonicalize_reloc (input_bfd, + input_section, + reloc_vector, + symbols); + if (reloc_count < 0) + goto error_return; + + if (reloc_count > 0) + { + arelent **parent; + for (parent = reloc_vector; *parent != (arelent *) NULL; + parent++) { - asection *os = input_section->output_section; + char *error_message = (char *) NULL; + bfd_reloc_status_type r = + bfd_perform_relocation (input_bfd, + *parent, + (PTR) data, + input_section, + relocateable ? abfd : (bfd *) NULL, + &error_message); - /* A partial link, so keep the relocs */ - os->orelocation[os->reloc_count] = *parent; - os->reloc_count++; + if (relocateable) + { + asection *os = input_section->output_section; + + /* A partial link, so keep the relocs */ + os->orelocation[os->reloc_count] = *parent; + os->reloc_count++; + } + + if (r != bfd_reloc_ok) + { + switch (r) + { + case bfd_reloc_undefined: + if (!((*link_info->callbacks->undefined_symbol) + (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), + input_bfd, input_section, (*parent)->address))) + goto error_return; + break; + case bfd_reloc_dangerous: + BFD_ASSERT (error_message != (char *) NULL); + if (!((*link_info->callbacks->reloc_dangerous) + (link_info, error_message, input_bfd, input_section, + (*parent)->address))) + goto error_return; + break; + case bfd_reloc_overflow: + if (!((*link_info->callbacks->reloc_overflow) + (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), + (*parent)->howto->name, (*parent)->addend, + input_bfd, input_section, (*parent)->address))) + goto error_return; + break; + case bfd_reloc_outofrange: + default: + abort (); + break; + } + + } } - - if (r != bfd_reloc_ok) - { - switch (r) - { - case bfd_reloc_undefined: - bfd_error_vector.undefined_symbol(*parent, seclet); - break; - case bfd_reloc_dangerous: - bfd_error_vector.reloc_dangerous(*parent, seclet); - break; - case bfd_reloc_outofrange: - case bfd_reloc_overflow: - bfd_error_vector.reloc_value_truncated(*parent, seclet); - break; - default: - abort(); - break; - } - - } - } - } - - + } + if (reloc_vector != NULL) + free (reloc_vector); return data; - +error_return: + if (reloc_vector != NULL) + free (reloc_vector); + return NULL; } diff --git a/gnu/usr.bin/gdb/bfd/section.c b/gnu/usr.bin/gdb/bfd/section.c index 547c69e2cb84..bfee4b90743e 100644 --- a/gnu/usr.bin/gdb/bfd/section.c +++ b/gnu/usr.bin/gdb/bfd/section.c @@ -22,13 +22,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION Sections - Sections are supported in BFD in <>. - The raw data contained within a BFD is maintained through the section abstraction. A single BFD may have any number of - sections, and keeps hold of them by pointing to the first, + sections. It keeps hold of them by pointing to the first; each one points to the next in the list. + Sections are supported in BFD in <>. + @menu @* Section Input:: @* Section Output:: @@ -39,31 +39,31 @@ SECTION INODE Section Input, Section Output, Sections, Sections SUBSECTION - Section Input + Section input When a BFD is opened for reading, the section structures are created and attached to the BFD. Each section has a name which describes the section in the - outside world - for example, <> would contain at least - three sections, called <<.text>>, <<.data>> and <<.bss>>. + outside world---for example, <> would contain at least + three sections, called <<.text>>, <<.data>> and <<.bss>>. Names need not be unique; for example a COFF file may have several - sections named .data. + sections named <<.data>>. - Sometimes a BFD will contain more than the 'natural' number of + Sometimes a BFD will contain more than the ``natural'' number of sections. A back end may attach other sections containing constructor data, or an application may add a section (using - bfd_make_section) to the sections attached to an already open - BFD. For example, the linker creates a supernumary section + <>) to the sections attached to an already open + BFD. For example, the linker creates an extra section <> for each input file's BFD to hold information about common storage. - The raw data is not necessarily read in at the same time as + The raw data is not necessarily read in when the section descriptor is created. Some targets may leave the data in place until a <> call is - made. Other back ends may read in all the data at once - For - example; an S-record file has to be read once to determine the + made. Other back ends may read in all the data at once. For + example, an S-record file has to be read once to determine the size of the data. An IEEE-695 file doesn't contain raw data in sections, but data and relocation expressions intermixed, so the data area has to be parsed to get out the data and @@ -73,31 +73,32 @@ INODE Section Output, typedef asection, Section Input, Sections SUBSECTION - Section Output + Section output To write a new object style BFD, the various sections to be written have to be created. They are attached to the BFD in - the same way as input sections, data is written to the - sections using <>. + the same way as input sections; data is written to the + sections using <>. Any program that creates or combines sections (e.g., the assembler - and linker) must use the fields <> and + and linker) must use the <> fields <> and <> to indicate the file sections to which each section must be written. (If the section is being created from scratch, <> should probably point to the section - itself, and <> should probably be zero.) + itself and <> should probably be zero.) - The data to be written comes from input sections attached to + The data to be written comes from input sections attached + (via <> pointers) to the output sections. The output section structure can be - considered a filter for the input section, the output section + considered a filter for the input section: the output section determines the vma of the output data and the name, but the input section determines the offset into the output section of the data to be written. E.g., to create a section "O", starting at 0x100, 0x123 long, - containing two subsections, "A" at offset 0x0 (ie at vma - 0x100) and "B" at offset 0x20 (ie at vma 0x120) the structures - would look like: + containing two subsections, "A" at offset 0x0 (i.e., at vma + 0x100) and "B" at offset 0x20 (i.e., at vma 0x120) the <> + structures would look like: | section name "A" | output_offset 0x00 @@ -111,23 +112,23 @@ SUBSECTION SUBSECTION - Seglets + Link orders - The data within a section is stored in a <>. These - are much like the fixups in <>. The seglet abstraction - allows the a section to grow and shrink within itself. + The data within a section is stored in a @dfn{link_order}. + These are much like the fixups in <>. The link_order + abstraction allows a section to grow and shrink within itself. - A seglet knows how big it is, and which is the next seglet and - where the raw data for it is, and also points to a list of - relocations which apply to it. + A link_order knows how big it is, and which is the next + link_order and where the raw data for it is; it also points to + a list of relocations which apply to it. - The seglet is used by the linker to perform relaxing on final - code. The application creates code which is as big as + The link_order is used by the linker to perform relaxing on + final code. The compiler creates code which is as big as necessary to make it work without relaxing, and the user can select whether to relax. Sometimes relaxing takes a lot of time. The linker runs around the relocations to see if any are attached to data which can be shrunk, if so it does it on - a seglet by seglet basis. + a link_order by link_order basis. */ @@ -144,44 +145,44 @@ typedef asection, section prototypes, Section Output, Sections SUBSECTION typedef asection - The shape of a section struct: + Here is the section structure: CODE_FRAGMENT . -.typedef struct sec +.typedef struct sec .{ -. {* The name of the section, the name isn't a copy, the pointer is +. {* The name of the section; the name isn't a copy, the pointer is . the same as that passed to bfd_make_section. *} . . CONST char *name; . -. {* Which section is it 0.nth *} +. {* Which section is it; 0..nth. *} . -. int index; +. int index; . . {* The next section in the list belonging to the BFD, or NULL. *} . . struct sec *next; . -. {* The field flags contains attributes of the section. Some of +. {* The field flags contains attributes of the section. Some . flags are read in from the object file, and some are -. synthesized from other information. *} +. synthesized from other information. *} . . flagword flags; . .#define SEC_NO_FLAGS 0x000 . -. {* Tells the OS to allocate space for this section when loaded. -. This would clear for a section containing debug information +. {* Tells the OS to allocate space for this section when loading. +. This is clear for a section containing debug information . only. *} .#define SEC_ALLOC 0x001 -. +. . {* Tells the OS to load the section from the file when loading. -. This would be clear for a .bss section *} +. This is clear for a .bss section. *} .#define SEC_LOAD 0x002 . -. {* The section contains data still to be relocated, so there will -. be some relocation information too. *} +. {* The section contains data still to be relocated, so there is +. some relocation information too. *} .#define SEC_RELOC 0x004 . .#if 0 {* Obsolete ? *} @@ -205,10 +206,10 @@ CODE_FRAGMENT . type is used by the linker to create lists of constructors and . destructors used by <>. When a back end sees a symbol . which should be used in a constructor list, it creates a new -. section for the type of name (eg <<__CTOR_LIST__>>), attaches -. the symbol to it and builds a relocation. To build the lists +. section for the type of name (e.g., <<__CTOR_LIST__>>), attaches +. the symbol to it, and builds a relocation. To build the lists . of constructors, all the linker has to do is catenate all the -. sections called <<__CTOR_LIST__>> and relocte the data +. sections called <<__CTOR_LIST__>> and relocate the data . contained within - exactly the operations it would peform on . standard data. *} .#define SEC_CONSTRUCTOR 0x100 @@ -220,25 +221,30 @@ CODE_FRAGMENT .#define SEC_CONSTRUCTOR_BSS 0x3100 . . {* The section has contents - a data section could be -. <> | <>, a debug section could be +. <> | <>; a debug section could be . <> *} .#define SEC_HAS_CONTENTS 0x200 . -. {* An instruction to the linker not to output sections -. containing this flag even if they have information which -. would normally be written. *} +. {* An instruction to the linker to not output the section +. even if it has information which would normally be written. *} .#define SEC_NEVER_LOAD 0x400 . -. {* The section is a shared library section. The linker must leave -. these completely alone, as the vma and size are used when -. the executable is loaded. *} -.#define SEC_SHARED_LIBRARY 0x800 +. {* The section is a COFF shared library section. This flag is +. only for the linker. If this type of section appears in +. the input file, the linker must copy it to the output file +. without changing the vma or size. FIXME: Although this +. was originally intended to be general, it really is COFF +. specific (and the flag was renamed to indicate this). It +. might be cleaner to have some more general mechanism to +. allow the back end to control what the linker does with +. sections. *} +.#define SEC_COFF_SHARED_LIBRARY 0x800 . . {* The section is a common section (symbols may be defined . multiple times, the value of a symbol is the amount of . space it requires, and the largest symbol value is the one . used). Most targets have exactly one of these (which we -. translate to bfd_com_section), but ECOFF has two. *} +. translate to bfd_com_section_ptr), but ECOFF has two. *} .#define SEC_IS_COMMON 0x8000 . . {* The section contains only debugging information. For @@ -247,6 +253,12 @@ CODE_FRAGMENT . discarded. *} .#define SEC_DEBUGGING 0x10000 . +. {* The contents of this section are held in memory pointed to +. by the contents field. This is checked by +. bfd_get_section_contents, and the data is retrieved from +. memory if appropriate. *} +.#define SEC_IN_MEMORY 0x20000 +. . {* End of section flags. *} . . {* The virtual memory address of the section - where it will be @@ -260,26 +272,26 @@ CODE_FRAGMENT . boolean user_set_vma; . . {* The load address of the section - where it would be in a -. rom image, really only used for writing section header +. rom image; really only used for writing section header . information. *} . . bfd_vma lma; . . {* The size of the section in bytes, as it will be output. -. contains a value even if the section has no contents (eg, the +. contains a value even if the section has no contents (e.g., the . size of <<.bss>>). This will be filled in after relocation *} . -. bfd_size_type _cooked_size; +. bfd_size_type _cooked_size; . -. {* The size on disk of the section in bytes originally. Normally this +. {* The original size on disk of the section, in bytes. Normally this . value is the same as the size, but if some relaxing has . been done, then this value will be bigger. *} . -. bfd_size_type _raw_size; +. bfd_size_type _raw_size; . . {* If this section is going to be output, then this value is the . offset into the output section of the first byte in the input -. section. Eg, if this was going to start at the 100th byte in +. section. E.g., if this was going to start at the 100th byte in . the output section, this value would be 100. *} . . bfd_vma output_offset; @@ -288,8 +300,8 @@ CODE_FRAGMENT . . struct sec *output_section; . -. {* The alignment requirement of the section, as an exponent - eg -. 3 aligns to 2^3 (or 8) *} +. {* The alignment requirement of the section, as an exponent of 2 - +. e.g., 3 aligns to 2^3 (or 8). *} . . unsigned int alignment_power; . @@ -312,8 +324,8 @@ CODE_FRAGMENT . . {* File position of section data *} . -. file_ptr filepos; -. +. file_ptr filepos; +. . {* File position of relocation info *} . . file_ptr rel_filepos; @@ -326,12 +338,14 @@ CODE_FRAGMENT . . PTR userdata; . -. struct lang_output_section *otheruserdata; +. {* If the SEC_IN_MEMORY flag is set, this points to the actual +. contents. *} +. unsigned char *contents; . . {* Attached line number information *} . . alent *lineno; -. +. . {* Number of line number records *} . . unsigned int lineno_count; @@ -341,7 +355,7 @@ CODE_FRAGMENT . . file_ptr moving_line_filepos; . -. {* what the section number is in the target world *} +. {* What the section number is in the target world *} . . int target_index; . @@ -358,35 +372,43 @@ CODE_FRAGMENT . . boolean reloc_done; . {* A symbol which points at this section only *} -. struct symbol_cache_entry *symbol; +. struct symbol_cache_entry *symbol; . struct symbol_cache_entry **symbol_ptr_ptr; . -. struct bfd_seclet *seclets_head; -. struct bfd_seclet *seclets_tail; +. struct bfd_link_order *link_order_head; +. struct bfd_link_order *link_order_tail; .} asection ; . -. . {* These sections are global, and are managed by BFD. The application . and target back end are not permitted to change the values in -. these sections. *} +. these sections. New code should use the section_ptr macros rather +. than referring directly to the const sections. The const sections +. may eventually vanish. *} .#define BFD_ABS_SECTION_NAME "*ABS*" .#define BFD_UND_SECTION_NAME "*UND*" .#define BFD_COM_SECTION_NAME "*COM*" .#define BFD_IND_SECTION_NAME "*IND*" . . {* the absolute section *} -.extern asection bfd_abs_section; +.extern const asection bfd_abs_section; +.#define bfd_abs_section_ptr ((asection *) &bfd_abs_section) +.#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr) . {* Pointer to the undefined section *} -.extern asection bfd_und_section; +.extern const asection bfd_und_section; +.#define bfd_und_section_ptr ((asection *) &bfd_und_section) +.#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr) . {* Pointer to the common section *} -.extern asection bfd_com_section; +.extern const asection bfd_com_section; +.#define bfd_com_section_ptr ((asection *) &bfd_com_section) . {* Pointer to the indirect section *} -.extern asection bfd_ind_section; +.extern const asection bfd_ind_section; +.#define bfd_ind_section_ptr ((asection *) &bfd_ind_section) +.#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr) . -.extern struct symbol_cache_entry *bfd_abs_symbol; -.extern struct symbol_cache_entry *bfd_com_symbol; -.extern struct symbol_cache_entry *bfd_und_symbol; -.extern struct symbol_cache_entry *bfd_ind_symbol; +.extern const struct symbol_cache_entry * const bfd_abs_symbol; +.extern const struct symbol_cache_entry * const bfd_com_symbol; +.extern const struct symbol_cache_entry * const bfd_und_symbol; +.extern const struct symbol_cache_entry * const bfd_ind_symbol; .#define bfd_get_section_size_before_reloc(section) \ . (section->reloc_done ? (abort(),1): (section)->_raw_size) .#define bfd_get_section_size_after_reloc(section) \ @@ -395,21 +417,24 @@ CODE_FRAGMENT /* These symbols are global, not specific to any BFD. Therefore, anything that tries to change them is broken, and should be repaired. */ -static CONST asymbol global_syms[] = { - /* the_bfd, name, value, attr, section [, udata] */ - { 0, BFD_COM_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_com_section }, - { 0, BFD_UND_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_und_section }, - { 0, BFD_ABS_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_abs_section }, - { 0, BFD_IND_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_ind_section }, +static const asymbol global_syms[] = +{ + /* the_bfd, name, value, attr, section [, udata] */ + {0, BFD_COM_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_com_section}, + {0, BFD_UND_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_und_section}, + {0, BFD_ABS_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_abs_section}, + {0, BFD_IND_SECTION_NAME, 0, BSF_SECTION_SYM, (asection *) &bfd_ind_section}, }; #define STD_SECTION(SEC, FLAGS, SYM, NAME, IDX) \ - asymbol *SYM = (asymbol *) &global_syms[IDX]; \ - asection SEC = { NAME, 0, 0, FLAGS, 0, 0, (boolean) 0, 0, 0, 0, &SEC,\ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (boolean) 0, \ - (asymbol *) &global_syms[IDX], &SYM, } + const asymbol * const SYM = (asymbol *) &global_syms[IDX]; \ + const asection SEC = \ + { NAME, 0, 0, FLAGS, 0, false, 0, 0, 0, 0, (asection *) &SEC, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (boolean) 0, \ + (asymbol *) &global_syms[IDX], (asymbol **) &SYM, } -STD_SECTION (bfd_com_section, SEC_IS_COMMON, bfd_com_symbol, BFD_COM_SECTION_NAME, 0); +STD_SECTION (bfd_com_section, SEC_IS_COMMON, bfd_com_symbol, + BFD_COM_SECTION_NAME, 0); STD_SECTION (bfd_und_section, 0, bfd_und_symbol, BFD_UND_SECTION_NAME, 1); STD_SECTION (bfd_abs_section, 0, bfd_abs_symbol, BFD_ABS_SECTION_NAME, 2); STD_SECTION (bfd_ind_section, 0, bfd_ind_symbol, BFD_IND_SECTION_NAME, 3); @@ -420,39 +445,39 @@ DOCDD INODE section prototypes, , typedef asection, Sections SUBSECTION - section prototypes + Section prototypes -These are the functions exported by the section handling part of -<. +These are the functions exported by the section handling part of BFD. */ /* -FUNCTION +FUNCTION bfd_get_section_by_name SYNOPSIS asection *bfd_get_section_by_name(bfd *abfd, CONST char *name); DESCRIPTION - Runs through the provided @var{abfd} and returns the one of the - <>s who's name matches that provided, otherwise NULL. + Run through @var{abfd} and return the one of the + <>s whose name matches @var{name}, otherwise <>. @xref{Sections}, for more information. This should only be used in special cases; the normal way to process - all sections of a given name is to use bfd_map_over_sections and - strcmp on the name (or better yet, base it on the section flags + all sections of a given name is to use <> and + <> on the name (or better yet, base it on the section flags or something else) for each section. */ asection * -DEFUN(bfd_get_section_by_name,(abfd, name), - bfd *abfd AND - CONST char *name) +bfd_get_section_by_name (abfd, name) + bfd *abfd; + CONST char *name; { asection *sect; for (sect = abfd->sections; sect != NULL; sect = sect->next) - if (!strcmp (sect->name, name)) return sect; + if (!strcmp (sect->name, name)) + return sect; return NULL; } @@ -462,36 +487,36 @@ FUNCTION bfd_make_section_old_way SYNOPSIS - asection *bfd_make_section_old_way(bfd *, CONST char *name); + asection *bfd_make_section_old_way(bfd *abfd, CONST char *name); DESCRIPTION - This function creates a new empty section called @var{name} - and attaches it to the end of the chain of sections for the - BFD supplied. An attempt to create a section with a name which - is already in use, returns its pointer without changing the + Create a new empty section called @var{name} + and attach it to the end of the chain of sections for the + BFD @var{abfd}. An attempt to create a section with a name which + is already in use returns its pointer without changing the section chain. It has the funny name since this is the way it used to be - before is was rewritten... + before it was rewritten.... Possible errors are: - o invalid_operation - + o <> - If output has already started for this BFD. - o no_memory - + o <> - If obstack alloc fails. */ asection * -DEFUN(bfd_make_section_old_way,(abfd, name), - bfd *abfd AND - CONST char * name) +bfd_make_section_old_way (abfd, name) + bfd *abfd; + CONST char *name; { - asection *sec = bfd_get_section_by_name(abfd, name); - if (sec == (asection *)NULL) + asection *sec = bfd_get_section_by_name (abfd, name); + if (sec == (asection *) NULL) { - sec = bfd_make_section(abfd, name); + sec = bfd_make_section (abfd, name); } return sec; } @@ -501,16 +526,16 @@ FUNCTION bfd_make_section_anyway SYNOPSIS - asection *bfd_make_section_anyway(bfd *, CONST char *name); + asection *bfd_make_section_anyway(bfd *abfd, CONST char *name); DESCRIPTION Create a new empty section called @var{name} and attach it to the end of the chain of sections for @var{abfd}. Create a new section even if there - is already a section with that name. + is already a section with that name. - Returns NULL and sets bfd_error on error; possible errors are: - o invalid_operation - If output has already started for @var{abfd}. - o no_memory - If obstack alloc fails. + Return <> and set <> on error; possible errors are: + o <> - If output has already started for @var{abfd}. + o <> - If obstack alloc fails. */ sec_ptr @@ -520,40 +545,45 @@ bfd_make_section_anyway (abfd, name) { asection *newsect; asection **prev = &abfd->sections; - asection * sect = abfd->sections; + asection *sect = abfd->sections; if (abfd->output_has_begun) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return NULL; } - while (sect) { - prev = §->next; - sect = sect->next; - } + while (sect) + { + prev = §->next; + sect = sect->next; + } - newsect = (asection *) bfd_zalloc(abfd, sizeof (asection)); - if (newsect == NULL) { - bfd_error = no_memory; - return NULL; - } + newsect = (asection *) bfd_zalloc (abfd, sizeof (asection)); + if (newsect == NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } newsect->name = name; newsect->index = abfd->section_count++; newsect->flags = SEC_NO_FLAGS; - newsect->userdata = 0; - newsect->next = (asection *)NULL; - newsect->relocation = (arelent *)NULL; + newsect->userdata = NULL; + newsect->contents = NULL; + newsect->next = (asection *) NULL; + newsect->relocation = (arelent *) NULL; newsect->reloc_count = 0; - newsect->line_filepos =0; + newsect->line_filepos = 0; newsect->owner = abfd; /* Create a symbol whos only job is to point to this section. This is useful for things like relocs which are relative to the base of a section. */ - newsect->symbol = bfd_make_empty_symbol(abfd); + newsect->symbol = bfd_make_empty_symbol (abfd); + if (!newsect) + return NULL; newsect->symbol->name = name; newsect->symbol->value = 0; newsect->symbol->section = newsect; @@ -561,10 +591,11 @@ bfd_make_section_anyway (abfd, name) newsect->symbol_ptr_ptr = &newsect->symbol; - if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) { - free (newsect); - return NULL; - } + if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) + { + free (newsect); + return NULL; + } *prev = newsect; return newsect; @@ -578,41 +609,43 @@ SYNOPSIS asection *bfd_make_section(bfd *, CONST char *name); DESCRIPTION - Like bfd_make_section_anyway, but return NULL (without setting - bfd_error) without changing the section chain if there is already a - section named @var{name}. If there is an error, return NULL and set - bfd_error. + Like <>, but return <> (without calling + bfd_set_error ()) without changing the section chain if there is already a + section named @var{name}. If there is an error, return <> and set + <>. */ -sec_ptr -DEFUN(bfd_make_section,(abfd, name), - bfd *abfd AND - CONST char * name) +asection * +bfd_make_section (abfd, name) + bfd *abfd; + CONST char *name; { - asection * sect = abfd->sections; + asection *sect = abfd->sections; - if (strcmp(name, BFD_ABS_SECTION_NAME) == 0) - { - return &bfd_abs_section; - } - if (strcmp(name, BFD_COM_SECTION_NAME) == 0) - { - return &bfd_com_section; - } - if (strcmp(name, BFD_UND_SECTION_NAME) == 0) - { - return &bfd_und_section; - } + if (strcmp (name, BFD_ABS_SECTION_NAME) == 0) + { + return bfd_abs_section_ptr; + } + if (strcmp (name, BFD_COM_SECTION_NAME) == 0) + { + return bfd_com_section_ptr; + } + if (strcmp (name, BFD_UND_SECTION_NAME) == 0) + { + return bfd_und_section_ptr; + } - if (strcmp(name, BFD_IND_SECTION_NAME) == 0) - { - return &bfd_ind_section; - } + if (strcmp (name, BFD_IND_SECTION_NAME) == 0) + { + return bfd_ind_section_ptr; + } - while (sect) { - if (!strcmp(sect->name, name)) return NULL; - sect = sect->next; - } + while (sect) + { + if (!strcmp (sect->name, name)) + return NULL; + sect = sect->next; + } /* The name is not already used; go ahead and make a new section. */ return bfd_make_section_anyway (abfd, name); @@ -624,25 +657,26 @@ FUNCTION bfd_set_section_flags SYNOPSIS - boolean bfd_set_section_flags(bfd *, asection *, flagword); + boolean bfd_set_section_flags(bfd *abfd, asection *sec, flagword flags); DESCRIPTION - Attempts to set the attributes of the section named in the BFD - supplied to the value. Returns true on success, false on - error. Possible error returns are: + Set the attributes of the section @var{sec} in the BFD + @var{abfd} to the value @var{flags}. Return <> on success, + <> on error. Possible error returns are: - o invalid operation - + o <> - The section cannot have one or more of the attributes requested. For example, a .bss section in <> may not have the <> field set. */ +/*ARGSUSED*/ boolean -DEFUN(bfd_set_section_flags,(abfd, section, flags), - bfd *abfd AND - sec_ptr section AND - flagword flags) +bfd_set_section_flags (abfd, section, flags) + bfd *abfd; + sec_ptr section; + flagword flags; { #if 0 /* If you try to copy a text section from an input file (where it @@ -650,10 +684,11 @@ DEFUN(bfd_set_section_flags,(abfd, section, flags), the bfd_applicable_section_flags (abfd) doesn't have the SEC_CODE set - which it doesn't, at least not for a.out. FIXME */ - if ((flags & bfd_applicable_section_flags (abfd)) != flags) { - bfd_error = invalid_operation; - return false; - } + if ((flags & bfd_applicable_section_flags (abfd)) != flags) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } #endif section->flags = flags; @@ -673,13 +708,13 @@ SYNOPSIS PTR obj); DESCRIPTION - Calls the provided function @var{func} for each section + Call the provided function @var{func} for each section attached to the BFD @var{abfd}, passing @var{obj} as an - argument. The function will be called as if by + argument. The function will be called as if by | func(abfd, the_section, obj); - This is the prefered method for iterating over sections, an + This is the prefered method for iterating over sections; an alternative would be to use a loop: | section *p; @@ -691,19 +726,19 @@ DESCRIPTION /*VARARGS2*/ void -DEFUN(bfd_map_over_sections,(abfd, operation, user_storage), - bfd *abfd AND - void (*operation) PARAMS ((bfd *abfd, asection *sect, PTR obj)) AND - PTR user_storage) +bfd_map_over_sections (abfd, operation, user_storage) + bfd *abfd; + void (*operation) PARAMS ((bfd * abfd, asection * sect, PTR obj)); + PTR user_storage; { asection *sect; int i = 0; - + for (sect = abfd->sections; sect != NULL; i++, sect = sect->next) (*operation) (abfd, sect, user_storage); - if (i != abfd->section_count) /* Debugging */ - abort(); + if (i != abfd->section_count) /* Debugging */ + abort (); } @@ -712,35 +747,36 @@ FUNCTION bfd_set_section_size SYNOPSIS - boolean bfd_set_section_size(bfd *, asection *, bfd_size_type val); + boolean bfd_set_section_size(bfd *abfd, asection *sec, bfd_size_type val); DESCRIPTION - Sets @var{section} to the size @var{val}. If the operation is - ok, then <> is returned, else <>. + Set @var{sec} to the size @var{val}. If the operation is + ok, then <> is returned, else <>. Possible error returns: - o invalid_operation - - Writing has started to the BFD, so setting the size is invalid + o <> - + Writing has started to the BFD, so setting the size is invalid. */ boolean -DEFUN(bfd_set_section_size,(abfd, ptr, val), - bfd *abfd AND - sec_ptr ptr AND - bfd_size_type val) +bfd_set_section_size (abfd, ptr, val) + bfd *abfd; + sec_ptr ptr; + bfd_size_type val; { /* Once you've started writing to any section you cannot create or change the size of any others. */ - if (abfd->output_has_begun) { - bfd_error = invalid_operation; - return false; - } + if (abfd->output_has_begun) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } ptr->_cooked_size = val; ptr->_raw_size = val; - + return true; } @@ -750,7 +786,7 @@ FUNCTION SYNOPSIS boolean bfd_set_section_contents - (bfd *abfd, + (bfd *abfd, asection *section, PTR data, file_ptr offset, @@ -761,13 +797,13 @@ DESCRIPTION Sets the contents of the section @var{section} in BFD @var{abfd} to the data starting in memory at @var{data}. The data is written to the output section starting at offset - @var{offset} for @var{count} bytes. + @var{offset} for @var{count} bytes. Normally <> is returned, else <>. Possible error returns are: - o no_contents - + o <> - The output section does not have the <> attribute, so nothing can be written to it. o and some more too @@ -784,25 +820,25 @@ DESCRIPTION : bfd_get_section_size_before_reloc (sec)) boolean -DEFUN(bfd_set_section_contents,(abfd, section, location, offset, count), - bfd *abfd AND - sec_ptr section AND - PTR location AND - file_ptr offset AND - bfd_size_type count) +bfd_set_section_contents (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; { bfd_size_type sz; - if (!bfd_get_section_flags(abfd, section) & SEC_HAS_CONTENTS) - { - bfd_error = no_contents; - return(false); - } + if (!(bfd_get_section_flags (abfd, section) & SEC_HAS_CONTENTS)) + { + bfd_set_error (bfd_error_no_contents); + return (false); + } if (offset < 0) { bad_val: - bfd_error = bad_value; + bfd_set_error (bfd_error_bad_value); return false; } sz = bfd_get_section_size_now (abfd, section); @@ -813,28 +849,28 @@ DEFUN(bfd_set_section_contents,(abfd, section, location, offset, count), switch (abfd->direction) { - case read_direction: - case no_direction: - bfd_error = invalid_operation; - return false; + case read_direction: + case no_direction: + bfd_set_error (bfd_error_invalid_operation); + return false; - case write_direction: - break; + case write_direction: + break; - case both_direction: - /* File is opened for update. `output_has_begun' some time ago when + case both_direction: + /* File is opened for update. `output_has_begun' some time ago when the file was created. Do not recompute sections sizes or alignments in _bfd_set_section_content. */ - abfd->output_has_begun = true; - break; + abfd->output_has_begun = true; + break; } if (BFD_SEND (abfd, _bfd_set_section_contents, - (abfd, section, location, offset, count))) - { - abfd->output_has_begun = true; - return true; - } + (abfd, section, location, offset, count))) + { + abfd->output_has_begun = true; + return true; + } return false; } @@ -844,56 +880,90 @@ FUNCTION bfd_get_section_contents SYNOPSIS - boolean bfd_get_section_contents + boolean bfd_get_section_contents (bfd *abfd, asection *section, PTR location, file_ptr offset, bfd_size_type count); DESCRIPTION - This function reads data from @var{section} in BFD @var{abfd} + Read data from @var{section} in BFD @var{abfd} into memory starting at @var{location}. The data is read at an offset of @var{offset} from the start of the input section, and is read for @var{count} bytes. - If the contents of a constuctor with the <> - flag set are requested, then the @var{location} is filled with - zeroes. If no errors occur, <> is returned, else + If the contents of a constructor with the <> + flag set are requested or if the section does not have the + <> flag set, then the @var{location} is filled + with zeroes. If no errors occur, <> is returned, else <>. */ boolean -DEFUN(bfd_get_section_contents,(abfd, section, location, offset, count), - bfd *abfd AND - sec_ptr section AND - PTR location AND - file_ptr offset AND - bfd_size_type count) +bfd_get_section_contents (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; { bfd_size_type sz; - if (section->flags & SEC_CONSTRUCTOR) + if (section->flags & SEC_CONSTRUCTOR) { - memset(location, 0, (unsigned)count); + memset (location, 0, (unsigned) count); return true; } if (offset < 0) { bad_val: - bfd_error = bad_value; + bfd_set_error (bfd_error_bad_value); return false; } - sz = bfd_get_section_size_now (abfd, section); - if (offset > sz - || count > sz - || offset + count > sz) + /* Even if reloc_done is true, this function reads unrelocated + contents, so we want the raw size. */ + sz = section->_raw_size; + if (offset > sz || count > sz || offset + count > sz) goto bad_val; if (count == 0) /* Don't bother. */ return true; + if ((section->flags & SEC_HAS_CONTENTS) == 0) + { + memset (location, 0, (unsigned) count); + return true; + } + + if ((section->flags & SEC_IN_MEMORY) != 0) + { + memcpy (location, section->contents + offset, count); + return true; + } + return BFD_SEND (abfd, _bfd_get_section_contents, (abfd, section, location, offset, count)); } + +/* +FUNCTION + bfd_copy_private_section_data + +SYNOPSIS + boolean bfd_copy_private_section_data(bfd *ibfd, asection *isec, bfd *obfd, asection *osec); + +DESCRIPTION + Copy private section information from @var{isec} in the BFD + @var{ibfd} to the section @var{osec} in the BFD @var{obfd}. + Return <> on success, <> on error. Possible error + returns are: + + o <> - + Not enough memory exists to create private data for @var{osec}. + +.#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \ +. BFD_SEND (ibfd, _bfd_copy_private_section_data, \ +. (ibfd, isection, obfd, osection)) +*/ diff --git a/gnu/usr.bin/gdb/bfd/srec.c b/gnu/usr.bin/gdb/bfd/srec.c index 88ba9570e34e..a52e9b280ae1 100644 --- a/gnu/usr.bin/gdb/bfd/srec.c +++ b/gnu/usr.bin/gdb/bfd/srec.c @@ -1,5 +1,5 @@ /* BFD back-end for s-record objects. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support . This file is part of BFD, the Binary File Descriptor library. @@ -26,12 +26,12 @@ DESCRIPTION Ordinary S-Records cannot hold anything but addresses and data, so that's all that we implement. - + The only interesting thing is that S-Records may come out of order and there is no header, so an initial scan is required to discover the minimum and maximum addresses used to create the vma and size of the only section we create. We - arbitrarily call this section ".text". + arbitrarily call this section ".text". When bfd_get_section_contents is called the file is read again, and this time the data is placed into a bfd_alloc'd @@ -95,7 +95,7 @@ EXAMPLE _etext $8036 _edata $8036 _end $8036 - $$ + $$ DESCRIPTION We allow symbols to be anywhere in the data stream - the module names @@ -107,11 +107,19 @@ DESCRIPTION #include "sysdep.h" #include "libbfd.h" -/* Macros for converting between hex and binary */ +static boolean srec_write_record PARAMS ((bfd *, int, bfd_vma, + const unsigned char *, + const unsigned char *)); +static boolean srec_write_header PARAMS ((bfd *)); +static boolean srec_write_symbols PARAMS ((bfd *)); + +/* Macros for converting between hex and binary. */ static CONST char digs[] = "0123456789ABCDEF"; -static char hex_value[1 + (unsigned char)~0]; +/* Table that gets filled in with numbers corresponding to hex chars. */ + +static char hex_value[256]; #define NOT_HEX 20 #define NIBBLE(x) hex_value[(unsigned char)(x)] @@ -122,40 +130,37 @@ static char hex_value[1 + (unsigned char)~0]; ch += ((x) & 0xff); #define ISHEX(x) (hex_value[(unsigned char)(x)] != NOT_HEX) - +/* Initialize by filling in the hex conversion array. */ static void -DEFUN_VOID(srec_init) +srec_init () { - unsigned int i; - static boolean inited = false; - - if (inited == false) + unsigned int i; + static boolean inited = false; + + if (inited == false) { - - inited = true; - - for (i = 0; i < sizeof (hex_value); i++) + inited = true; + + for (i = 0; i < sizeof (hex_value); i++) { - hex_value[i] = NOT_HEX; + hex_value[i] = NOT_HEX; } - - for (i = 0; i < 10; i++) + for (i = 0; i < 10; i++) { - hex_value[i + '0'] = i; - + hex_value[i + '0'] = i; } - for (i = 0; i < 6; i++) + for (i = 0; i < 6; i++) { - hex_value[i + 'a'] = i+10; - hex_value[i + 'A'] = i+10; + hex_value[i + 'a'] = i + 10; + hex_value[i + 'A'] = i + 10; } - } + } } /* The maximum number of bytes on a line is FF */ -#define MAXCHUNK 0xff +#define MAXCHUNK 0xff /* The number of bytes we fit onto a line on output */ #define CHUNK 21 @@ -164,21 +169,21 @@ DEFUN_VOID(srec_init) struct srec_data_list_struct { - unsigned char *data; - bfd_vma where; - bfd_size_type size; - struct srec_data_list_struct *next; + unsigned char *data; + bfd_vma where; + bfd_size_type size; + struct srec_data_list_struct *next; - -} ; + +}; typedef struct srec_data_list_struct srec_data_list_type; -typedef struct srec_data_struct -{ - srec_data_list_type *head; +typedef struct srec_data_struct + { + srec_data_list_type *head; unsigned int type; - + int done_symbol_read; int count; asymbol *symbols; @@ -186,67 +191,78 @@ typedef struct srec_data_struct int symbol_idx; int string_size; int string_idx; -} tdata_type; + } +tdata_type; +static boolean srec_write_section PARAMS ((bfd *, tdata_type *, + srec_data_list_type *)); +static boolean srec_write_terminator PARAMS ((bfd *, tdata_type *)); -/* +/* called once per input S-Record, used to work out vma and size of data. */ -static bfd_vma low,high; +static bfd_vma low, high; +/*ARGSUSED*/ static void -size_symbols(abfd, buf, len, val) -bfd *abfd; -char *buf; -int len; -int val; +size_symbols (abfd, buf, len, val) + bfd *abfd; + char *buf; + int len; + int val; { - abfd->symcount ++; - abfd->tdata.srec_data->string_size += len + 1; + abfd->symcount++; + abfd->tdata.srec_data->string_size += len + 1; } static void -fillup_symbols(abfd, buf, len, val) -bfd *abfd; -char *buf; -int len; -int val; +fillup_symbols (abfd, buf, len, val) + bfd *abfd; + char *buf; + int len; + int val; { if (!abfd->tdata.srec_data->done_symbol_read) - { - asymbol *p; - if (abfd->tdata.srec_data->symbols == 0) { - abfd->tdata.srec_data->symbols = (asymbol *)bfd_alloc(abfd, abfd->symcount * sizeof(asymbol)); - abfd->tdata.srec_data->strings = (char*)bfd_alloc(abfd, abfd->tdata.srec_data->string_size); - abfd->tdata.srec_data->symbol_idx = 0; - abfd->tdata.srec_data->string_idx = 0; - } + asymbol *p; + if (abfd->tdata.srec_data->symbols == 0) + { + abfd->tdata.srec_data->symbols = (asymbol *) bfd_alloc (abfd, abfd->symcount * sizeof (asymbol)); + abfd->tdata.srec_data->strings = (char *) bfd_alloc (abfd, abfd->tdata.srec_data->string_size); + if (!abfd->tdata.srec_data->symbols || !abfd->tdata.srec_data->strings) + { + bfd_set_error (bfd_error_no_memory); + abort (); /* FIXME */ + } + abfd->tdata.srec_data->symbol_idx = 0; + abfd->tdata.srec_data->string_idx = 0; + } - p = abfd->tdata.srec_data->symbols + abfd->tdata.srec_data->symbol_idx++; - p->the_bfd = abfd; - p->name = abfd->tdata.srec_data->strings + abfd->tdata.srec_data->string_idx; - memcpy((char *)(p->name), buf, len+1); - abfd->tdata.srec_data->string_idx += len + 1; - p->value = val; - p->flags = BSF_EXPORT | BSF_GLOBAL; - p->section = &bfd_abs_section; - p->udata = 0; - } + p = abfd->tdata.srec_data->symbols + abfd->tdata.srec_data->symbol_idx++; + p->the_bfd = abfd; + p->name = abfd->tdata.srec_data->strings + abfd->tdata.srec_data->string_idx; + memcpy ((char *) (p->name), buf, len + 1); + abfd->tdata.srec_data->string_idx += len + 1; + p->value = val; + p->flags = BSF_EXPORT | BSF_GLOBAL; + p->section = bfd_abs_section_ptr; + p->udata = 0; + } } +/*ARGSUSED*/ static void -DEFUN(size_srec,(abfd, section, address, raw, length), - bfd *abfd AND - asection *section AND - bfd_vma address AND - bfd_byte *raw AND - unsigned int length) +size_srec (abfd, section, address, raw, length) + bfd *abfd; + asection *section; + bfd_vma address; + bfd_byte *raw; + unsigned int length; { if (address < low) low = address; - if (address + length > high) - high = address + length -1; + if (address + length > high) + high = address + length - 1; } @@ -254,280 +270,302 @@ DEFUN(size_srec,(abfd, section, address, raw, length), called once per input S-Record, copies data from input into bfd_alloc'd area */ +/*ARGSUSED*/ static void -DEFUN(fillup,(abfd, section, address, raw, length), -bfd *abfd AND -asection *section AND -bfd_vma address AND -bfd_byte *raw AND -unsigned int length) +fillup (abfd, section, address, raw, length) + bfd *abfd; + asection *section; + bfd_vma address; + bfd_byte *raw; + unsigned int length; { - unsigned int i; - bfd_byte *dst = - (bfd_byte *)(section->used_by_bfd) + address - section->vma; - /* length -1 because we don't read in the checksum */ - for (i = 0; i < length -1 ; i++) { - *dst = HEX(raw); - dst++; - raw+=2; - } + unsigned int i; + bfd_byte *dst = + (bfd_byte *) (section->used_by_bfd) + address - section->vma; + /* length -1 because we don't read in the checksum */ + for (i = 0; i < length - 1; i++) + { + *dst = HEX (raw); + dst++; + raw += 2; + } } /* Pass over an S-Record file, calling one of the above functions on each record. */ -static int white(x) -char x; +static int +white (x) + char x; { -return (x== ' ' || x == '\t' || x == '\n' || x == '\r'); + return (x == ' ' || x == '\t' || x == '\n' || x == '\r'); } static int -skipwhite(src,abfd) -char *src; -bfd *abfd; +skipwhite (src, abfd) + char *src; + bfd *abfd; { int eof = 0; - while (white(*src) && !eof) - { - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - } + while (white (*src) && !eof) + { + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + } return eof; } static boolean -DEFUN(srec_mkobject, (abfd), - bfd *abfd) +srec_mkobject (abfd) + bfd *abfd; { - if (abfd->tdata.srec_data == 0) - { - tdata_type *tdata = (tdata_type *)bfd_alloc(abfd, sizeof(tdata_type)); - abfd->tdata.srec_data = tdata; - tdata->type = 1; - tdata->head = (srec_data_list_type *)NULL; - } + if (abfd->tdata.srec_data == 0) + { + tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type)); + if (!tdata) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + abfd->tdata.srec_data = tdata; + tdata->type = 1; + tdata->head = (srec_data_list_type *) NULL; + } return true; - + } static void -DEFUN(pass_over,(abfd, func, symbolfunc, section), - bfd *abfd AND - void (*func)() AND - void (*symbolfunc)() AND - asection *section) +pass_over (abfd, func, symbolfunc, section) + bfd *abfd; + void (*func) (); + void (*symbolfunc) (); + asection *section; { unsigned int bytes_on_line; boolean eof = false; - srec_mkobject(abfd); + srec_mkobject (abfd); /* To the front of the file */ - bfd_seek(abfd, (file_ptr)0, SEEK_SET); + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) + abort (); while (eof == false) - { - char buffer[MAXCHUNK]; - char *src = buffer; - char type; - bfd_vma address = 0; - - /* Find first 'S' or $ */ - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - switch (*src) { - default: - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - if (eof) return; - break; + char buffer[MAXCHUNK]; + char *src = buffer; + char type; + bfd_vma address = 0; - case '$': - /* Inside a symbol definition - just ignore the module name */ - while (*src != '\n' && !eof) - { - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - } - break; - - case ' ': - /* spaces - maybe just before a symbol */ - while (*src != '\n' && white(*src)) { - eof = skipwhite(src, abfd); - -{ - int val = 0; - int slen = 0; - char symbol[MAXCHUNK]; - - /* get the symbol part */ - while (!eof && !white(*src) && slen < MAXCHUNK) + /* Find first 'S' or $ */ + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + switch (*src) { - symbol[slen++] = *src; - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); + default: + if (eof) + return; + break; + + case '$': + /* Inside a symbol definition - just ignore the module name */ + while (*src != '\n' && !eof) + { + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + } + break; + + case ' ': + /* spaces - maybe just before a symbol */ + while (*src != '\n' && *src != '\r' && white (*src)) + { + eof = skipwhite (src, abfd); + + { + int val = 0; + int slen = 0; + char symbol[MAXCHUNK]; + + /* get the symbol part */ + while (!eof && !white (*src) && slen < MAXCHUNK) + { + symbol[slen++] = *src; + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + } + symbol[slen] = 0; + eof = skipwhite (src, abfd); + /* skip the $ for the hex value */ + if (*src == '$') + { + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + } + + /* Scan off the hex number */ + while (isxdigit (*src)) + { + val *= 16; + if (isdigit (*src)) + val += *src - '0'; + else if (isupper (*src)) + { + val += *src - 'A' + 10; + } + else + { + val += *src - 'a' + 10; + } + eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1); + } + symbolfunc (abfd, symbol, slen, val); + } + } + break; + case 'S': + src++; + + /* Fetch the type and the length */ + if (bfd_read (src, 1, 3, abfd) != 3) + abort (); /* FIXME */ + + type = *src++; + + if (!ISHEX (src[0]) || !ISHEX (src[1])) + break; + + bytes_on_line = HEX (src); + + if (bytes_on_line > MAXCHUNK / 2) + break; + src += 2; + + if (bfd_read (src, 1, bytes_on_line * 2, abfd) != bytes_on_line * 2) + abort (); /* FIXME */ + + switch (type) + { + case '0': + case '5': + /* Prologue - ignore */ + break; + case '3': + address = HEX (src); + src += 2; + bytes_on_line--; + + case '2': + address = HEX (src) | (address << 8); + src += 2; + bytes_on_line--; + case '1': + address = HEX (src) | (address << 8); + src += 2; + address = HEX (src) | (address << 8); + src += 2; + bytes_on_line -= 2; + func (abfd, section, address, src, bytes_on_line); + break; + default: + return; + } } - symbol[slen] = 0; - eof = skipwhite(src, abfd); - /* skip the $ for the hex value */ - if (*src == '$') - { - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - } - - /* Scan off the hex number */ - while (isxdigit(*src )) - { - val *= 16; - if (isdigit(*src)) - val += *src - '0'; - else if (isupper(*src)) { - val += *src - 'A' + 10; - } - else { - val += *src - 'a' + 10; - } - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - } - symbolfunc(abfd, symbol, slen, val); - } -} - break; - case 'S': - src++; - - /* Fetch the type and the length */ - bfd_read(src, 1, 3, abfd); - - type = *src++; - - if (!ISHEX (src[0]) || !ISHEX (src[1])) - break; - - bytes_on_line = HEX(src); - - if (bytes_on_line > MAXCHUNK/2) - break; - src+=2 ; - - bfd_read(src, 1 , bytes_on_line * 2, abfd); - - switch (type) { - case '0': - case '5': - /* Prologue - ignore */ - break; - case '3': - address = HEX(src); - src+=2; - bytes_on_line--; - - case '2': - address = HEX(src) | (address<<8) ; - src+=2; - bytes_on_line--; - case '1': - address = HEX(src) | (address<<8) ; - src+=2; - address = HEX(src) | (address<<8) ; - src+=2; - bytes_on_line-=2; - func(abfd,section, address, src, bytes_on_line); - break; - default: - return; - } } - } } -static bfd_target * -object_p(abfd) -bfd *abfd; +static const bfd_target * +object_p (abfd) + bfd *abfd; { asection *section; - /* We create one section called .text for all the contents, + /* We create one section called .text for all the contents, and allocate enough room for the entire file. */ - - section = bfd_make_section(abfd, ".text"); + + section = bfd_make_section (abfd, ".text"); section->_raw_size = 0; section->vma = 0xffffffff; low = 0xffffffff; high = 0; - pass_over(abfd, size_srec, size_symbols, section); + pass_over (abfd, size_srec, size_symbols, section); section->_raw_size = high - low; section->vma = low; section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC; if (abfd->symcount) - abfd->flags |= HAS_SYMS; + abfd->flags |= HAS_SYMS; return abfd->xvec; } -static bfd_target * -DEFUN(srec_object_p, (abfd), - bfd *abfd) +static const bfd_target * +srec_object_p (abfd) + bfd *abfd; { char b[4]; - srec_init(); - - bfd_seek(abfd, (file_ptr)0, SEEK_SET); - bfd_read(b, 1, 4, abfd); + srec_init (); - if (b[0] != 'S' || !ISHEX(b[1]) || !ISHEX(b[2]) || !ISHEX(b[3])) - return (bfd_target*) NULL; - - /* We create one section called .text for all the contents, + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 + || bfd_read (b, 1, 4, abfd) != 4) + return NULL; + + if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3])) + return (const bfd_target *) NULL; + + /* We create one section called .text for all the contents, and allocate enough room for the entire file. */ - return object_p(abfd); + return object_p (abfd); } -static bfd_target * -DEFUN(symbolsrec_object_p, (abfd), - bfd *abfd) +static const bfd_target * +symbolsrec_object_p (abfd) + bfd *abfd; { char b[4]; - srec_init(); - - bfd_seek(abfd, (file_ptr)0, SEEK_SET); - bfd_read(b, 1, 4, abfd); + srec_init (); + + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 + || bfd_read (b, 1, 4, abfd) != 4) + return NULL; if (b[0] != '$' || b[1] != '$') - return (bfd_target*) NULL; + return (const bfd_target *) NULL; - return object_p(abfd); + return object_p (abfd); } static boolean -DEFUN(srec_get_section_contents,(abfd, section, location, offset, count), - bfd *abfd AND - asection *section AND - PTR location AND - file_ptr offset AND - bfd_size_type count) +srec_get_section_contents (abfd, section, location, offset, count) + bfd *abfd; + asection *section; + PTR location; + file_ptr offset; + bfd_size_type count; { - if (section->used_by_bfd == (PTR)NULL) + if (section->used_by_bfd == (PTR) NULL) { - section->used_by_bfd = (PTR)bfd_alloc (abfd, section->_raw_size); - - pass_over(abfd, fillup, fillup_symbols, section); + section->used_by_bfd = (PTR) bfd_alloc (abfd, section->_raw_size); + if (!section->used_by_bfd) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + pass_over (abfd, fillup, fillup_symbols, section); } - (void) memcpy((PTR)location, - (PTR)((char *)(section->used_by_bfd) + offset), - count); - return true; + memcpy ((PTR) location, + (PTR) ((char *) (section->used_by_bfd) + offset), + count); + return true; } - + boolean -DEFUN(srec_set_arch_mach,(abfd, arch, machine), - bfd *abfd AND - enum bfd_architecture arch AND - unsigned long machine) +srec_set_arch_mach (abfd, arch, machine) + bfd *abfd; + enum bfd_architecture arch; + unsigned long machine; { - return bfd_default_set_arch_mach(abfd, arch, machine); + return bfd_default_set_arch_mach (abfd, arch, machine); } @@ -535,33 +573,44 @@ DEFUN(srec_set_arch_mach,(abfd, arch, machine), also remember */ static boolean -DEFUN(srec_set_section_contents,(abfd, section, location, offset, bytes_to_do), - bfd *abfd AND - sec_ptr section AND - PTR location AND - file_ptr offset AND - bfd_size_type bytes_to_do) +srec_set_section_contents (abfd, section, location, offset, bytes_to_do) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type bytes_to_do; { - tdata_type *tdata = abfd->tdata.srec_data; + tdata_type *tdata = abfd->tdata.srec_data; srec_data_list_type *entry = (srec_data_list_type *) - bfd_alloc(abfd, sizeof(srec_data_list_type)); + bfd_alloc (abfd, sizeof (srec_data_list_type)); + + if (!entry) + { + bfd_set_error (bfd_error_no_memory); + return false; + } if ((section->flags & SEC_ALLOC) - && (section->flags & SEC_LOAD)) + && (section->flags & SEC_LOAD)) { - unsigned char *data = (unsigned char *) bfd_alloc(abfd, bytes_to_do); - memcpy(data, location, bytes_to_do); + unsigned char *data = (unsigned char *) bfd_alloc (abfd, bytes_to_do); + if (!data) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + memcpy ((PTR) data, location, bytes_to_do); - if ((section->lma + offset + bytes_to_do) <= 0xffff) + if ((section->lma + offset + bytes_to_do) <= 0xffff) { } - else if ((section->lma + offset + bytes_to_do) <= 0xffffff - && tdata->type < 2) + else if ((section->lma + offset + bytes_to_do) <= 0xffffff + && tdata->type < 2) { tdata->type = 2; } - else + else { tdata->type = 3; } @@ -572,430 +621,453 @@ DEFUN(srec_set_section_contents,(abfd, section, location, offset, bytes_to_do), entry->next = tdata->head; tdata->head = entry; } - return true; + return true; } /* Write a record of type, of the supplied number of bytes. The supplied bytes and length don't have a checksum. That's worked out here */ -static -void DEFUN(srec_write_record,(abfd, type, address, data, end), - bfd *abfd AND - char type AND - bfd_vma address AND - CONST unsigned char *data AND - CONST unsigned char *end) - +static boolean +srec_write_record (abfd, type, address, data, end) + bfd *abfd; + int type; + bfd_vma address; + const unsigned char *data; + const unsigned char *end; { - char buffer[MAXCHUNK]; - - unsigned int check_sum = 0; - unsigned CONST char *src = data; - char *dst =buffer; - char *length; - + char buffer[MAXCHUNK]; - *dst++ = 'S'; - *dst++ = '0' + type; + unsigned int check_sum = 0; + CONST unsigned char *src = data; + char *dst = buffer; + char *length; - length = dst; - dst+=2; /* leave room for dst*/ - - switch (type) + + *dst++ = 'S'; + *dst++ = '0' + type; + + length = dst; + dst += 2; /* leave room for dst*/ + + switch (type) { - case 3: - case 7: - TOHEX(dst, (address >> 24), check_sum); - dst+=2; - case 8: - case 2: - TOHEX(dst, (address >> 16), check_sum); - dst+=2; - case 9: - case 1: - case 0: - TOHEX(dst, (address >> 8), check_sum); - dst+=2; - TOHEX(dst, (address), check_sum); - dst+=2; - break; + case 3: + case 7: + TOHEX (dst, (address >> 24), check_sum); + dst += 2; + case 8: + case 2: + TOHEX (dst, (address >> 16), check_sum); + dst += 2; + case 9: + case 1: + case 0: + TOHEX (dst, (address >> 8), check_sum); + dst += 2; + TOHEX (dst, (address), check_sum); + dst += 2; + break; } - for (src = data; src < end; src++) + for (src = data; src < end; src++) { - TOHEX(dst, *src, check_sum); - dst+=2; + TOHEX (dst, *src, check_sum); + dst += 2; } - /* Fill in the length */ - TOHEX(length, (dst - length)/2, check_sum); - check_sum &= 0xff; - check_sum = 255 - check_sum; - TOHEX(dst, check_sum, check_sum); - dst+=2; - - *dst ++ = '\r'; - *dst ++ = '\n'; - bfd_write((PTR)buffer, 1, dst - buffer , abfd); + /* Fill in the length */ + TOHEX (length, (dst - length) / 2, check_sum); + check_sum &= 0xff; + check_sum = 255 - check_sum; + TOHEX (dst, check_sum, check_sum); + dst += 2; + + *dst++ = '\r'; + *dst++ = '\n'; + if (bfd_write ((PTR) buffer, 1, dst - buffer, abfd) != dst - buffer) + return false; + return true; } -static void -DEFUN(srec_write_header,(abfd), - bfd *abfd) +static boolean +srec_write_header (abfd) + bfd *abfd; { - unsigned char buffer[MAXCHUNK]; - unsigned char *dst = buffer; - unsigned int i; + unsigned char buffer[MAXCHUNK]; + unsigned char *dst = buffer; + unsigned int i; - /* I'll put an arbitary 40 char limit on header size */ - for (i = 0; i < 40 && abfd->filename[i]; i++) + /* I'll put an arbitary 40 char limit on header size */ + for (i = 0; i < 40 && abfd->filename[i]; i++) { - *dst++ = abfd->filename[i]; + *dst++ = abfd->filename[i]; } - srec_write_record(abfd,0, 0, buffer, dst); + return srec_write_record (abfd, 0, 0, buffer, dst); } -static void -DEFUN(srec_write_section,(abfd, tdata, list), - bfd *abfd AND - tdata_type *tdata AND - srec_data_list_type *list) +static boolean +srec_write_section (abfd, tdata, list) + bfd *abfd; + tdata_type *tdata; + srec_data_list_type *list; { - unsigned int bytes_written = 0; - unsigned char *location = list->data; + unsigned int bytes_written = 0; + unsigned char *location = list->data; - while (bytes_written < list->size) + while (bytes_written < list->size) { - bfd_vma address; - - unsigned int bytes_this_chunk = list->size - bytes_written; + bfd_vma address; - if (bytes_this_chunk > CHUNK) + unsigned int bytes_this_chunk = list->size - bytes_written; + + if (bytes_this_chunk > CHUNK) { - bytes_this_chunk = CHUNK; + bytes_this_chunk = CHUNK; } - address = list->where + bytes_written; + address = list->where + bytes_written; - srec_write_record(abfd, - tdata->type, - address, - location, - location + bytes_this_chunk); + if (! srec_write_record (abfd, + tdata->type, + address, + location, + location + bytes_this_chunk)) + return false; - bytes_written += bytes_this_chunk; - location += bytes_this_chunk; + bytes_written += bytes_this_chunk; + location += bytes_this_chunk; } + return true; } -static void -DEFUN(srec_write_terminator,(abfd, tdata), - bfd *abfd AND - tdata_type *tdata) +static boolean +srec_write_terminator (abfd, tdata) + bfd *abfd; + tdata_type *tdata; { - unsigned char buffer[2]; - - srec_write_record(abfd, 10 - tdata->type, - abfd->start_address, buffer, buffer); + unsigned char buffer[2]; + + return srec_write_record (abfd, 10 - tdata->type, + abfd->start_address, buffer, buffer); } - -static void -srec_write_symbols(abfd) + +static boolean +srec_write_symbols (abfd) bfd *abfd; { char buffer[MAXCHUNK]; /* Dump out the symbols of a bfd */ int i; - int len = bfd_get_symcount(abfd); + int count = bfd_get_symcount (abfd); - if (len) - { - asymbol **table = bfd_get_outsymbols(abfd); - sprintf(buffer, "$$ %s\r\n", abfd->filename); - - bfd_write(buffer, strlen(buffer), 1, abfd); - - for (i = 0; i < len; i++) + if (count) { - asymbol *s = table[i]; -#if 0 - int len = strlen(s->name); + size_t len; + asymbol **table = bfd_get_outsymbols (abfd); + sprintf (buffer, "$$ %s\r\n", abfd->filename); - /* If this symbol has a .[ocs] in it, it's probably a file name + len = strlen (buffer); + if (bfd_write (buffer, len, 1, abfd) != len) + return false; + + for (i = 0; i < count; i++) + { + asymbol *s = table[i]; +#if 0 + int len = strlen (s->name); + + /* If this symbol has a .[ocs] in it, it's probably a file name and we'll output that as the module name */ - if (len > 3 && s->name[len-2] == '.') - { - int l; - sprintf(buffer, "$$ %s\r\n", s->name); - l = strlen(buffer); - bfd_write(buffer, l, 1, abfd); - } - else + if (len > 3 && s->name[len - 2] == '.') + { + int l; + sprintf (buffer, "$$ %s\r\n", s->name); + l = strlen (buffer); + if (bfd_write (buffer, l, 1, abfd) != l) + return false; + } + else #endif - if (s->flags & (BSF_GLOBAL | BSF_LOCAL) - && (s->flags & BSF_DEBUGGING) == 0 - && s->name[0] != '.' - && s->name[0] != 't') - { - /* Just dump out non debug symbols */ + if (s->flags & (BSF_GLOBAL | BSF_LOCAL) + && (s->flags & BSF_DEBUGGING) == 0 + && s->name[0] != '.' + && s->name[0] != 't') + { + /* Just dump out non debug symbols */ - int l; - char buf2[40], *p; + int l; + char buf2[40], *p; - sprintf_vma (buf2, s->value + s->section->lma); - p = buf2; - while (p[0] == '0' && p[1] != 0) - p++; - sprintf (buffer, " %s $%s\r\n", s->name, p); - l = strlen(buffer); - bfd_write(buffer, l, 1,abfd); - } + sprintf_vma (buf2, + s->value + s->section->output_section->lma + + s->section->output_offset); + p = buf2; + while (p[0] == '0' && p[1] != 0) + p++; + sprintf (buffer, " %s $%s\r\n", s->name, p); + l = strlen (buffer); + if (bfd_write (buffer, l, 1, abfd) != l) + return false; + } + } + sprintf (buffer, "$$ \r\n"); + len = strlen (buffer); + if (bfd_write (buffer, len, 1, abfd) != len) + return false; } - sprintf(buffer, "$$ \r\n"); - bfd_write(buffer, strlen(buffer), 1, abfd); - } + + return true; } static boolean -internal_srec_write_object_contents(abfd, symbols) +internal_srec_write_object_contents (abfd, symbols) bfd *abfd; int symbols; { - int bytes_written; - tdata_type *tdata = abfd->tdata.srec_data; - srec_data_list_type *list; + tdata_type *tdata = abfd->tdata.srec_data; + srec_data_list_type *list; - bytes_written = 0; - - - if (symbols) - srec_write_symbols(abfd); - - srec_write_header(abfd); - - /* Now wander though all the sections provided and output them */ - list = tdata->head; - - while (list != (srec_data_list_type*)NULL) + if (symbols) { - srec_write_section(abfd, tdata, list); - list = list->next; + if (! srec_write_symbols (abfd)) + return false; } - srec_write_terminator(abfd, tdata); - return true; + + if (! srec_write_header (abfd)) + return false; + + /* Now wander though all the sections provided and output them */ + list = tdata->head; + + while (list != (srec_data_list_type *) NULL) + { + if (! srec_write_section (abfd, tdata, list)) + return false; + list = list->next; + } + return srec_write_terminator (abfd, tdata); } static boolean -srec_write_object_contents(abfd) +srec_write_object_contents (abfd) bfd *abfd; { - return internal_srec_write_object_contents(abfd, 0); + return internal_srec_write_object_contents (abfd, 0); } static boolean -symbolsrec_write_object_contents(abfd) +symbolsrec_write_object_contents (abfd) bfd *abfd; { - return internal_srec_write_object_contents(abfd, 1); + return internal_srec_write_object_contents (abfd, 1); } -static int -DEFUN(srec_sizeof_headers,(abfd, exec), - bfd *abfd AND - boolean exec) +/*ARGSUSED*/ +static int +srec_sizeof_headers (abfd, exec) + bfd *abfd; + boolean exec; { -return 0; + return 0; } static asymbol * -DEFUN(srec_make_empty_symbol, (abfd), - bfd*abfd) +srec_make_empty_symbol (abfd) + bfd *abfd; { - asymbol *new= (asymbol *)bfd_zalloc (abfd, sizeof (asymbol)); - new->the_bfd = abfd; + asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol)); + if (new) + new->the_bfd = abfd; return new; } -static unsigned int -srec_get_symtab_upper_bound(abfd) -bfd *abfd; +static long +srec_get_symtab_upper_bound (abfd) + bfd *abfd; { /* Read in all the info */ - srec_get_section_contents(abfd,abfd->sections,0,0,0); - return (bfd_get_symcount(abfd) + 1) * (sizeof(asymbol *)); + if (! srec_get_section_contents (abfd, abfd->sections, 0, 0, 0)) + return -1; + return (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol *)); } -static unsigned int -DEFUN(srec_get_symtab, (abfd, alocation), - bfd *abfd AND - asymbol **alocation) +static long +srec_get_symtab (abfd, alocation) + bfd *abfd; + asymbol **alocation; { int lim = abfd->symcount; int i; - for (i = 0; i < lim; i++) { - alocation[i] = abfd->tdata.srec_data->symbols + i; - } + for (i = 0; i < lim; i++) + { + alocation[i] = abfd->tdata.srec_data->symbols + i; + } alocation[i] = 0; return lim; } -void -DEFUN(srec_get_symbol_info,(ignore_abfd, symbol, ret), - bfd *ignore_abfd AND - asymbol *symbol AND - symbol_info *ret) +/*ARGSUSED*/ +void +srec_get_symbol_info (ignore_abfd, symbol, ret) + bfd *ignore_abfd; + asymbol *symbol; + symbol_info *ret; { bfd_symbol_info (symbol, ret); } -void -DEFUN(srec_print_symbol,(ignore_abfd, afile, symbol, how), - bfd *ignore_abfd AND - PTR afile AND - asymbol *symbol AND - bfd_print_symbol_type how) +/*ARGSUSED*/ +void +srec_print_symbol (ignore_abfd, afile, symbol, how) + bfd *ignore_abfd; + PTR afile; + asymbol *symbol; + bfd_print_symbol_type how; { - FILE *file = (FILE *)afile; - switch (how) - { - case bfd_print_symbol_name: - fprintf (file, "%s", symbol->name); - break; - default: - bfd_print_symbol_vandf ((PTR) file, symbol); - fprintf (file, " %-5s %s", - symbol->section->name, - symbol->name); + FILE *file = (FILE *) afile; + switch (how) + { + case bfd_print_symbol_name: + fprintf (file, "%s", symbol->name); + break; + default: + bfd_print_symbol_vandf ((PTR) file, symbol); + fprintf (file, " %-5s %s", + symbol->section->name, + symbol->name); - } + } } -#define FOO PROTO -#define srec_new_section_hook (FOO(boolean, (*), (bfd *, asection *)))bfd_true +#define srec_close_and_cleanup _bfd_generic_close_and_cleanup +#define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info +#define srec_new_section_hook _bfd_generic_new_section_hook -#define srec_get_reloc_upper_bound (FOO(unsigned int, (*),(bfd*, asection *)))bfd_false -#define srec_canonicalize_reloc (FOO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0 +#define srec_bfd_is_local_label bfd_generic_is_local_label +#define srec_get_lineno _bfd_nosymbols_get_lineno +#define srec_find_nearest_line _bfd_nosymbols_find_nearest_line +#define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol - - -#define srec_openr_next_archived_file (FOO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr -#define srec_find_nearest_line (FOO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false -#define srec_generic_stat_arch_elt (FOO(int, (*), (bfd *,struct stat *))) bfd_0 - - -#define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr) -#define srec_core_file_failing_signal (int (*)())bfd_0 -#define srec_core_file_matches_executable_p (FOO(boolean, (*),(bfd*, bfd*)))bfd_false -#define srec_slurp_armap bfd_true -#define srec_slurp_extended_name_table bfd_true -#define srec_truncate_arname (void (*)())bfd_nullvoidptr -#define srec_write_armap (FOO( boolean, (*),(bfd *, unsigned int, struct orl *, unsigned int, int))) bfd_nullvoidptr -#define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr -#define srec_close_and_cleanup bfd_generic_close_and_cleanup -#define srec_bfd_debug_info_start bfd_void -#define srec_bfd_debug_info_end bfd_void -#define srec_bfd_debug_info_accumulate (FOO(void, (*), (bfd *, asection *))) bfd_void -#define srec_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents +#define srec_bfd_get_relocated_section_contents \ + bfd_generic_get_relocated_section_contents #define srec_bfd_relax_section bfd_generic_relax_section -#define srec_bfd_seclet_link bfd_generic_seclet_link -#define srec_bfd_reloc_type_lookup \ - ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) -#define srec_bfd_make_debug_symbol \ - ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +#define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create +#define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols +#define srec_bfd_final_link _bfd_generic_final_link -bfd_target srec_vec = +const bfd_target srec_vec = { - "srec", /* name */ - bfd_target_srec_flavour, - true, /* target byte order */ - true, /* target headers byte order */ - (HAS_RELOC | EXEC_P | /* object flags */ - HAS_LINENO | HAS_DEBUG | - HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), - (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS - |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ - 0, /* leading underscore */ - ' ', /* ar_pad_char */ - 16, /* ar_max_namelen */ - 1, /* minimum alignment */ - bfd_getb64, bfd_getb_signed_64, bfd_putb64, - bfd_getb32, bfd_getb_signed_32, bfd_putb32, - bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ - bfd_getb64, bfd_getb_signed_64, bfd_putb64, - bfd_getb32, bfd_getb_signed_32, bfd_putb32, - bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ + "srec", /* name */ + bfd_target_srec_flavour, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS + | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* leading underscore */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 1, /* minimum alignment */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ { - _bfd_dummy_target, - srec_object_p, /* bfd_check_format */ - (struct bfd_target *(*)()) bfd_nullvoidptr, - (struct bfd_target *(*)()) bfd_nullvoidptr, + _bfd_dummy_target, + srec_object_p, /* bfd_check_format */ + _bfd_dummy_target, + _bfd_dummy_target, }, { - bfd_false, - srec_mkobject, - _bfd_generic_mkarchive, - bfd_false, + bfd_false, + srec_mkobject, + _bfd_generic_mkarchive, + bfd_false, }, { /* bfd_write_contents */ - bfd_false, - srec_write_object_contents, - _bfd_write_archive_contents, - bfd_false, + bfd_false, + srec_write_object_contents, + _bfd_write_archive_contents, + bfd_false, }, - JUMP_TABLE(srec) - }; + + BFD_JUMP_TABLE_GENERIC (srec), + BFD_JUMP_TABLE_COPY (_bfd_generic), + BFD_JUMP_TABLE_CORE (_bfd_nocore), + BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), + BFD_JUMP_TABLE_SYMBOLS (srec), + BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), + BFD_JUMP_TABLE_WRITE (srec), + BFD_JUMP_TABLE_LINK (srec), + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + + (PTR) 0 +}; -bfd_target symbolsrec_vec = +const bfd_target symbolsrec_vec = { - "symbolsrec", /* name */ - bfd_target_srec_flavour, - true, /* target byte order */ - true, /* target headers byte order */ - (HAS_RELOC | EXEC_P | /* object flags */ - HAS_LINENO | HAS_DEBUG | - HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), - (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS - |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ - 0, /* leading underscore */ - ' ', /* ar_pad_char */ - 16, /* ar_max_namelen */ - 1, /* minimum alignment */ - bfd_getb64, bfd_getb_signed_64, bfd_putb64, - bfd_getb32, bfd_getb_signed_32, bfd_putb32, - bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ - bfd_getb64, bfd_getb_signed_64, bfd_putb64, - bfd_getb32, bfd_getb_signed_32, bfd_putb32, - bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ + "symbolsrec", /* name */ + bfd_target_srec_flavour, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS + | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* leading underscore */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 1, /* minimum alignment */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ { - _bfd_dummy_target, - symbolsrec_object_p, /* bfd_check_format */ - (struct bfd_target *(*)()) bfd_nullvoidptr, - (struct bfd_target *(*)()) bfd_nullvoidptr, + _bfd_dummy_target, + symbolsrec_object_p, /* bfd_check_format */ + _bfd_dummy_target, + _bfd_dummy_target, }, { - bfd_false, - srec_mkobject, - _bfd_generic_mkarchive, - bfd_false, + bfd_false, + srec_mkobject, + _bfd_generic_mkarchive, + bfd_false, }, { /* bfd_write_contents */ - bfd_false, - symbolsrec_write_object_contents, - _bfd_write_archive_contents, - bfd_false, + bfd_false, + symbolsrec_write_object_contents, + _bfd_write_archive_contents, + bfd_false, }, - JUMP_TABLE(srec), - (PTR) 0 - }; + BFD_JUMP_TABLE_GENERIC (srec), + BFD_JUMP_TABLE_COPY (_bfd_generic), + BFD_JUMP_TABLE_CORE (_bfd_nocore), + BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), + BFD_JUMP_TABLE_SYMBOLS (srec), + BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), + BFD_JUMP_TABLE_WRITE (srec), + BFD_JUMP_TABLE_LINK (srec), + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + + (PTR) 0 +}; diff --git a/gnu/usr.bin/gdb/bfd/stab-syms.c b/gnu/usr.bin/gdb/bfd/stab-syms.c index 88cf8506e47d..4cc9332784a2 100644 --- a/gnu/usr.bin/gdb/bfd/stab-syms.c +++ b/gnu/usr.bin/gdb/bfd/stab-syms.c @@ -1,5 +1,5 @@ /* Table of stab names for the BFD library. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" -#define ARCH_SIZE 32 /* Value doesn't matter. */ +#define ARCH_SIZE 32 /* Value doesn't matter. */ #include "libaout.h" #include "aout/aout64.h" @@ -28,30 +28,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define __define_name(CODE, STRING) {(int)CODE, STRING}, #define __define_stab(NAME, CODE, STRING) __define_name(CODE, STRING) -CONST struct {short code; char string[10];} aout_stab_names[] - = { +CONST struct + { + short code; + char string[10]; + } +aout_stab_names[] = +{ #include "aout/stab.def" /* These are not really stab symbols, but it is convenient to have them here for the sake of nm. For completeness, we could also add N_TEXT etc, but those are never needed, since nm treats those specially. */ -__define_name (N_SETA, "SETA") /* Absolute set element symbol */ -__define_name (N_SETT, "SETT") /* Text set element symbol */ -__define_name (N_SETD, "SETD") /* Data set element symbol */ -__define_name (N_SETB, "SETB") /* Bss set element symbol */ -__define_name (N_SETV, "SETV") /* Pointer to set vector in data area. */ -__define_name (N_INDR, "INDR") -__define_name (N_WARNING, "WARNING") - }; + __define_name (N_SETA, "SETA")/* Absolute set element symbol */ + __define_name (N_SETT, "SETT")/* Text set element symbol */ + __define_name (N_SETD, "SETD")/* Data set element symbol */ + __define_name (N_SETB, "SETB")/* Bss set element symbol */ + __define_name (N_SETV, "SETV")/* Pointer to set vector in data area. */ + __define_name (N_INDR, "INDR") + __define_name (N_WARNING, "WARNING") +}; #undef __define_stab #undef GNU_EXTRA_STABS CONST char * -DEFUN(aout_stab_name,(code), -int code) +aout_stab_name (code) + int code; { - register int i = sizeof(aout_stab_names) / sizeof(aout_stab_names[0]); + register int i = sizeof (aout_stab_names) / sizeof (aout_stab_names[0]); while (--i >= 0) if (aout_stab_names[i].code == code) return aout_stab_names[i].string; diff --git a/gnu/usr.bin/gdb/bfd/syms.c b/gnu/usr.bin/gdb/bfd/syms.c index 89ac00124e3c..23a70f5e3ea9 100644 --- a/gnu/usr.bin/gdb/bfd/syms.c +++ b/gnu/usr.bin/gdb/bfd/syms.c @@ -22,20 +22,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ SECTION Symbols - BFD trys to maintain as much symbol information as it can when + BFD tries to maintain as much symbol information as it can when it moves information from file to file. BFD passes information to applications though the <> structure. When the application requests the symbol table, BFD reads the table in the native form and translates parts of it into the internal - format. To maintain more than the infomation passed to - applications some targets keep some information `behind the - scenes', in a structure only the particular back end knows + format. To maintain more than the information passed to + applications, some targets keep some information ``behind the + scenes'' in a structure only the particular back end knows about. For example, the coff back end keeps the original symbol table structure as well as the canonical structure when a BFD is read in. On output, the coff back end can reconstruct the output symbol table so that no information is lost, even information unique to coff which BFD doesn't know or - understand. If a coff symbol table was read, but was written + understand. If a coff symbol table were read, but were written through an a.out back end, all the coff specific information would be lost. The symbol table of a BFD is not necessarily read in until a canonicalize request is @@ -43,8 +43,8 @@ SECTION application with pointers to the canonical information. To output symbols, the application provides BFD with a table of pointers to pointers to <>s. This allows applications - like the linker to output a symbol as read, since the `behind - the scenes' information will be still available. + like the linker to output a symbol as it was read, since the ``behind + the scenes'' information will be still available. @menu @* Reading Symbols:: @* Writing Symbols:: @@ -55,57 +55,63 @@ SECTION INODE Reading Symbols, Writing Symbols, Symbols, Symbols SUBSECTION - Reading Symbols + Reading symbols - There are two stages to reading a symbol table from a BFD; + There are two stages to reading a symbol table from a BFD: allocating storage, and the actual reading process. This is an - excerpt from an appliction which reads the symbol table: + excerpt from an application which reads the symbol table: -| unsigned int storage_needed; +| long storage_needed; | asymbol **symbol_table; -| unsigned int number_of_symbols; -| unsigned int i; -| -| storage_needed = get_symtab_upper_bound (abfd); -| +| long number_of_symbols; +| long i; +| +| storage_needed = bfd_get_symtab_upper_bound (abfd); +| +| if (storage_needed < 0) +| FAIL +| | if (storage_needed == 0) { | return ; | } -| symbol_table = (asymbol **) bfd_xmalloc (storage_needed); +| symbol_table = (asymbol **) xmalloc (storage_needed); | ... -| number_of_symbols = -| bfd_canonicalize_symtab (abfd, symbol_table); -| +| number_of_symbols = +| bfd_canonicalize_symtab (abfd, symbol_table); +| +| if (number_of_symbols < 0) +| FAIL +| | for (i = 0; i < number_of_symbols; i++) { | process_symbol (symbol_table[i]); | } All storage for the symbols themselves is in an obstack - connected to the BFD, and is freed when the BFD is closed. + connected to the BFD; it is freed when the BFD is closed. INODE Writing Symbols, typedef asymbol, Reading Symbols, Symbols SUBSECTION - Writing Symbols + Writing symbols Writing of a symbol table is automatic when a BFD open for writing is closed. The application attaches a vector of pointers to pointers to symbols to the BFD being written, and fills in the symbol count. The close and cleanup code reads through the table provided and performs all the necessary - operations. The outputing code must always be provided with an - 'owned' symbol; one which has come from another BFD, or one - which has been created using <>. An + operations. The BFD output code must always be provided with an + ``owned'' symbol: one which has come from another BFD, or one + which has been created using <>. Here is an example showing the creation of a symbol table with only one element: | #include "bfd.h" -| main() +| main() | { | bfd *abfd; | asymbol *ptrs[2]; | asymbol *new; -| +| | abfd = bfd_openw("foo","a.out-sunos-big"); | bfd_set_format(abfd, bfd_object); | new = bfd_make_empty_symbol(abfd); @@ -113,23 +119,23 @@ SUBSECTION | new->section = bfd_make_section_old_way(abfd, ".text"); | new->flags = BSF_GLOBAL; | new->value = 0x12345; -| +| | ptrs[0] = new; | ptrs[1] = (asymbol *)0; -| +| | bfd_set_symtab(abfd, ptrs, 1); | bfd_close(abfd); | } -| -| ./makesym +| +| ./makesym | nm foo | 00012345 A dummy_symbol Many formats cannot represent arbitary symbol information; for - instance the <> object format does not allow an + instance, the <> object format does not allow an arbitary number of sections. A symbol pointing to a section which is not one of <<.text>>, <<.data>> or <<.bss>> cannot - be described. + be described. */ @@ -153,7 +159,7 @@ SUBSECTION CODE_FRAGMENT . -.typedef struct symbol_cache_entry +.typedef struct symbol_cache_entry .{ . {* A pointer to the BFD which owns the symbol. This information . is necessary so that a back end can work out what additional @@ -167,7 +173,7 @@ CODE_FRAGMENT . . struct _bfd *the_bfd; {* Use bfd_asymbol_bfd(sym) to access this field. *} . -. {* The text of the symbol. The name is left alone, and not copied - the +. {* The text of the symbol. The name is left alone, and not copied; the . application may not alter it. *} . CONST char *name; . @@ -188,7 +194,7 @@ CODE_FRAGMENT . value is the offset into the section of the data. *} .#define BSF_GLOBAL 0x02 . -. {* The symbol has global scope, and is exported. The value is +. {* The symbol has global scope and is exported. The value is . the offset into the section of the data. *} .#define BSF_EXPORT BSF_GLOBAL {* no real difference *} . @@ -249,9 +255,12 @@ CODE_FRAGMENT . for ELF STT_FILE symbols. *} .#define BSF_FILE 0x4000 . +. {* Symbol is from dynamic linking information. *} +.#define BSF_DYNAMIC 0x8000 +. . flagword flags; . -. {* A pointer to the section to which this symbol is +. {* A pointer to the section to which this symbol is . relative. This will always be non NULL, there are special . sections for undefined and absolute symbols *} . struct sec *section; @@ -268,39 +277,53 @@ CODE_FRAGMENT #include "libbfd.h" #include "aout/stab_gnu.h" - + /* DOCDD INODE symbol handling functions, , typedef asymbol, Symbols SUBSECTION - Symbol Handling Functions + Symbol handling functions */ /* FUNCTION - get_symtab_upper_bound + bfd_get_symtab_upper_bound DESCRIPTION - Returns the number of bytes required in a vector of pointers - to <> for all the symbols in the supplied BFD, + Return the number of bytes required to store a vector of pointers + to <> for all the symbols in the BFD @var{abfd}, including a terminal NULL pointer. If there are no symbols in - the BFD, then 0 is returned. + the BFD, then return 0. If an error occurs, return -1. -.#define get_symtab_upper_bound(abfd) \ -. BFD_SEND (abfd, _get_symtab_upper_bound, (abfd)) +.#define bfd_get_symtab_upper_bound(abfd) \ +. BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd)) */ +/* +FUNCTION + bfd_is_local_label + +SYNOPSIS + boolean bfd_is_local_label(bfd *abfd, asymbol *sym); + +DESCRIPTION + Return true if the given symbol @var{sym} in the BFD @var{abfd} is + a compiler generated local label, else return false. +.#define bfd_is_local_label(abfd, sym) \ +. BFD_SEND (abfd, _bfd_is_local_label,(abfd, sym)) +*/ + /* FUNCTION bfd_canonicalize_symtab DESCRIPTION - Supplied a BFD and a pointer to an uninitialized vector of - pointers. This reads in the symbols from the BFD, and fills in - the table with pointers to the symbols, and a trailing NULL. - The routine returns the actual number of symbol pointers not + Read the symbols from the BFD @var{abfd}, and fills in + the vector @var{location} with pointers to the symbols and + a trailing NULL. + Return the actual number of symbol pointers, not including the NULL. @@ -315,12 +338,13 @@ DESCRIPTION FUNCTION bfd_set_symtab -DESCRIPTION - Provided a table of pointers to symbols and a count, writes to - the output BFD the symbols when closed. - SYNOPSIS - boolean bfd_set_symtab (bfd *, asymbol **, unsigned int ); + boolean bfd_set_symtab (bfd *abfd, asymbol **location, unsigned int count); + +DESCRIPTION + Arrange that when the output BFD @var{abfd} is closed, + the table @var{location} of @var{count} pointers to symbols + will be written. */ boolean @@ -329,10 +353,11 @@ bfd_set_symtab (abfd, location, symcount) asymbol **location; unsigned int symcount; { - if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) { - bfd_error = invalid_operation; - return false; - } + if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } bfd_get_outsymbols (abfd) = location; bfd_get_symcount (abfd) = symcount; @@ -343,35 +368,40 @@ bfd_set_symtab (abfd, location, symcount) FUNCTION bfd_print_symbol_vandf -DESCRIPTION - Prints the value and flags of the symbol supplied to the stream file. - SYNOPSIS void bfd_print_symbol_vandf(PTR file, asymbol *symbol); + +DESCRIPTION + Print the value and flags of the @var{symbol} supplied to the + stream @var{file}. */ void -DEFUN(bfd_print_symbol_vandf,(file, symbol), -PTR file AND -asymbol *symbol) +bfd_print_symbol_vandf (arg, symbol) + PTR arg; + asymbol *symbol; { + FILE *file = (FILE *) arg; flagword type = symbol->flags; - if (symbol->section != (asection *)NULL) - { - fprintf_vma(file, symbol->value+symbol->section->vma); - } - else - { - fprintf_vma(file, symbol->value); - } - fprintf(file," %c%c%c%c%c%c%c", - (type & BSF_LOCAL) ? 'l':' ', - (type & BSF_GLOBAL) ? 'g' : ' ', - (type & BSF_WEAK) ? 'w' : ' ', - (type & BSF_CONSTRUCTOR) ? 'C' : ' ', - (type & BSF_WARNING) ? 'W' : ' ', - (type & BSF_INDIRECT) ? 'I' : ' ', - (type & BSF_DEBUGGING) ? 'd' :' '); + if (symbol->section != (asection *) NULL) + { + fprintf_vma (file, symbol->value + symbol->section->vma); + } + else + { + fprintf_vma (file, symbol->value); + } + /* This presumes that a symbol can not be both BSF_DEBUGGING and + BSF_DYNAMIC. */ + fprintf (file, " %c%c%c%c%c%c%c", + (type & BSF_LOCAL) ? 'l' : ' ', + (type & BSF_GLOBAL) ? 'g' : ' ', + (type & BSF_WEAK) ? 'w' : ' ', + (type & BSF_CONSTRUCTOR) ? 'C' : ' ', + (type & BSF_WARNING) ? 'W' : ' ', + (type & BSF_INDIRECT) ? 'I' : ' ', + (type & BSF_DEBUGGING) ? 'd' + : (type & BSF_DYNAMIC) ? 'D' : ' '); } @@ -380,10 +410,10 @@ FUNCTION bfd_make_empty_symbol DESCRIPTION - This function creates a new <> structure for the BFD, - and returns a pointer to it. + Create a new <> structure for the BFD @var{abfd} + and return a pointer to it. - This routine is necessary, since each back end has private + This routine is necessary because each back end has private information surrounding the <>. Building your own <> and pointing to it will not create the private information, and will cause problems later on. @@ -397,7 +427,7 @@ FUNCTION bfd_make_debug_symbol DESCRIPTION - This function creates a new <> structure for the BFD, + Create a new <> structure for the BFD @var{abfd}, to be used as a debugging symbol. Further details of its use have yet to be worked out. @@ -411,10 +441,11 @@ struct section_to_type char type; }; -/* Map COFF section names to POSIX/BSD single-character symbol types. +/* Map section names to POSIX/BSD single-character symbol types. This table is probably incomplete. It is sorted for convenience of adding entries. Since it is so short, a linear search is used. */ -static CONST struct section_to_type stt[] = { +static CONST struct section_to_type stt[] = +{ {"*DEBUG*", 'N'}, {".bss", 'b'}, {".data", 'd'}, @@ -426,7 +457,7 @@ static CONST struct section_to_type stt[] = { }; /* Return the single-character symbol type corresponding to - COFF section S, or '?' for an unknown COFF section. */ + section S, or '?' for an unknown COFF section. */ static char coff_section_type (s) @@ -453,27 +484,27 @@ FUNCTION DESCRIPTION Return a character corresponding to the symbol - class of symbol, or '?' for an unknown class. + class of @var{symbol}, or '?' for an unknown class. SYNOPSIS int bfd_decode_symclass(asymbol *symbol); */ int -DEFUN(bfd_decode_symclass,(symbol), -asymbol *symbol) +bfd_decode_symclass (symbol) + asymbol *symbol; { char c; if (bfd_is_com_section (symbol->section)) return 'C'; - if (symbol->section == &bfd_und_section) + if (bfd_is_und_section (symbol->section)) return 'U'; - if (symbol->section == &bfd_ind_section) + if (bfd_is_ind_section (symbol->section)) return 'I'; - if (!(symbol->flags & (BSF_GLOBAL|BSF_LOCAL))) + if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL))) return '?'; - if (symbol->section == &bfd_abs_section) + if (bfd_is_abs_section (symbol->section)) c = 'a'; else if (symbol->section) c = coff_section_type (symbol->section->name); @@ -484,8 +515,8 @@ asymbol *symbol) return c; /* We don't have to handle these cases just yet, but we will soon: - N_SETV: 'v'; - N_SETA: 'l'; + N_SETV: 'v'; + N_SETA: 'l'; N_SETT: 'x'; N_SETD: 'z'; N_SETB: 's'; @@ -507,21 +538,20 @@ SYNOPSIS */ void -DEFUN(bfd_symbol_info,(symbol, ret), - asymbol *symbol AND - symbol_info *ret) +bfd_symbol_info (symbol, ret) + asymbol *symbol; + symbol_info *ret; { ret->type = bfd_decode_symclass (symbol); if (ret->type != 'U') - ret->value = symbol->value+symbol->section->vma; + ret->value = symbol->value + symbol->section->vma; else ret->value = 0; ret->name = symbol->name; } void -bfd_symbol_is_absolute() +bfd_symbol_is_absolute () { - abort(); + abort (); } - diff --git a/gnu/usr.bin/gdb/bfd/sysdep.h b/gnu/usr.bin/gdb/bfd/sysdep.h index dd7328b1d0f0..68b107d7b67b 100644 --- a/gnu/usr.bin/gdb/bfd/sysdep.h +++ b/gnu/usr.bin/gdb/bfd/sysdep.h @@ -30,13 +30,12 @@ #ifdef __bsdi__ /* This seems to be the right thing for BSDI. */ #define HOST_STACK_END_ADDR USRSTACK +#define HOST_DATA_START_ADDR ((bfd_vma)u.u_kproc.kp_eproc.e_vm.vm_daddr) #else /* This seems to be the right thing for 386BSD release 0.1. */ #define HOST_STACK_END_ADDR (USRSTACK - MAXSSIZ) #endif -#define HOST_DATA_START_ADDR ((bfd_vma)u.u_kproc.kp_eproc.e_vm.vm_daddr) - #define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(core_bfd) \ ((core_bfd)->tdata.trad_core_data->u.u_sig) #define u_comm u_kproc.kp_proc.p_comm diff --git a/gnu/usr.bin/gdb/bfd/targets.c b/gnu/usr.bin/gdb/bfd/targets.c index d6a966588c45..15a1e45f25df 100644 --- a/gnu/usr.bin/gdb/bfd/targets.c +++ b/gnu/usr.bin/gdb/bfd/targets.c @@ -1,5 +1,5 @@ /* Generic target-file-type support for the BFD library. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 91, 92, 93, 1994 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -38,25 +38,25 @@ DESCRIPTION target are unknown. BFD uses various mechanisms to determine how to interpret the file. The operations performed are: - o First a BFD is created by calling the internal routine - <>, then <> is called with the + o Create a BFD by calling the internal routine + <<_bfd_new_bfd>>, then call <> with the target string supplied to <> and the new BFD pointer. o If a null target string was provided to <>, - it looks up the environment variable <> and uses + look up the environment variable <> and use that as the target string. - o If the target string is still NULL, or the target string is - <>, then the first item in the target vector is used - as the target type, and <> is set to + o If the target string is still <>, or the target string is + <>, then use the first item in the target vector + as the target type, and set <> in the BFD to cause <> to loop through all the targets. @xref{bfd_target}. @xref{Formats}. - o Otherwise, the elements in the target vector are inspected + o Otherwise, inspect the elements in the target vector one by one, until a match on target name is found. When found, - that is used. + use it. - o Otherwise the error <> is returned to + o Otherwise return the error <> to <>. o <> attempts to open the file using @@ -66,8 +66,8 @@ DESCRIPTION format may be determined. This is done by calling <> on the BFD with a suggested format. If <> has been set, each possible target - type is tried to see if it recognizes the specified format. The - routine returns <> when the application guesses right. + type is tried to see if it recognizes the specified format. + <> returns <> when the caller guesses right. @menu @* bfd_target:: @end menu @@ -84,16 +84,16 @@ SUBSECTION DESCRIPTION This structure contains everything that BFD knows about a - target. It includes things like its byte order, name, what - routines to call to do various operations, etc. + target. It includes things like its byte order, name, and which + routines to call to do various operations. Every BFD points to a target structure with its <> member. - These macros are used to dispatch to functions through the - bfd_target vector. They are used in a number of macros further + The macros below are used to dispatch to functions through the + <> vector. They are used in a number of macros further down in @file{bfd.h}, and are also used when calling various - routines by hand inside the BFD implementation. The "arglist" + routines by hand inside the BFD implementation. The @var{arglist} argument must be parenthesized; it contains all the arguments to the called function. @@ -102,13 +102,29 @@ DESCRIPTION .#define BFD_SEND(bfd, message, arglist) \ . ((*((bfd)->xvec->message)) arglist) +. +.#ifdef DEBUG_BFD_SEND +.#undef BFD_SEND +.#define BFD_SEND(bfd, message, arglist) \ +. (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ +. ((*((bfd)->xvec->message)) arglist) : \ +. (bfd_assert (__FILE__,__LINE__), NULL)) +.#endif - For operations which index on the BFD format + For operations which index on the BFD format: .#define BFD_SEND_FMT(bfd, message, arglist) \ . (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) +. +.#ifdef DEBUG_BFD_SEND +.#undef BFD_SEND_FMT +.#define BFD_SEND_FMT(bfd, message, arglist) \ +. (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ +. (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) : \ +. (bfd_assert (__FILE__,__LINE__), NULL)) +.#endif - This is the struct which defines the type of BFD this is. The + This is the structure which defines the type of BFD this is. The <> member of the struct <> itself points here. Each module that implements access to a different target under BFD, defines one of these. @@ -118,28 +134,34 @@ DESCRIPTION the entry points which call them. Too bad we can't have one macro to define them both! +.enum bfd_flavour { +. bfd_target_unknown_flavour, +. bfd_target_aout_flavour, +. bfd_target_coff_flavour, +. bfd_target_ecoff_flavour, +. bfd_target_elf_flavour, +. bfd_target_ieee_flavour, +. bfd_target_nlm_flavour, +. bfd_target_oasys_flavour, +. bfd_target_tekhex_flavour, +. bfd_target_srec_flavour, +. bfd_target_som_flavour, +. bfd_target_os9k_flavour}; +. +.{* Forward declaration. *} +.typedef struct bfd_link_info _bfd_link_info; +. .typedef struct bfd_target .{ -Identifies the kind of target, eg SunOS4, Ultrix, etc. +Identifies the kind of target, e.g., SunOS4, Ultrix, etc. . char *name; The "flavour" of a back end is a general indication about the contents of a file. -. enum target_flavour { -. bfd_target_unknown_flavour, -. bfd_target_aout_flavour, -. bfd_target_coff_flavour, -. bfd_target_ecoff_flavour, -. bfd_target_elf_flavour, -. bfd_target_ieee_flavour, -. bfd_target_nlm_flavour, -. bfd_target_oasys_flavour, -. bfd_target_tekhex_flavour, -. bfd_target_srec_flavour, -. bfd_target_hppa_flavour} flavour; +. enum bfd_flavour flavour; The order of bytes within the data area of a file. @@ -149,22 +171,22 @@ The order of bytes within the header parts of a file. . boolean header_byteorder_big_p; -This is a mask of all the flags which an executable may have set - +A mask of all the flags which an executable may have set - from the set <>, <>, ...<>. . flagword object_flags; -This is a mask of all the flags which a section may have set - from +A mask of all the flags which a section may have set - from the set <>, <>, ...<>. . flagword section_flags; The character normally found at the front of a symbol -(if any), perhaps _. +(if any), perhaps `_'. . char symbol_leading_char; -The pad character for filenames within an archive header. +The pad character for file names within an archive header. . char ar_pad_char; @@ -176,60 +198,95 @@ The minimum alignment restriction for any section. . unsigned int align_power_min; -Entries for byte swapping for data. These are different to the other -entry points, since they don't take BFD as first arg. Certain other handlers -could do the same. +Entries for byte swapping for data. These are different from the other +entry points, since they don't take a BFD asthe first argument. +Certain other handlers could do the same. -. bfd_vma (*bfd_getx64) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *)); . void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *)); -. bfd_vma (*bfd_getx32) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *)); . void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *)); -. bfd_vma (*bfd_getx16) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *)); . void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *)); Byte swapping for the headers -. bfd_vma (*bfd_h_getx64) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *)); . void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *)); -. bfd_vma (*bfd_h_getx32) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *)); . void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *)); -. bfd_vma (*bfd_h_getx16) PARAMS ((bfd_byte *)); -. bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((bfd_byte *)); +. bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *)); +. bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *)); . void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *)); Format dependent routines: these are vectors of entry points within the target vector structure, one for each format to check. -Check the format of a file being read. Return bfd_target * or zero. +Check the format of a file being read. Return a <> or zero. -. struct bfd_target * (*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *)); +. const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *)); Set the format of a file being written. . boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *)); -Write cached information into a file being written, at bfd_close. +Write cached information into a file being written, at <>. . boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *)); -The following functions are defined in <>. The idea is -that the back end writer of <> names all the routines -<>@var{entry_point}, <> will built the entries -in this structure in the right order. - -Core file entry points +The general target vector. +. +. {* Generic entry points. *} +.#define BFD_JUMP_TABLE_GENERIC(NAME)\ +.CAT(NAME,_close_and_cleanup),\ +.CAT(NAME,_bfd_free_cached_info),\ +.CAT(NAME,_new_section_hook),\ +.CAT(NAME,_get_section_contents) +. {* Called when the BFD is being closed to do any necessary cleanup. *} +. boolean (*_close_and_cleanup) PARAMS ((bfd *)); +. {* Ask the BFD to free all cached information. *} +. boolean (*_bfd_free_cached_info) PARAMS ((bfd *)); +. {* Called when a new section is created. *} +. boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr)); +. {* Read the contents of a section. *} +. boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, +. file_ptr, bfd_size_type)); +. +. {* Entry points to copy private data. *} +.#define BFD_JUMP_TABLE_COPY(NAME)\ +.CAT(NAME,_bfd_copy_private_bfd_data),\ +.CAT(NAME,_bfd_copy_private_section_data) +. {* Called to copy BFD general private data from one object file +. to another. *} +. boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *)); +. {* Called to copy BFD private section data from one object file +. to another. *} +. boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr, +. bfd *, sec_ptr)); +. +. {* Core file entry points. *} +.#define BFD_JUMP_TABLE_CORE(NAME)\ +.CAT(NAME,_core_file_failing_command),\ +.CAT(NAME,_core_file_failing_signal),\ +.CAT(NAME,_core_file_matches_executable_p) . char * (*_core_file_failing_command) PARAMS ((bfd *)); . int (*_core_file_failing_signal) PARAMS ((bfd *)); . boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *)); - -Archive entry points - +. +. {* Archive entry points. *} +.#define BFD_JUMP_TABLE_ARCHIVE(NAME)\ +.CAT(NAME,_slurp_armap),\ +.CAT(NAME,_slurp_extended_name_table),\ +.CAT(NAME,_truncate_arname),\ +.CAT(NAME,_write_armap),\ +.CAT(NAME,_openr_next_archived_file),\ +.CAT(NAME,_generic_stat_arch_elt) . boolean (*_bfd_slurp_armap) PARAMS ((bfd *)); . boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *)); . void (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *)); @@ -238,24 +295,23 @@ Archive entry points . struct orl *map, . unsigned int orl_count, . int stridx)); - -Standard stuff. - -. boolean (*_close_and_cleanup) PARAMS ((bfd *)); -. boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR, -. file_ptr, bfd_size_type)); -. boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, -. file_ptr, bfd_size_type)); -. boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr)); - -Symbols and relocations - -. unsigned int (*_get_symtab_upper_bound) PARAMS ((bfd *)); -. unsigned int (*_bfd_canonicalize_symtab) PARAMS ((bfd *, -. struct symbol_cache_entry **)); -. unsigned int (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr)); -. unsigned int (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, -. struct symbol_cache_entry **)); +. bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); +. int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); +. +. {* Entry points used for symbols. *} +.#define BFD_JUMP_TABLE_SYMBOLS(NAME)\ +.CAT(NAME,_get_symtab_upper_bound),\ +.CAT(NAME,_get_symtab),\ +.CAT(NAME,_make_empty_symbol),\ +.CAT(NAME,_print_symbol),\ +.CAT(NAME,_get_symbol_info),\ +.CAT(NAME,_bfd_is_local_label),\ +.CAT(NAME,_get_lineno),\ +.CAT(NAME,_find_nearest_line),\ +.CAT(NAME,_bfd_make_debug_symbol) +. long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *)); +. long (*_bfd_canonicalize_symtab) PARAMS ((bfd *, +. struct symbol_cache_entry **)); . struct symbol_cache_entry * . (*_bfd_make_empty_symbol) PARAMS ((bfd *)); . void (*_bfd_print_symbol) PARAMS ((bfd *, PTR, @@ -266,42 +322,13 @@ Symbols and relocations . struct symbol_cache_entry *, . symbol_info *)); .#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e)) - +. boolean (*_bfd_is_local_label) PARAMS ((bfd *, asymbol *)); +. . alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *)); -. -. boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture, -. unsigned long)); -. -. bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev)); -. . boolean (*_bfd_find_nearest_line) PARAMS ((bfd *abfd, . struct sec *section, struct symbol_cache_entry **symbols, . bfd_vma offset, CONST char **file, CONST char **func, . unsigned int *line)); -. -. int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *)); -. -. int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean)); -. -. void (*_bfd_debug_info_start) PARAMS ((bfd *)); -. void (*_bfd_debug_info_end) PARAMS ((bfd *)); -. void (*_bfd_debug_info_accumulate) PARAMS ((bfd *, struct sec *)); -. -. bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *, -. struct bfd_seclet *, bfd_byte *data, -. boolean relocateable)); -. -. boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *, -. struct symbol_cache_entry **)); -. -. boolean (*_bfd_seclet_link) PARAMS ((bfd *, PTR data, -. boolean relocateable)); - -. {* See documentation on reloc types. *} -. CONST struct reloc_howto_struct * -. (*reloc_type_lookup) PARAMS ((bfd *abfd, -. bfd_reloc_code_real_type code)); -. . {* Back-door to allow format-aware applications to create debug symbols . while using BFD for everything else. Currently used by the assembler . when creating COFF files. *} @@ -309,6 +336,74 @@ Symbols and relocations . bfd *abfd, . void *ptr, . unsigned long size)); +. +. {* Routines for relocs. *} +.#define BFD_JUMP_TABLE_RELOCS(NAME)\ +.CAT(NAME,_get_reloc_upper_bound),\ +.CAT(NAME,_canonicalize_reloc),\ +.CAT(NAME,_bfd_reloc_type_lookup) +. long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr)); +. long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, +. struct symbol_cache_entry **)); +. {* See documentation on reloc types. *} +. CONST struct reloc_howto_struct * +. (*reloc_type_lookup) PARAMS ((bfd *abfd, +. bfd_reloc_code_real_type code)); +. +. {* Routines used when writing an object file. *} +.#define BFD_JUMP_TABLE_WRITE(NAME)\ +.CAT(NAME,_set_arch_mach),\ +.CAT(NAME,_set_section_contents) +. boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture, +. unsigned long)); +. boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR, +. file_ptr, bfd_size_type)); +. +. {* Routines used by the linker. *} +.#define BFD_JUMP_TABLE_LINK(NAME)\ +.CAT(NAME,_sizeof_headers),\ +.CAT(NAME,_bfd_get_relocated_section_contents),\ +.CAT(NAME,_bfd_relax_section),\ +.CAT(NAME,_bfd_link_hash_table_create),\ +.CAT(NAME,_bfd_link_add_symbols),\ +.CAT(NAME,_bfd_final_link) +. int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean)); +. bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *, +. struct bfd_link_info *, struct bfd_link_order *, +. bfd_byte *data, boolean relocateable, +. struct symbol_cache_entry **)); +. +. boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *, +. struct bfd_link_info *, boolean *again)); +. +. {* Create a hash table for the linker. Different backends store +. different information in this table. *} +. struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *)); +. +. {* Add symbols from this object file into the hash table. *} +. boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *)); +. +. {* Do a link based on the link_order structures attached to each +. section of the BFD. *} +. boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *)); +. +. {* Routines to handle dynamic symbols and relocs. *} +.#define BFD_JUMP_TABLE_DYNAMIC(NAME)\ +.CAT(NAME,_get_dynamic_symtab_upper_bound),\ +.CAT(NAME,_canonicalize_dynamic_symtab),\ +.CAT(NAME,_get_dynamic_reloc_upper_bound),\ +.CAT(NAME,_canonicalize_dynamic_reloc) +. {* Get the amount of memory required to hold the dynamic symbols. *} +. long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *)); +. {* Read in the dynamic symbols. *} +. long (*_bfd_canonicalize_dynamic_symtab) +. PARAMS ((bfd *, struct symbol_cache_entry **)); +. {* Get the amount of memory required to hold the dynamic relocs. *} +. long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *)); +. {* Read in the dynamic relocs. *} +. long (*_bfd_canonicalize_dynamic_reloc) +. PARAMS ((bfd *, arelent **, struct symbol_cache_entry **)); +. Data for use by back-end routines, which isn't generic enough to belong in this structure. @@ -322,77 +417,93 @@ in this structure. Alphabetized for easy reference. They are listed a second time below, since we can't intermix extern's and initializers. */ -extern bfd_target a29kcoff_big_vec; -extern bfd_target a_out_adobe_vec; -extern bfd_target aout_mips_big_vec; -extern bfd_target aout_mips_little_vec; -extern bfd_target apollocoff_vec; -extern bfd_target b_out_vec_big_host; -extern bfd_target b_out_vec_little_host; -extern bfd_target bfd_elf32_big_generic_vec; -extern bfd_target bfd_elf32_bigmips_vec; -extern bfd_target bfd_elf32_hppa_vec; -extern bfd_target bfd_elf32_i386_vec; -extern bfd_target bfd_elf32_i860_vec; -extern bfd_target bfd_elf32_little_generic_vec; -extern bfd_target bfd_elf32_littlemips_vec; -extern bfd_target bfd_elf32_m68k_vec; -extern bfd_target bfd_elf32_m88k_vec; -extern bfd_target bfd_elf32_sparc_vec; -extern bfd_target bfd_elf64_big_generic_vec; -extern bfd_target bfd_elf64_little_generic_vec; -extern bfd_target demo_64_vec; -extern bfd_target ecoff_big_vec; -extern bfd_target ecoff_little_vec; -extern bfd_target ecoffalpha_little_vec; -extern bfd_target h8300coff_vec; -extern bfd_target h8500coff_vec; -extern bfd_target host_aout_vec; -extern bfd_target hp300bsd_vec; -extern bfd_target hp300hpux_vec; -extern bfd_target hppa_vec; -extern bfd_target i386aout_vec; -extern bfd_target i386bsd_vec; -extern bfd_target netbsd386_vec; -extern bfd_target freebsd386_vec; -extern bfd_target i386coff_vec; -extern bfd_target i386linux_vec; -extern bfd_target i386lynx_aout_vec; -extern bfd_target i386lynx_coff_vec; -extern bfd_target icoff_big_vec; -extern bfd_target icoff_little_vec; -extern bfd_target ieee_vec; -extern bfd_target m68kcoff_vec; -extern bfd_target m68kcoffun_vec; -extern bfd_target m68klynx_aout_vec; -extern bfd_target m68klynx_coff_vec; -extern bfd_target m88kbcs_vec; -extern bfd_target newsos3_vec; -extern bfd_target nlm32_big_generic_vec; -extern bfd_target nlm32_i386_vec; -extern bfd_target nlm32_little_generic_vec; -extern bfd_target nlm64_big_generic_vec; -extern bfd_target nlm64_little_generic_vec; -extern bfd_target oasys_vec; -extern bfd_target rs6000coff_vec; -extern bfd_target shcoff_vec; -extern bfd_target sunos_big_vec; -extern bfd_target tekhex_vec; -extern bfd_target we32kcoff_vec; -extern bfd_target z8kcoff_vec; +extern const bfd_target a29kcoff_big_vec; +extern const bfd_target a_out_adobe_vec; +extern const bfd_target aout_mips_big_vec; +extern const bfd_target aout_mips_little_vec; +extern const bfd_target aout0_big_vec; +extern const bfd_target apollocoff_vec; +extern const bfd_target b_out_vec_big_host; +extern const bfd_target b_out_vec_little_host; +extern const bfd_target bfd_elf32_big_generic_vec; +extern const bfd_target bfd_elf32_bigmips_vec; +extern const bfd_target bfd_elf32_hppa_vec; +extern const bfd_target bfd_elf32_i386_vec; +extern const bfd_target bfd_elf32_i860_vec; +extern const bfd_target bfd_elf32_little_generic_vec; +extern const bfd_target bfd_elf32_littlemips_vec; +extern const bfd_target bfd_elf32_m68k_vec; +extern const bfd_target bfd_elf32_m88k_vec; +extern const bfd_target bfd_elf32_powerpc_vec; +extern const bfd_target bfd_elf32_sparc_vec; +extern const bfd_target bfd_elf64_big_generic_vec; +extern const bfd_target bfd_elf64_little_generic_vec; +extern const bfd_target bfd_elf64_sparc_vec; +extern const bfd_target demo_64_vec; +extern const bfd_target ecoff_big_vec; +extern const bfd_target ecoff_little_vec; +extern const bfd_target ecoffalpha_little_vec; +extern const bfd_target h8300coff_vec; +extern const bfd_target h8500coff_vec; +extern const bfd_target host_aout_vec; +extern const bfd_target hp300bsd_vec; +extern const bfd_target hp300hpux_vec; +extern const bfd_target som_vec; +extern const bfd_target i386aout_vec; +extern const bfd_target i386bsd_vec; +extern const bfd_target i386dynix_vec; +extern const bfd_target i386os9k_vec; +extern const bfd_target netbsd386_vec; +extern const bfd_target freebsd386_vec; +extern const bfd_target i386coff_vec; +extern const bfd_target go32coff_vec; +extern const bfd_target i386linux_vec; +extern const bfd_target i386lynx_aout_vec; +extern const bfd_target i386lynx_coff_vec; +extern const bfd_target i386mach3_vec; +extern const bfd_target icoff_big_vec; +extern const bfd_target icoff_little_vec; +extern const bfd_target ieee_vec; +extern const bfd_target m68kcoff_vec; +extern const bfd_target m68kcoffun_vec; +extern const bfd_target m68klynx_aout_vec; +extern const bfd_target m68klynx_coff_vec; +extern const bfd_target m88kbcs_vec; +extern const bfd_target m88kmach3_vec; +extern const bfd_target netbsd532_vec; +extern const bfd_target newsos3_vec; +extern const bfd_target nlm32_i386_vec; +extern const bfd_target nlm32_sparc_vec; +extern const bfd_target nlm32_alpha_vec; +extern const bfd_target nlm32_powerpc_vec; +extern const bfd_target oasys_vec; +extern const bfd_target pc532mach_vec; +extern const bfd_target rs6000coff_vec; +extern const bfd_target shcoff_vec; +extern const bfd_target sparclynx_aout_vec; +extern const bfd_target sparclynx_coff_vec; +extern const bfd_target sparccoff_vec; +extern const bfd_target sunos_big_vec; +extern const bfd_target tekhex_vec; +extern const bfd_target we32kcoff_vec; +extern const bfd_target z8kcoff_vec; /* srec is always included. */ -extern bfd_target srec_vec; -extern bfd_target symbolsrec_vec; +extern const bfd_target srec_vec; +extern const bfd_target symbolsrec_vec; /* All of the xvecs for core files. */ -extern bfd_target aix386_core_vec; -extern bfd_target hpux_core_vec; -extern bfd_target osf_core_vec; -extern bfd_target sco_core_vec; -extern bfd_target trad_core_vec; +extern const bfd_target aix386_core_vec; +extern const bfd_target cisco_core_vec; +extern const bfd_target hpux_core_vec; +extern const bfd_target hppabsd_core_vec; +extern const bfd_target irix_core_vec; +extern const bfd_target osf_core_vec; +extern const bfd_target sco_core_vec; +extern const bfd_target trad_core_vec; +extern const bfd_target ptrace_core_vec; -bfd_target *target_vector[] = { +const bfd_target * const bfd_target_vector[] = { #ifdef SELECT_VECS @@ -417,26 +528,32 @@ bfd_target *target_vector[] = { &aout_mips_little_vec, &b_out_vec_big_host, &b_out_vec_little_host, -#if 0 /* No one seems to use this. */ + + /* This, and other vectors, may not be used in any *.mt configuration. + But that does not mean they are unnecessary. If configured with + --enable-targets=all, objdump or gdb should be able to examine + the file even if we don't recognize the machine type. */ &bfd_elf32_big_generic_vec, &bfd_elf32_bigmips_vec, -#endif -#if 0 &bfd_elf32_hppa_vec, -#endif &bfd_elf32_i386_vec, &bfd_elf32_i860_vec, -#if 0 /* No one seems to use this. */ &bfd_elf32_little_generic_vec, &bfd_elf32_littlemips_vec, -#endif &bfd_elf32_m68k_vec, &bfd_elf32_m88k_vec, &bfd_elf32_sparc_vec, + &bfd_elf32_powerpc_vec, #ifdef BFD64 /* No one seems to use this. */ &bfd_elf64_big_generic_vec, &bfd_elf64_little_generic_vec, #endif +#if 0 + &bfd_elf64_sparc_vec, +#endif + /* We don't include cisco_core_vec. Although it has a magic number, + the magic number isn't at the beginning of the file, and thus + might spuriously match other kinds of files. */ #ifdef BFD64 &demo_64_vec, /* Only compiled if host has long-long support */ #endif @@ -448,25 +565,33 @@ bfd_target *target_vector[] = { &h8300coff_vec, &h8500coff_vec, #if 0 + /* Since a.out files lack decent magic numbers, no way to recognize + which kind of a.out file it is. */ &host_aout_vec, #endif #if 0 /* Clashes with sunos_big_vec magic no. */ &hp300bsd_vec, #endif &hp300hpux_vec, -#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD) - &hppa_vec, +#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD) || defined (HOST_HPPAOSF) + &som_vec, #endif &i386aout_vec, &i386bsd_vec, - &netbsd386_vec, - &freebsd386_vec, &i386coff_vec, + &go32coff_vec, #if 0 + /* Since a.out files lack decent magic numbers, no way to recognize + which kind of a.out file it is. */ &i386linux_vec, #endif &i386lynx_aout_vec, &i386lynx_coff_vec, +#if 0 + /* No distinguishing features for Mach 3 executables. */ + &i386mach3_vec, +#endif + &i386os9k_vec, &icoff_big_vec, &icoff_little_vec, &ieee_vec, @@ -475,17 +600,14 @@ bfd_target *target_vector[] = { &m68klynx_aout_vec, &m68klynx_coff_vec, &m88kbcs_vec, + &m88kmach3_vec, &newsos3_vec, -#if 0 /* No one seems to use this. */ - &nlm32_big_generic_vec, -#endif + &netbsd386_vec, + &netbsd532_vec, &nlm32_i386_vec, -#if 0 /* No one seems to use this. */ - &nlm32_little_generic_vec, -#endif + &nlm32_sparc_vec, #ifdef BFD64 - &nlm64_big_generic_vec, - &nlm64_little_generic_vec, + &nlm32_alpha_vec, #endif #if 0 /* We have no oasys tools anymore, so we can't test any of this @@ -495,9 +617,13 @@ bfd_target *target_vector[] = { can be annoying target mis-matches. */ &oasys_vec, #endif + &pc532machaout_vec, &rs6000coff_vec, &shcoff_vec, + &sparclynx_aout_vec, + &sparclynx_coff_vec, &sunos_big_vec, + &aout0_big_vec, #if 0 &tekhex_vec, #endif @@ -518,57 +644,66 @@ bfd_target *target_vector[] = { #ifdef HPUX_CORE &hpux_core_vec, #endif +#ifdef HPPABSD_CORE + &hppabsd_core_vec, +#endif +#ifdef IRIX_CORE + &irix_core_vec, +#endif #ifdef OSF_CORE &osf_core_vec, #endif -#ifdef SCO_CORE - &sco_core_vec, -#endif #ifdef TRAD_CORE &trad_core_vec, #endif +#ifdef PTRACE_CORE + &ptrace_core_vec, +#endif + NULL /* end of list marker */ }; -/* default_vector[0] contains either the address of the default vector, +/* bfd_default_vector[0] contains either the address of the default vector, if there is one, or zero if there isn't. */ -bfd_target *default_vector[] = { +const bfd_target * const bfd_default_vector[] = { #ifdef DEFAULT_VECTOR &DEFAULT_VECTOR, #endif NULL }; - - +/* When there is an ambiguous match, bfd_check_format_matches puts the + names of the matching targets in an array. This variable is the maximum + number of entries that the array could possibly need. */ +const size_t _bfd_target_vector_entries = sizeof(bfd_target_vector)/sizeof(*bfd_target_vector); /* FUNCTION bfd_find_target +SYNOPSIS + const bfd_target *bfd_find_target(CONST char *target_name, bfd *abfd); + DESCRIPTION - Returns a pointer to the transfer vector for the object target - named target_name. If target_name is NULL, chooses the one in - the environment variable GNUTARGET; if that is null or not - defined thenthe first entry in the target list is chosen. + Return a pointer to the transfer vector for the object target + named @var{target_name}. If @var{target_name} is <>, choose the + one in the environment variable <>; if that is null or not + defined, then choose the first entry in the target list. Passing in the string "default" or setting the environment variable to "default" will cause the first entry in the target list to be returned, and "target_defaulted" will be set in the BFD. This causes <> to loop over all the targets to find the one that matches the file being read. - -SYNOPSIS - bfd_target *bfd_find_target(CONST char *, bfd *); */ -bfd_target * -DEFUN(bfd_find_target,(target_name, abfd), - CONST char *target_name AND - bfd *abfd) +const bfd_target * +bfd_find_target (target_name, abfd) + CONST char *target_name; + bfd *abfd; { - bfd_target **target; + const bfd_target * const *target; extern char *getenv (); CONST char *targname = (target_name ? target_name : (CONST char *) getenv ("GNUTARGET")); @@ -576,17 +711,17 @@ DEFUN(bfd_find_target,(target_name, abfd), /* This is safe; the vector cannot be null */ if (targname == NULL || !strcmp (targname, "default")) { abfd->target_defaulted = true; - return abfd->xvec = target_vector[0]; + return abfd->xvec = bfd_target_vector[0]; } abfd->target_defaulted = false; - for (target = &target_vector[0]; *target != NULL; target++) { + for (target = &bfd_target_vector[0]; *target != NULL; target++) { if (!strcmp (targname, (*target)->name)) return abfd->xvec = *target; } - bfd_error = invalid_target; + bfd_set_error (bfd_error_invalid_target); return NULL; } @@ -595,18 +730,18 @@ DEFUN(bfd_find_target,(target_name, abfd), FUNCTION bfd_target_list -DESCRIPTION - This function returns a freshly malloced NULL-terminated - vector of the names of all the valid BFD targets. Do not - modify the names - SYNOPSIS - CONST char **bfd_target_list(void); + const char **bfd_target_list(void); + +DESCRIPTION + Return a freshly malloced NULL-terminated + vector of the names of all the valid BFD targets. Do not + modify the names. */ -CONST char ** -DEFUN_VOID(bfd_target_list) +const char ** +bfd_target_list () { int vec_length= 0; #ifdef NATIVE_HPPAHPUX_COMPILER @@ -614,21 +749,21 @@ DEFUN_VOID(bfd_target_list) to loop endlessly when compiling this file. This avoids it. */ volatile #endif - bfd_target **target; + const bfd_target * const *target; CONST char **name_list, **name_ptr; - for (target = &target_vector[0]; *target != NULL; target++) + for (target = &bfd_target_vector[0]; *target != NULL; target++) vec_length++; - name_ptr = - name_list = (CONST char **) zalloc ((vec_length + 1) * sizeof (char **)); + name_ptr = name_list = (CONST char **) + bfd_zmalloc ((vec_length + 1) * sizeof (char **)); if (name_list == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return NULL; } - for (target = &target_vector[0]; *target != NULL; target++) + for (target = &bfd_target_vector[0]; *target != NULL; target++) *(name_ptr++) = (*target)->name; return name_list; diff --git a/gnu/usr.bin/gdb/bfd/trad-core.c b/gnu/usr.bin/gdb/bfd/trad-core.c index 203c80e6a832..48b5f8e0ad81 100644 --- a/gnu/usr.bin/gdb/bfd/trad-core.c +++ b/gnu/usr.bin/gdb/bfd/trad-core.c @@ -1,5 +1,5 @@ /* BFD back end for traditional Unix core files (U-area and raw sections) - Copyright 1988, 1989, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1988, 1989, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by John Gilmore of Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -63,7 +63,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* forward declarations */ -bfd_target * trad_unix_core_file_p PARAMS ((bfd *abfd)); +const bfd_target *trad_unix_core_file_p PARAMS ((bfd *abfd)); char * trad_unix_core_file_failing_command PARAMS ((bfd *abfd)); int trad_unix_core_file_failing_signal PARAMS ((bfd *abfd)); boolean trad_unix_core_file_matches_executable_p @@ -72,7 +72,7 @@ boolean trad_unix_core_file_matches_executable_p /* Handle 4.2-style (and perhaps also sysV-style) core dump file. */ /* ARGSUSED */ -bfd_target * +const bfd_target * trad_unix_core_file_p (abfd) bfd *abfd; @@ -82,7 +82,7 @@ trad_unix_core_file_p (abfd) #ifdef TRAD_CORE_USER_OFFSET /* If defined, this macro is the file position of the user struct. */ - if (bfd_seek (abfd, TRAD_CORE_USER_OFFSET, SEEK_SET) == 0) + if (bfd_seek (abfd, TRAD_CORE_USER_OFFSET, SEEK_SET) != 0) return 0; #endif @@ -90,19 +90,19 @@ trad_unix_core_file_p (abfd) if (val != sizeof u) { /* Too small to be a core file */ - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return 0; } /* Sanity check perhaps??? */ if (u.u_dsize > 0x1000000) /* Remember, it's in pages... */ { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return 0; } if (u.u_ssize > 0x1000000) { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return 0; } @@ -114,14 +114,19 @@ trad_unix_core_file_p (abfd) return 0; if (fstat (fileno (stream), &statbuf) < 0) { - bfd_error = system_call_error; + bfd_set_error (bfd_error_system_call); return 0; } - if (NBPG * (UPAGES + u.u_dsize + u.u_ssize) > statbuf.st_size) + if (NBPG * (UPAGES + u.u_dsize +#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE + - u.u_tsize +#endif + + u.u_ssize) > statbuf.st_size) { - bfd_error = file_truncated; + bfd_set_error (bfd_error_file_truncated); return 0; } +#ifndef TRAD_CORE_ALLOW_ANY_EXTRA_SIZE if (NBPG * (UPAGES + u.u_dsize + u.u_ssize) #ifdef TRAD_CORE_EXTRA_SIZE_ALLOWED /* Some systems write the file too big. */ @@ -131,9 +136,10 @@ trad_unix_core_file_p (abfd) { /* The file is too big. Maybe it's not a core file or we otherwise have bad values for u_dsize and u_ssize). */ - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return 0; } +#endif } /* OK, we believe you. You're a core file (sure, sure). */ @@ -141,9 +147,9 @@ trad_unix_core_file_p (abfd) /* Allocate both the upage and the struct core_data at once, so a single free() will free them both. */ rawptr = (struct trad_core_struct *) - bfd_zalloc (abfd, sizeof (struct trad_core_struct)); + bfd_zmalloc (sizeof (struct trad_core_struct)); if (rawptr == NULL) { - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); return 0; } @@ -154,20 +160,20 @@ trad_unix_core_file_p (abfd) /* Create the sections. This is raunchy, but bfd_close wants to free them separately. */ - core_stacksec(abfd) = (asection *) zalloc (sizeof (asection)); + core_stacksec(abfd) = (asection *) bfd_zmalloc (sizeof (asection)); if (core_stacksec (abfd) == NULL) { loser: - bfd_error = no_memory; + bfd_set_error (bfd_error_no_memory); free ((void *)rawptr); return 0; } - core_datasec (abfd) = (asection *) zalloc (sizeof (asection)); + core_datasec (abfd) = (asection *) bfd_zmalloc (sizeof (asection)); if (core_datasec (abfd) == NULL) { loser1: free ((void *)core_stacksec (abfd)); goto loser; } - core_regsec (abfd) = (asection *) zalloc (sizeof (asection)); + core_regsec (abfd) = (asection *) bfd_zmalloc (sizeof (asection)); if (core_regsec (abfd) == NULL) { free ((void *)core_datasec (abfd)); goto loser1; @@ -179,9 +185,13 @@ trad_unix_core_file_p (abfd) core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; - core_regsec (abfd)->flags = SEC_ALLOC + SEC_HAS_CONTENTS; + core_regsec (abfd)->flags = SEC_HAS_CONTENTS; - core_datasec (abfd)->_raw_size = NBPG * u.u_dsize; + core_datasec (abfd)->_raw_size = NBPG * u.u_dsize +#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE + - NBPG * u.u_tsize +#endif + ; core_stacksec (abfd)->_raw_size = NBPG * u.u_ssize; core_regsec (abfd)->_raw_size = NBPG * UPAGES; /* Larger than sizeof struct u */ @@ -192,14 +202,7 @@ trad_unix_core_file_p (abfd) #else core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize); #endif -/* a hack, but it works for FreeBSD !! */ -#include -/* this should really be in , but somebody forgot it */ -#ifndef vm_page_size -#define vm_page_size 4096 -#endif -#define HOST_STACK_START_ADDR trunc_page(u.u_kproc.kp_eproc.e_vm.vm_maxsaddr \ -+ MAXSSIZ - ctob(u.u_ssize)) + #ifdef HOST_STACK_START_ADDR core_stacksec (abfd)->vma = HOST_STACK_START_ADDR; #else @@ -223,11 +226,11 @@ trad_unix_core_file_p (abfd) core_regsec (abfd)->vma = 0 - (int) u.u_ar0; core_datasec (abfd)->filepos = NBPG * UPAGES; -#ifdef TRAD_CORE_STACK_FILEPOS - core_stacksec (abfd)->filepos = TRAD_CORE_STACK_FILEPOS; -#else - core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize; + core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize +#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE + - NBPG * u.u_tsize #endif + ; core_regsec (abfd)->filepos = 0; /* Register segment is the upage */ /* Align to word at least */ @@ -276,74 +279,18 @@ trad_unix_core_file_matches_executable_p (core_bfd, exec_bfd) return true; /* FIXME, We have no way of telling at this point */ } -/* No archive file support via this BFD */ -#define trad_unix_openr_next_archived_file bfd_generic_openr_next_archived_file -#define trad_unix_generic_stat_arch_elt bfd_generic_stat_arch_elt -#define trad_unix_slurp_armap bfd_false -#define trad_unix_slurp_extended_name_table bfd_true -#define trad_unix_write_armap (boolean (*) PARAMS \ - ((bfd *arch, unsigned int elength, struct orl *map, \ - unsigned int orl_count, int stridx))) bfd_false -#define trad_unix_truncate_arname bfd_dont_truncate_arname -#define aout_32_openr_next_archived_file bfd_generic_openr_next_archived_file - -#define trad_unix_close_and_cleanup bfd_generic_close_and_cleanup -#define trad_unix_set_section_contents (boolean (*) PARAMS \ - ((bfd *abfd, asection *section, PTR data, file_ptr offset, \ - bfd_size_type count))) bfd_false -#define trad_unix_get_section_contents bfd_generic_get_section_contents -#define trad_unix_new_section_hook (boolean (*) PARAMS \ - ((bfd *, sec_ptr))) bfd_true -#define trad_unix_get_symtab_upper_bound bfd_0u -#define trad_unix_get_symtab (unsigned int (*) PARAMS \ - ((bfd *, struct symbol_cache_entry **))) bfd_0u -#define trad_unix_get_reloc_upper_bound (unsigned int (*) PARAMS \ - ((bfd *, sec_ptr))) bfd_0u -#define trad_unix_canonicalize_reloc (unsigned int (*) PARAMS \ - ((bfd *, sec_ptr, arelent **, struct symbol_cache_entry**))) bfd_0u -#define trad_unix_make_empty_symbol (struct symbol_cache_entry * \ - (*) PARAMS ((bfd *))) bfd_false -#define trad_unix_print_symbol (void (*) PARAMS \ - ((bfd *, PTR, struct symbol_cache_entry *, \ - bfd_print_symbol_type))) bfd_false -#define trad_unix_get_symbol_info (void (*) PARAMS \ - ((bfd *, struct symbol_cache_entry *, \ - symbol_info *))) bfd_false -#define trad_unix_get_lineno (alent * (*) PARAMS \ - ((bfd *, struct symbol_cache_entry *))) bfd_nullvoidptr -#define trad_unix_set_arch_mach (boolean (*) PARAMS \ - ((bfd *, enum bfd_architecture, unsigned long))) bfd_false -#define trad_unix_find_nearest_line (boolean (*) PARAMS \ - ((bfd *abfd, struct sec *section, \ - struct symbol_cache_entry **symbols,bfd_vma offset, \ - CONST char **file, CONST char **func, unsigned int *line))) bfd_false -#define trad_unix_sizeof_headers (int (*) PARAMS \ - ((bfd *, boolean))) bfd_0 - -#define trad_unix_bfd_debug_info_start bfd_void -#define trad_unix_bfd_debug_info_end bfd_void -#define trad_unix_bfd_debug_info_accumulate (void (*) PARAMS \ - ((bfd *, struct sec *))) bfd_void -#define trad_unix_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents -#define trad_unix_bfd_relax_section bfd_generic_relax_section -#define trad_unix_bfd_seclet_link \ - ((boolean (*) PARAMS ((bfd *, PTR, boolean))) bfd_false) -#define trad_unix_bfd_reloc_type_lookup \ - ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) -#define trad_unix_bfd_make_debug_symbol \ - ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) - /* If somebody calls any byte-swapping routines, shoot them. */ void swap_abort() { abort(); /* This way doesn't require any declaration for ANSI to fuck up */ } -#define NO_GET ((bfd_vma (*) PARAMS (( bfd_byte *))) swap_abort ) +#define NO_GET ((bfd_vma (*) PARAMS (( const bfd_byte *))) swap_abort ) #define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort ) -#define NO_SIGNED_GET ((bfd_signed_vma (*) PARAMS ((bfd_byte *))) swap_abort ) +#define NO_SIGNED_GET \ + ((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort ) -bfd_target trad_core_vec = +const bfd_target trad_core_vec = { "trad-core", bfd_target_unknown_flavour, @@ -351,7 +298,7 @@ bfd_target trad_core_vec = true, /* target headers byte order */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | - HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 0, /* symbol prefix */ ' ', /* ar_pad_char */ @@ -379,6 +326,15 @@ bfd_target trad_core_vec = bfd_false, bfd_false }, - JUMP_TABLE(trad_unix), + BFD_JUMP_TABLE_GENERIC (_bfd_generic), + BFD_JUMP_TABLE_COPY (_bfd_generic), + BFD_JUMP_TABLE_CORE (trad_unix), + BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), + BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), + BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), + BFD_JUMP_TABLE_WRITE (_bfd_generic), + BFD_JUMP_TABLE_LINK (_bfd_nolink), + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + (PTR) 0 /* backend_data */ }; diff --git a/gnu/usr.bin/gdb/gdb/Makefile b/gnu/usr.bin/gdb/gdb/Makefile index 70f0e0c0de74..3e481ce39964 100644 --- a/gnu/usr.bin/gdb/gdb/Makefile +++ b/gnu/usr.bin/gdb/gdb/Makefile @@ -1,19 +1,23 @@ PROG = gdb BINDIR= /usr/bin CLEANFILES+= y.tab.h c-exp.tab.c ch-exp.tab.c m2-exp.tab.c -SRCS = main.c blockframe.c breakpoint.c findvar.c stack.c thread.c \ - source.c values.c eval.c valops.c valarith.c valprint.c printcmd.c \ - symtab.c symfile.c symmisc.c infcmd.c infrun.c command.c utils.c \ - expprint.c environ.c gdbtypes.c copying.c i386-tdep.c i386-pinsn.c \ - freebsd-solib.c ser-unix.c exec.c fork-child.c infptrace.c inftarg.c \ - corelow.c coredep.c freebsd-nat.c remote.c dcache.c remote-utils.c \ - mem-break.c target.c putenv.c parse.c language.c buildsym.c \ - objfiles.c minsyms.c maint.c demangle.c dbxread.c coffread.c \ - elfread.c dwarfread.c mipsread.c stabsread.c core.c c-lang.c \ - ch-lang.c m2-lang.c complaints.c typeprint.c c-typeprint.c \ - ch-typeprint.c m2-typeprint.c c-valprint.c cp-valprint.c ch-valprint.c \ - m2-valprint.c nlmread.c serial.c inflow.c regex.c init.c \ - c-exp.tab.c ch-exp.tab.c m2-exp.tab.c version.c i386-dis.c dis-buf.c +SRCS = annotate.c blockframe.c breakpoint.c buildsym.c c-lang.c \ + c-typeprint.c c-valprint.c ch-lang.c ch-typeprint.c \ + ch-valprint.c coffread.c command.c complaints.c copying.c core.c \ + coredep.c corelow.c cp-valprint.c \ + dcache.c dbxread.c demangle.c disassemble.c dis-buf.c dwarfread.c \ + elfread.c environ.c eval.c exec.c expprint.c \ + findvar.c fork-child.c freebsd-nat.c gdbtypes.c i386-dis.c \ + i386-pinsn.c i386-tdep.c infcmd.c inflow.c infptrace.c \ + infrun.c inftarg.c init.c kcorelow.c language.c \ + m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \ + mem-break.c minsyms.c objfiles.c parse.c \ + printcmd.c regex.c remote.c remote-utils.c solib.c source.c \ + stabsread.c stack.c symfile.c symmisc.c \ + symtab.c target.c thread.c top.c \ + typeprint.c utils.c valarith.c valops.c \ + valprint.c values.c version.c serial.c ser-unix.c mdebugread.c\ + c-exp.tab.c ch-exp.tab.c m2-exp.tab.c c-exp.tab.c: $(.CURDIR)/c-exp.y yacc -d -p c_ $(.CURDIR)/c-exp.y @@ -40,7 +44,6 @@ m2-exp.tab.c: $(.CURDIR)/m2-exp.y mv m2-exp.new ./m2-exp.tab.c - CFLAGS+= -I$(.CURDIR)/. -I${DESTDIR}/usr/include/readline -I$(.CURDIR)/../bfd DPADD+= ${LIBREADLINE} ${LIBTERMCAP} LDADD+= -lreadline -ltermcap diff --git a/gnu/usr.bin/gdb/gdb/ansidecl.h b/gnu/usr.bin/gdb/gdb/ansidecl.h index fdc4072120ed..3c0dcb3d9fc4 100644 --- a/gnu/usr.bin/gdb/gdb/ansidecl.h +++ b/gnu/usr.bin/gdb/gdb/ansidecl.h @@ -27,6 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ VOLATILE `volatile' `' SIGNED `signed' `' PTRCONST `void *const' `char *' + ANSI_PROTOTYPES 1 not defined CONST is also defined, but is obsolete. Just use const. @@ -111,6 +112,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define PROTO(type, name, arglist) type name arglist #define PARAMS(paramlist) paramlist +#define ANSI_PROTOTYPES 1 #else /* Not ANSI C. */ diff --git a/gnu/usr.bin/gdb/gdb/aout/aout64.h b/gnu/usr.bin/gdb/gdb/aout/aout64.h index 018e6ddb0685..18b6bfd65c7b 100644 --- a/gnu/usr.bin/gdb/gdb/aout/aout64.h +++ b/gnu/usr.bin/gdb/gdb/aout/aout64.h @@ -36,9 +36,10 @@ struct external_exec #define OMAGIC 0407 /* ...object file or impure executable. */ #define NMAGIC 0410 /* Code indicating pure executable. */ #define ZMAGIC 0413 /* Code indicating demand-paged executable. */ +#define BMAGIC 0415 /* Used by a b.out object. */ /* This indicates a demand-paged executable with the header in the text. - As far as I know it is only used by 386BSD and/or BSDI. */ + It is used by 386BSD (and variants) and Linux, at least. */ #define QMAGIC 0314 # ifndef N_BADMAG # define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \ @@ -57,7 +58,7 @@ struct external_exec #endif /* The difference between PAGE_SIZE and N_SEGSIZE is that PAGE_SIZE is - the the finest granularity at which you can page something, thus it + the finest granularity at which you can page something, thus it controls the padding (if any) before the text segment of a ZMAGIC file. N_SEGSIZE is the resolution at which things can be marked as read-only versus read/write, so it controls the padding between the @@ -121,6 +122,11 @@ struct external_exec #define N_SHARED_LIB(x) ((x).a_entry < TEXT_START_ADDR) #endif +/* Returning 0 not TEXT_START_ADDR for OMAGIC and NMAGIC is based on + the assumption that we are dealing with a .o file, not an + executable. This is necessary for OMAGIC (but means we don't work + right on the output from ld -N); more questionable for NMAGIC. */ + #ifndef N_TXTADDR #define N_TXTADDR(x) \ (/* The address of a QMAGIC file is always one page in, */ \ @@ -134,6 +140,19 @@ struct external_exec ) #endif +/* If N_HEADER_IN_TEXT is not true for ZMAGIC, there is some padding + to make the text segment start at a certain boundary. For most + systems, this boundary is PAGE_SIZE. But for Linux, in the + time-honored tradition of crazy ZMAGIC hacks, it is 1024 which is + not what PAGE_SIZE needs to be for QMAGIC. */ + +#ifndef ZMAGIC_DISK_BLOCK_SIZE +#define ZMAGIC_DISK_BLOCK_SIZE PAGE_SIZE +#endif + +#define N_DISK_BLOCK_SIZE(x) \ + (N_MAGIC(x) == ZMAGIC ? ZMAGIC_DISK_BLOCK_SIZE : PAGE_SIZE) + /* Offset in an a.out of the start of the text section. */ #ifndef N_TXTOFF #define N_TXTOFF(x) \ @@ -142,7 +161,7 @@ struct external_exec N_SHARED_LIB(x) ? 0 : \ N_HEADER_IN_TEXT(x) ? \ EXEC_BYTES_SIZE : /* no padding */\ - PAGE_SIZE /* a page of padding */\ + ZMAGIC_DISK_BLOCK_SIZE /* a page of padding */\ ) #endif /* Size of the text section. It's always as stated, except that we @@ -174,15 +193,21 @@ struct external_exec /* Offsets of the various portions of the file after the text segment. */ -/* For {N,Q,Z}MAGIC, there is padding to make the data segment start - on a page boundary. Most of the time the a_text field (and thus - N_TXTSIZE) already contains this padding. But if it doesn't (I - think maybe this happens on BSDI and/or 386BSD), then add it. */ +/* For {Q,Z}MAGIC, there is padding to make the data segment start on + a page boundary. Most of the time the a_text field (and thus + N_TXTSIZE) already contains this padding. It is possible that for + BSDI and/or 386BSD it sometimes doesn't contain the padding, and + perhaps we should be adding it here. But this seems kind of + questionable and probably should be BSDI/386BSD-specific if we do + do it. + + For NMAGIC (at least for hp300 BSD, probably others), there is + padding in memory only, not on disk, so we must *not* ever pad here + for NMAGIC. */ #ifndef N_DATOFF #define N_DATOFF(x) \ - (N_MAGIC(x) == OMAGIC ? N_TXTOFF(x) + N_TXTSIZE(x) : \ - PAGE_SIZE + ((N_TXTOFF(x) + N_TXTSIZE(x) - 1) & ~(PAGE_SIZE - 1))) + (N_TXTOFF(x) + N_TXTSIZE(x)) #endif #ifndef N_TRELOFF @@ -263,6 +288,17 @@ struct internal_nlist { #define N_WARNING 0x1e +/* Weak symbols. These are a GNU extension to the a.out format. The + semantics are those of ELF weak symbols. Weak symbols are always + externally visible. The N_WEAK? values are squeezed into the + available slots. The value of a N_WEAKU symbol is 0. The values + of the other types are the definitions. */ +#define N_WEAKU 0x0d /* Weak undefined symbol. */ +#define N_WEAKA 0x0e /* Weak absolute symbol. */ +#define N_WEAKT 0x0f /* Weak text symbol. */ +#define N_WEAKD 0x10 /* Weak data symbol. */ +#define N_WEAKB 0x11 /* Weak bss symbol. */ + /* Relocations There are two types of relocation flavours for a.out systems, @@ -286,25 +322,25 @@ struct reloc_std_external { bfd_byte r_type[1]; /* relocation type */ }; -#define RELOC_STD_BITS_PCREL_BIG 0x80 -#define RELOC_STD_BITS_PCREL_LITTLE 0x01 +#define RELOC_STD_BITS_PCREL_BIG ((unsigned int) 0x80) +#define RELOC_STD_BITS_PCREL_LITTLE ((unsigned int) 0x01) -#define RELOC_STD_BITS_LENGTH_BIG 0x60 -#define RELOC_STD_BITS_LENGTH_SH_BIG 5 /* To shift to units place */ -#define RELOC_STD_BITS_LENGTH_LITTLE 0x06 +#define RELOC_STD_BITS_LENGTH_BIG ((unsigned int) 0x60) +#define RELOC_STD_BITS_LENGTH_SH_BIG 5 +#define RELOC_STD_BITS_LENGTH_LITTLE ((unsigned int) 0x06) #define RELOC_STD_BITS_LENGTH_SH_LITTLE 1 -#define RELOC_STD_BITS_EXTERN_BIG 0x10 -#define RELOC_STD_BITS_EXTERN_LITTLE 0x08 +#define RELOC_STD_BITS_EXTERN_BIG ((unsigned int) 0x10) +#define RELOC_STD_BITS_EXTERN_LITTLE ((unsigned int) 0x08) -#define RELOC_STD_BITS_BASEREL_BIG 0x08 -#define RELOC_STD_BITS_BASEREL_LITTLE 0x08 +#define RELOC_STD_BITS_BASEREL_BIG ((unsigned int) 0x08) +#define RELOC_STD_BITS_BASEREL_LITTLE ((unsigned int) 0x10) -#define RELOC_STD_BITS_JMPTABLE_BIG 0x04 -#define RELOC_STD_BITS_JMPTABLE_LITTLE 0x04 +#define RELOC_STD_BITS_JMPTABLE_BIG ((unsigned int) 0x04) +#define RELOC_STD_BITS_JMPTABLE_LITTLE ((unsigned int) 0x20) -#define RELOC_STD_BITS_RELATIVE_BIG 0x02 -#define RELOC_STD_BITS_RELATIVE_LITTLE 0x02 +#define RELOC_STD_BITS_RELATIVE_BIG ((unsigned int) 0x02) +#define RELOC_STD_BITS_RELATIVE_LITTLE ((unsigned int) 0x40) #define RELOC_STD_SIZE (BYTES_IN_WORD + 3 + 1) /* Bytes per relocation entry */ @@ -346,12 +382,12 @@ struct reloc_ext_external { bfd_byte r_addend[BYTES_IN_WORD]; /* datum addend */ }; -#define RELOC_EXT_BITS_EXTERN_BIG 0x80 -#define RELOC_EXT_BITS_EXTERN_LITTLE 0x01 +#define RELOC_EXT_BITS_EXTERN_BIG ((unsigned int) 0x80) +#define RELOC_EXT_BITS_EXTERN_LITTLE ((unsigned int) 0x01) -#define RELOC_EXT_BITS_TYPE_BIG 0x1F +#define RELOC_EXT_BITS_TYPE_BIG ((unsigned int) 0x1F) #define RELOC_EXT_BITS_TYPE_SH_BIG 0 -#define RELOC_EXT_BITS_TYPE_LITTLE 0xF8 +#define RELOC_EXT_BITS_TYPE_LITTLE ((unsigned int) 0xF8) #define RELOC_EXT_BITS_TYPE_SH_LITTLE 3 /* Bytes per relocation entry */ @@ -402,7 +438,13 @@ enum reloc_type RELOC_CONST, RELOC_CONSTH, + /* All the new ones I can think of, for sparc v9 */ + RELOC_64, /* data[0:63] = addend + sv */ + RELOC_DISP64, /* data[0:63] = addend - pc + sv */ + RELOC_WDISP21, /* data[0:20] = (addend + sv - pc)>>2 */ + RELOC_DISP21, /* data[0:20] = addend - pc + sv */ + RELOC_DISP14, /* data[0:13] = addend - pc + sv */ /* Q . What are the other ones, Since this is a clean slate, can we throw away the ones we dont diff --git a/gnu/usr.bin/gdb/gdb/aout/ar.h b/gnu/usr.bin/gdb/gdb/aout/ar.h index cca636d81936..7b5dcdabd106 100644 --- a/gnu/usr.bin/gdb/gdb/aout/ar.h +++ b/gnu/usr.bin/gdb/gdb/aout/ar.h @@ -6,10 +6,14 @@ #ifndef __GNU_AR_H__ #define __GNU_AR_H__ -#define ARMAG "!\n" /* For COFF and a.out archives */ -#define ARMAGB "!\n" /* For b.out archives */ +/* Note that the usual '\n' in magic strings may translate to different + characters, as allowed by ANSI. '\012' has a fixed value, and remains + compatible with existing BSDish archives. */ + +#define ARMAG "!\012" /* For COFF and a.out archives */ +#define ARMAGB "!\012" /* For b.out archives */ #define SARMAG 8 -#define ARFMAG "`\n" +#define ARFMAG "`\012" /* The ar_date field of the armap (__.SYMDEF) member of an archive must be greater than the modified date of the entire file, or diff --git a/gnu/usr.bin/gdb/gdb/aout/stab.def b/gnu/usr.bin/gdb/gdb/aout/stab.def index 9d1da7d6eb8f..ff1981618425 100644 --- a/gnu/usr.bin/gdb/gdb/aout/stab.def +++ b/gnu/usr.bin/gdb/gdb/aout/stab.def @@ -219,11 +219,11 @@ __define_stab (N_LENG, 0xfe, "LENG") | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA | | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT | - | 08 BSS | 0A INDR | 0C FN_SEQ | 0E | - | 09 |EXT | 0B | 0D | 0F | + | 08 BSS | 0A INDR | 0C FN_SEQ | 0E WEAKA | + | 09 |EXT | 0B | 0D WEAKU | 0F WEAKT | - | 10 | 12 COMM | 14 SETA | 16 SETT | - | 11 | 13 | 15 | 17 | + | 10 WEAKD | 12 COMM | 14 SETA | 16 SETT | + | 11 WEAKB | 13 | 15 | 17 | | 18 SETD | 1A SETB | 1C SETV | 1E WARNING| | 19 | 1B | 1D | 1F FN | diff --git a/gnu/usr.bin/gdb/gdb/blockframe.c b/gnu/usr.bin/gdb/gdb/blockframe.c index c7b3fdce26bd..667472b7d518 100644 --- a/gnu/usr.bin/gdb/gdb/blockframe.c +++ b/gnu/usr.bin/gdb/gdb/blockframe.c @@ -28,6 +28,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "value.h" /* for read_register */ #include "target.h" /* for target_has_stack */ #include "inferior.h" /* for read_pc */ +#include "annotate.h" /* Is ADDR inside the startup file? Note that if your machine has a way to detect the bottom of the stack, there is no need @@ -192,6 +193,7 @@ flush_cached_frames () obstack_init (&frame_cache_obstack); current_frame = (struct frame_info *) 0; /* Invalidate cache */ + annotate_frames_invalid (); } /* Flush the frame cache, and start a new one if necessary. */ @@ -389,13 +391,18 @@ get_prev_frame_info (next_frame) Only change here is that create_new_frame would no longer init extra frame info; SETUP_ARBITRARY_FRAME would have to do that. INIT_PREV_FRAME(fromleaf, prev) - Replace INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC. + Replace INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC. This should + also return a flag saying whether to keep the new frame, or + whether to discard it, because on some machines (e.g. mips) it + is really awkward to have FRAME_CHAIN_VALID called *before* + INIT_EXTRA_FRAME_INFO (there is no good way to get information + deduced in FRAME_CHAIN_VALID into the extra fields of the new frame). std_frame_pc(fromleaf, prev) This is the default setting for INIT_PREV_FRAME. It just does what the default INIT_FRAME_PC does. Some machines will call it from INIT_PREV_FRAME (either at the beginning, the end, or in the middle). Some machines won't use it. - kingdon@cygnus.com, 13Apr93. */ + kingdon@cygnus.com, 13Apr93, 31Jan94. */ #ifdef INIT_FRAME_PC_FIRST INIT_FRAME_PC_FIRST (fromleaf, prev); @@ -406,10 +413,25 @@ get_prev_frame_info (next_frame) #endif /* This entry is in the frame queue now, which is good since - FRAME_SAVED_PC may use that queue to figure out it's value + FRAME_SAVED_PC may use that queue to figure out its value (see tm-sparc.h). We want the pc saved in the inferior frame. */ INIT_FRAME_PC(fromleaf, prev); + /* If ->frame and ->pc are unchanged, we are in the process of getting + ourselves into an infinite backtrace. Some architectures check this + in FRAME_CHAIN or thereabouts, but it seems like there is no reason + this can't be an architecture-independent check. */ + if (next_frame != NULL) + { + if (prev->frame == next_frame->frame + && prev->pc == next_frame->pc) + { + next_frame->prev = NULL; + obstack_free (&frame_cache_obstack, prev); + return NULL; + } + } + find_pc_partial_function (prev->pc, &name, (CORE_ADDR *)NULL,(CORE_ADDR *)NULL); if (IN_SIGTRAMP (prev->pc, name)) @@ -726,7 +748,7 @@ find_pc_partial_function (pc, name, address, endaddr) /* See if we're in a transfer table for Sun shared libs. */ - if (msymbol -> type == mst_text) + if (msymbol -> type == mst_text || msymbol -> type == mst_file_text) cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol); else /* It is a transfer table for Sun shared libraries. */ @@ -785,6 +807,29 @@ block_innermost_frame (block) } } +/* Return the full FRAME which corresponds to the given FRAME_ADDR + or NULL if no FRAME on the chain corresponds to FRAME_ADDR. */ + +FRAME +find_frame_addr_in_frame_chain (frame_addr) + FRAME_ADDR frame_addr; +{ + FRAME frame = NULL; + + if (frame_addr == (CORE_ADDR)0) + return NULL; + + while (1) + { + frame = get_prev_frame (frame); + if (frame == NULL) + return NULL; + + if (FRAME_FP (frame) == frame_addr) + return frame; + } +} + #ifdef SIGCONTEXT_PC_OFFSET /* Get saved user PC for sigtramp from sigcontext for BSD style sigtramp. */ diff --git a/gnu/usr.bin/gdb/gdb/breakpoint.c b/gnu/usr.bin/gdb/gdb/breakpoint.c index 69694c016f67..acdeff2798e8 100644 --- a/gnu/usr.bin/gdb/gdb/breakpoint.c +++ b/gnu/usr.bin/gdb/gdb/breakpoint.c @@ -1,5 +1,6 @@ /* Everything about breakpoints, for GDB. - Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -30,10 +31,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ctype.h" #include "command.h" #include "inferior.h" +#include "thread.h" #include "target.h" #include "language.h" #include #include "demangle.h" +#include "annotate.h" /* local function prototypes */ @@ -88,6 +91,9 @@ get_catch_sals PARAMS ((int)); static void watch_command PARAMS ((char *, int)); +static int +can_use_hardware_watchpoint PARAMS ((struct value *)); + static void tbreak_command PARAMS ((char *, int)); @@ -133,9 +139,10 @@ get_number PARAMS ((char **)); static void set_breakpoint_count PARAMS ((int)); +static int +remove_breakpoint PARAMS ((struct breakpoint *)); extern int addressprint; /* Print machine addresses? */ -extern int demangle; /* Print de-mangled symbol names? */ /* Are we executing breakpoint commands? */ static int executing_breakpoint_commands; @@ -151,15 +158,36 @@ static int executing_breakpoint_commands; b? (tmp=b->next, 1): 0; \ b = tmp) +/* By default no support for hardware watchpoints is assumed. */ +#ifndef TARGET_CAN_USE_HARDWARE_WATCHPOINT +#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(TYPE,CNT,OTHERTYPE) 0 +#define target_remove_watchpoint(ADDR,LEN,TYPE) -1 +#define target_insert_watchpoint(ADDR,LEN,TYPE) -1 +#endif + +#ifndef target_insert_hw_breakpoint +#define target_remove_hw_breakpoint(ADDR,SHADOW) -1 +#define target_insert_hw_breakpoint(ADDR,SHADOW) -1 +#endif + +#ifndef target_stopped_data_address +#define target_stopped_data_address() 0 +#endif + +/* True if breakpoint hit counts should be displayed in breakpoint info. */ + +int show_breakpoint_hit_counts = 1; + /* Chain of all breakpoints defined. */ -struct breakpoint *breakpoint_chain; +static struct breakpoint *breakpoint_chain; /* Number of last breakpoint made. */ static int breakpoint_count; /* Set breakpoint count to NUM. */ + static void set_breakpoint_count (num) int num; @@ -169,6 +197,17 @@ set_breakpoint_count (num) value_from_longest (builtin_type_int, (LONGEST) num)); } +/* Used in run_command to zero the hit count when a new run starts. */ + +void +clear_breakpoint_hit_counts () +{ + struct breakpoint *b; + + ALL_BREAKPOINTS (b) + b->hit_count = 0; +} + /* Default address, symtab and line to put a breakpoint at for "break" command with no arg. if default_breakpoint_valid is zero, the other three are @@ -180,9 +219,6 @@ int default_breakpoint_valid; CORE_ADDR default_breakpoint_address; struct symtab *default_breakpoint_symtab; int default_breakpoint_line; - -/* Flag indicating extra verbosity for xgdb. */ -extern int xgdb_verbose; /* *PP is a string denoting a breakpoint. Get the number of the breakpoint. Advance *PP after the string and any trailing whitespace. @@ -206,7 +242,7 @@ get_number (pp) to pass to lookup_internalvar(). */ char *varname; char *start = ++p; - value val; + value_ptr val; while (isalnum (*p) || *p == '_') p++; @@ -322,6 +358,7 @@ End with a line saying just \"end\".\n", bnum); l = read_command_lines (); free_command_lines (&b->commands); b->commands = l; + breakpoints_changed (); return; } error ("No breakpoint number %d.", bnum); @@ -356,7 +393,11 @@ read_memory_nobpt (memaddr, myaddr, len) ALL_BREAKPOINTS (b) { - if (b->type == bp_watchpoint || !b->inserted) + if (b->type == bp_watchpoint + || b->type == bp_hardware_watchpoint + || b->type == bp_read_watchpoint + || b->type == bp_access_watchpoint + || !b->inserted) continue; else if (b->address + memory_breakpoint_size <= memaddr) /* The breakpoint is entirely before the chunk of memory @@ -434,11 +475,17 @@ insert_breakpoints () ALL_BREAKPOINTS (b) if (b->type != bp_watchpoint + && b->type != bp_hardware_watchpoint + && b->type != bp_read_watchpoint + && b->type != bp_access_watchpoint && b->enable != disabled && ! b->inserted && ! b->duplicate) { - val = target_insert_breakpoint(b->address, b->shadow_contents); + if (b->type == bp_hardware_breakpoint) + val = target_insert_hw_breakpoint(b->address, b->shadow_contents); + else + val = target_insert_breakpoint(b->address, b->shadow_contents); if (val) { /* Can't set the breakpoint. */ @@ -449,7 +496,8 @@ insert_breakpoints () b->enable = disabled; if (!disabled_breaks) { - fprintf (stderr, + target_terminal_ours_for_output (); + fprintf_unfiltered (gdb_stderr, "Cannot insert breakpoint %d:\n", b->number); printf_filtered ("Disabling shared library breakpoints:\n"); } @@ -459,9 +507,10 @@ insert_breakpoints () else #endif { - fprintf (stderr, "Cannot insert breakpoint %d:\n", b->number); + target_terminal_ours_for_output (); + fprintf_unfiltered (gdb_stderr, "Cannot insert breakpoint %d:\n", b->number); #ifdef ONE_PROCESS_WRITETEXT - fprintf (stderr, + fprintf_unfiltered (gdb_stderr, "The same program may be running in another process.\n"); #endif memory_error (val, b->address); /* which bombs us out */ @@ -470,38 +519,172 @@ insert_breakpoints () else b->inserted = 1; } + else if ((b->type == bp_hardware_watchpoint || + b->type == bp_read_watchpoint || + b->type == bp_access_watchpoint) + && b->enable == enabled + && ! b->inserted + && ! b->duplicate) + { + FRAME saved_frame; + int saved_level, within_current_scope; + value_ptr mark = value_mark (); + value_ptr v; + + /* Save the current frame and level so we can restore it after + evaluating the watchpoint expression on its own frame. */ + saved_frame = selected_frame; + saved_level = selected_frame_level; + + /* Determine if the watchpoint is within scope. */ + if (b->exp_valid_block == NULL) + within_current_scope = 1; + else + { + FRAME fr = find_frame_addr_in_frame_chain (b->watchpoint_frame); + within_current_scope = (fr != NULL); + if (within_current_scope) + select_frame (fr, -1); + } + + if (within_current_scope) + { + /* Evaluate the expression and cut the chain of values + produced off from the value chain. */ + v = evaluate_expression (b->exp); + value_release_to_mark (mark); + + b->val_chain = v; + b->inserted = 1; + + /* Look at each value on the value chain. */ + for ( ; v; v=v->next) + { + /* If it's a memory location, then we must watch it. */ + if (v->lval == lval_memory) + { + int addr, len, type; + + addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v); + len = TYPE_LENGTH (VALUE_TYPE (v)); + type = 0; + if (b->type == bp_read_watchpoint) + type = 1; + else if (b->type == bp_access_watchpoint) + type = 2; + + val = target_insert_watchpoint (addr, len, type); + if (val == -1) + { + b->inserted = 0; + break; + } + val = 0; + } + } + /* Failure to insert a watchpoint on any memory value in the + value chain brings us here. */ + if (!b->inserted) + warning ("Hardware watchpoint %d: Could not insert watchpoint\n", + b->number); + } + else + { + printf_filtered ("\ +Hardware watchpoint %d deleted because the program has left the block in\n\ +which its expression is valid.\n", b->number); + if (b->related_breakpoint) + delete_breakpoint (b->related_breakpoint); + delete_breakpoint (b); + } + + /* Restore the frame and level. */ + select_frame (saved_frame, saved_level); + } if (disabled_breaks) printf_filtered ("\n"); return val; } + int remove_breakpoints () { register struct breakpoint *b; int val; -#ifdef BREAKPOINT_DEBUG - printf ("Removing breakpoints.\n"); -#endif /* BREAKPOINT_DEBUG */ - ALL_BREAKPOINTS (b) - if (b->type != bp_watchpoint && b->inserted) - { - val = target_remove_breakpoint(b->address, b->shadow_contents); - if (val) - return val; - b->inserted = 0; -#ifdef BREAKPOINT_DEBUG - printf ("Removed breakpoint at %s", - local_hex_string((unsigned long) b->address)); - printf (", shadow %s", - local_hex_string((unsigned long) b->shadow_contents[0])); - printf (", %s.\n", - local_hex_string((unsigned long) b->shadow_contents[1])); -#endif /* BREAKPOINT_DEBUG */ - } + { + if (b->inserted) + { + val = remove_breakpoint (b); + if (val != 0) + return val; + } + } + return 0; +} + +static int +remove_breakpoint (b) + struct breakpoint *b; +{ + int val; + + if (b->type != bp_watchpoint + && b->type != bp_hardware_watchpoint + && b->type != bp_read_watchpoint + && b->type != bp_access_watchpoint) + { + if (b->type == bp_hardware_breakpoint) + val = target_remove_hw_breakpoint(b->address, b->shadow_contents); + else + val = target_remove_breakpoint(b->address, b->shadow_contents); + if (val) + return val; + b->inserted = 0; + } + else if ((b->type == bp_hardware_watchpoint || + b->type == bp_read_watchpoint || + b->type == bp_access_watchpoint) + && b->enable == enabled + && ! b->duplicate) + { + value_ptr v, n; + + b->inserted = 0; + /* Walk down the saved value chain. */ + for (v = b->val_chain; v; v = v->next) + { + /* For each memory reference remove the watchpoint + at that address. */ + if (v->lval == lval_memory) + { + int addr, len; + + addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v); + len = TYPE_LENGTH (VALUE_TYPE (v)); + val = target_remove_watchpoint (addr, len, b->type); + if (val == -1) + b->inserted = 1; + val = 0; + } + } + /* Failure to remove any of the hardware watchpoints comes here. */ + if (b->inserted) + error ("Hardware watchpoint %d: Could not remove watchpoint\n", + b->number); + + /* Free the saved value chain. We will construct a new one + the next time the watchpoint is inserted. */ + for (v = b->val_chain; v; v = n) + { + n = v->next; + value_free (v); + } + b->val_chain = NULL; + } return 0; } @@ -533,6 +716,16 @@ breakpoint_init_inferior () get rid of it. */ if (b->type == bp_call_dummy) delete_breakpoint (b); + + /* Likewise for scope breakpoints. */ + if (b->type == bp_watchpoint_scope) + delete_breakpoint (b); + + /* Likewise for watchpoints on local expressions. */ + if ((b->type == bp_watchpoint || b->type == bp_hardware_watchpoint || + b->type == bp_read_watchpoint || b->type == bp_access_watchpoint) + && b->exp_valid_block != NULL) + delete_breakpoint (b); } } @@ -553,6 +746,37 @@ breakpoint_here_p (pc) return 0; } +/* Return nonzero if FRAME is a dummy frame. We can't use PC_IN_CALL_DUMMY + because figuring out the saved SP would take too much time, at least using + get_saved_register on the 68k. This means that for this function to + work right a port must use the bp_call_dummy breakpoint. */ + +int +frame_in_dummy (frame) + FRAME frame; +{ + struct breakpoint *b; + +#ifdef CALL_DUMMY + ALL_BREAKPOINTS (b) + { + static unsigned LONGEST dummy[] = CALL_DUMMY; + + if (b->type == bp_call_dummy + && b->frame == frame->frame + + /* We need to check the PC as well as the frame on the sparc, + for signals.exp in the testsuite. */ + && (frame->pc + >= (b->address + - sizeof (dummy) / sizeof (LONGEST) * REGISTER_SIZE)) + && frame->pc <= b->address) + return 1; + } +#endif /* CALL_DUMMY */ + return 0; +} + /* breakpoint_match_thread (PC, PID) returns true if the breakpoint at PC is valid for process/thread PID. */ @@ -749,30 +973,49 @@ print_it_normal (bs) which has since been deleted. */ if (bs->breakpoint_at == NULL || (bs->breakpoint_at->type != bp_breakpoint - && bs->breakpoint_at->type != bp_watchpoint)) + && bs->breakpoint_at->type != bp_hardware_breakpoint + && bs->breakpoint_at->type != bp_watchpoint + && bs->breakpoint_at->type != bp_read_watchpoint + && bs->breakpoint_at->type != bp_access_watchpoint + && bs->breakpoint_at->type != bp_hardware_watchpoint)) return 0; - if (bs->breakpoint_at->type == bp_breakpoint) + if (bs->breakpoint_at->type == bp_breakpoint || + bs->breakpoint_at->type == bp_hardware_breakpoint) { /* I think the user probably only wants to see one breakpoint number, not all of them. */ + annotate_breakpoint (bs->breakpoint_at->number); printf_filtered ("\nBreakpoint %d, ", bs->breakpoint_at->number); return 0; } - - if (bs->old_val != NULL) + else if ((bs->old_val != NULL) && + (bs->breakpoint_at->type == bp_watchpoint || + bs->breakpoint_at->type == bp_access_watchpoint || + bs->breakpoint_at->type == bp_hardware_watchpoint)) { - printf_filtered ("\nWatchpoint %d, ", bs->breakpoint_at->number); - print_expression (bs->breakpoint_at->exp, stdout); + annotate_watchpoint (bs->breakpoint_at->number); + mention (bs->breakpoint_at); printf_filtered ("\nOld value = "); - value_print (bs->old_val, stdout, 0, Val_pretty_default); + value_print (bs->old_val, gdb_stdout, 0, Val_pretty_default); printf_filtered ("\nNew value = "); - value_print (bs->breakpoint_at->val, stdout, 0, + value_print (bs->breakpoint_at->val, gdb_stdout, 0, Val_pretty_default); printf_filtered ("\n"); value_free (bs->old_val); bs->old_val = NULL; - return 0; + /* More than one watchpoint may have been triggered. */ + return -1; + } + else if (bs->breakpoint_at->type == bp_access_watchpoint || + bs->breakpoint_at->type == bp_read_watchpoint) + { + mention (bs->breakpoint_at); + printf_filtered ("\nValue = "); + value_print (bs->breakpoint_at->val, gdb_stdout, 0, + Val_pretty_default); + printf_filtered ("\n"); + return -1; } /* We can't deal with it. Maybe another member of the bpstat chain can. */ return -1; @@ -815,7 +1058,10 @@ static int breakpoint_cond_eval (exp) char *exp; { - return !value_true (evaluate_expression ((struct expression *)exp)); + value_ptr mark = value_mark (); + int i = !value_true (evaluate_expression ((struct expression *)exp)); + value_free_to_mark (mark); + return i; } /* Allocate a new bpstat and chain it to the current one. */ @@ -837,145 +1083,39 @@ bpstat_alloc (b, cbs) return bs; } -/* Return the frame which we can use to evaluate the expression - whose valid block is valid_block, or NULL if not in scope. - - This whole concept is probably not the way to do things (it is incredibly - slow being the main reason, not to mention fragile (e.g. the sparc - frame pointer being fetched as 0 bug causes it to stop)). Instead, - introduce a version of "struct frame" which survives over calls to the - inferior, but which is better than FRAME_ADDR in the sense that it lets - us evaluate expressions relative to that frame (on some machines, it - can just be a FRAME_ADDR). Save one of those instead of (or in addition - to) the exp_valid_block, and then use it to evaluate the watchpoint - expression, with no need to do all this backtracing every time. - - Or better yet, what if it just copied the struct frame and its next - frame? Off the top of my head, I would think that would work - because things like (a29k) rsize and msize, or (sparc) bottom just - depend on the frame, and aren't going to be different just because - the inferior has done something. Trying to recalculate them - strikes me as a lot of work, possibly even impossible. Saving the - next frame is needed at least on a29k, where get_saved_register - uses fi->next->saved_msp. For figuring out whether that frame is - still on the stack, I guess this needs to be machine-specific (e.g. - a29k) but I think - - read_fp () INNER_THAN watchpoint_frame->frame - - would generally work. - - Of course the scope of the expression could be less than a whole - function; perhaps if the innermost frame is the one which the - watchpoint is relative to (another machine-specific thing, usually - - FRAMELESS_FUNCTION_INVOCATION (get_current_frame(), fromleaf) - read_fp () == wp_frame->frame - && !fromleaf - - ), *then* it could do a - - contained_in (get_current_block (), wp->exp_valid_block). - - */ - -FRAME -within_scope (valid_block) - struct block *valid_block; -{ - FRAME fr = get_current_frame (); - struct frame_info *fi = get_frame_info (fr); - CORE_ADDR func_start; - - /* If caller_pc_valid is true, we are stepping through - a function prologue, which is bounded by callee_func_start - (inclusive) and callee_prologue_end (exclusive). - caller_pc is the pc of the caller. - - Yes, this is hairy. */ - static int caller_pc_valid = 0; - static CORE_ADDR caller_pc; - static CORE_ADDR callee_func_start; - static CORE_ADDR callee_prologue_end; - - find_pc_partial_function (fi->pc, (PTR)NULL, &func_start, (CORE_ADDR *)NULL); - func_start += FUNCTION_START_OFFSET; - if (fi->pc == func_start) - { - /* We just called a function. The only other case I - can think of where the pc would equal the pc of the - start of a function is a frameless function (i.e. - no prologue) where we branch back to the start - of the function. In that case, SKIP_PROLOGUE won't - find one, and we'll clear caller_pc_valid a few lines - down. */ - caller_pc_valid = 1; - caller_pc = SAVED_PC_AFTER_CALL (fr); - callee_func_start = func_start; - SKIP_PROLOGUE (func_start); - callee_prologue_end = func_start; - } - if (caller_pc_valid) - { - if (fi->pc < callee_func_start - || fi->pc >= callee_prologue_end) - caller_pc_valid = 0; - } - - if (contained_in (block_for_pc (caller_pc_valid - ? caller_pc - : fi->pc), - valid_block)) - { - return fr; - } - fr = get_prev_frame (fr); - - /* If any active frame is in the exp_valid_block, then it's - OK. Note that this might not be the same invocation of - the exp_valid_block that we were watching a little while - ago, or the same one as when the watchpoint was set (e.g. - we are watching a local variable in a recursive function. - When we return from a recursive invocation, then we are - suddenly watching a different instance of the variable). - - At least for now I am going to consider this a feature. */ - for (; fr != NULL; fr = get_prev_frame (fr)) - { - fi = get_frame_info (fr); - if (contained_in (block_for_pc (fi->pc), - valid_block)) - { - return fr; - } - } - return NULL; -} - /* Possible return values for watchpoint_check (this can't be an enum because of check_errors). */ -/* The watchpoint has been disabled. */ -#define WP_DISABLED 1 +/* The watchpoint has been deleted. */ +#define WP_DELETED 1 /* The value has changed. */ #define WP_VALUE_CHANGED 2 /* The value has not changed. */ #define WP_VALUE_NOT_CHANGED 3 /* Check watchpoint condition. */ + static int watchpoint_check (p) char *p; { bpstat bs = (bpstat) p; - FRAME fr; + struct breakpoint *b; + FRAME saved_frame, fr; + int within_current_scope, saved_level; - int within_current_scope; - if (bs->breakpoint_at->exp_valid_block == NULL) + /* Save the current frame and level so we can restore it after + evaluating the watchpoint expression on its own frame. */ + saved_frame = selected_frame; + saved_level = selected_frame_level; + + b = bs->breakpoint_at; + + if (b->exp_valid_block == NULL) within_current_scope = 1; else { - fr = within_scope (bs->breakpoint_at->exp_valid_block); - within_current_scope = fr != NULL; + fr = find_frame_addr_in_frame_chain (b->watchpoint_frame); + within_current_scope = (fr != NULL); if (within_current_scope) /* If we end up stopping, the current frame will get selected in normal_stop. So this call to select_frame won't affect @@ -990,15 +1130,16 @@ watchpoint_check (p) call free_all_values. We can't call free_all_values because we might be in the middle of evaluating a function call. */ - value mark = value_mark (); - value new_val = evaluate_expression (bs->breakpoint_at->exp); - if (!value_equal (bs->breakpoint_at->val, new_val)) + value_ptr mark = value_mark (); + value_ptr new_val = evaluate_expression (bs->breakpoint_at->exp); + if (!value_equal (b->val, new_val)) { release_value (new_val); value_free_to_mark (mark); - bs->old_val = bs->breakpoint_at->val; - bs->breakpoint_at->val = new_val; + bs->old_val = b->val; + b->val = new_val; /* We will stop here */ + select_frame (saved_frame, saved_level); return WP_VALUE_CHANGED; } else @@ -1006,6 +1147,7 @@ watchpoint_check (p) /* Nothing changed, don't do anything. */ value_free_to_mark (mark); /* We won't stop here */ + select_frame (saved_frame, saved_level); return WP_VALUE_NOT_CHANGED; } } @@ -1019,11 +1161,15 @@ watchpoint_check (p) So we can't even detect the first assignment to it and watch after that (since the garbage may or may not equal the first value assigned). */ - bs->breakpoint_at->enable = disabled; printf_filtered ("\ -Watchpoint %d disabled because the program has left the block in\n\ +Watchpoint %d deleted because the program has left the block in\n\ which its expression is valid.\n", bs->breakpoint_at->number); - return WP_DISABLED; + if (b->related_breakpoint) + delete_breakpoint (b->related_breakpoint); + delete_breakpoint (b); + + select_frame (saved_frame, saved_level); + return WP_DELETED; } } @@ -1083,6 +1229,9 @@ bpstat_stop_status (pc, frame_address, not_a_breakpoint) struct bpstat root_bs[1]; /* Pointer to the last thing in the chain currently. */ bpstat bs = root_bs; + static char message1[] = + "Error evaluating expression for watchpoint %d\n"; + char message[sizeof (message1) + 30 /* slop */]; /* Get the address where the breakpoint would have been. */ bp_addr = *pc - DECR_PC_AFTER_BREAK; @@ -1092,29 +1241,44 @@ bpstat_stop_status (pc, frame_address, not_a_breakpoint) if (b->enable == disabled) continue; - if (b->type != bp_watchpoint && b->address != bp_addr) + if (b->type != bp_watchpoint + && b->type != bp_hardware_watchpoint + && b->type != bp_read_watchpoint + && b->type != bp_access_watchpoint + && b->type != bp_hardware_breakpoint + && b->address != bp_addr) continue; - if (b->type != bp_watchpoint && not_a_breakpoint) +#ifndef DECR_PC_AFTER_HW_BREAK +#define DECR_PC_AFTER_HW_BREAK 0 +#endif + if (b->type == bp_hardware_breakpoint + && b->address != (bp_addr - DECR_PC_AFTER_HW_BREAK)) + continue; + + if (b->type != bp_watchpoint + && b->type != bp_hardware_watchpoint + && b->type != bp_read_watchpoint + && b->type != bp_access_watchpoint + && not_a_breakpoint) continue; /* Come here if it's a watchpoint, or if the break address matches */ + ++(b->hit_count); + bs = bpstat_alloc (b, bs); /* Alloc a bpstat to explain stop */ bs->stop = 1; bs->print = 1; - if (b->type == bp_watchpoint) + sprintf (message, message1, b->number); + if (b->type == bp_watchpoint || b->type == bp_hardware_watchpoint) { - static char message1[] = - "Error evaluating expression for watchpoint %d\n"; - char message[sizeof (message1) + 30 /* slop */]; - sprintf (message, message1, b->number); switch (catch_errors (watchpoint_check, (char *) bs, message, RETURN_MASK_ALL)) { - case WP_DISABLED: + case WP_DELETED: /* We've already printed what needs to be printed. */ bs->print_it = print_it_done; /* Stop. */ @@ -1132,14 +1296,62 @@ bpstat_stop_status (pc, frame_address, not_a_breakpoint) /* FALLTHROUGH */ case 0: /* Error from catch_errors. */ - b->enable = disabled; - printf_filtered ("Watchpoint %d disabled.\n", b->number); + printf_filtered ("Watchpoint %d deleted.\n", b->number); + if (b->related_breakpoint) + delete_breakpoint (b->related_breakpoint); + delete_breakpoint (b); /* We've already printed what needs to be printed. */ bs->print_it = print_it_done; + /* Stop. */ break; } } + else if (b->type == bp_read_watchpoint || b->type == bp_access_watchpoint) + { + CORE_ADDR addr; + value_ptr v; + int found = 0; + + addr = target_stopped_data_address(); + if (addr == 0) continue; + for (v = b->val_chain; v; v = v->next) + { + if (v->lval == lval_memory) + { + CORE_ADDR vaddr; + + vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v); + if (addr == vaddr) + found = 1; + } + } + if (found) + switch (catch_errors (watchpoint_check, (char *) bs, message, + RETURN_MASK_ALL)) + { + case WP_DELETED: + /* We've already printed what needs to be printed. */ + bs->print_it = print_it_done; + /* Stop. */ + break; + case WP_VALUE_CHANGED: + case WP_VALUE_NOT_CHANGED: + /* Stop. */ + break; + default: + /* Can't happen. */ + case 0: + /* Error from catch_errors. */ + printf_filtered ("Watchpoint %d deleted.\n", b->number); + if (b->related_breakpoint) + delete_breakpoint (b->related_breakpoint); + delete_breakpoint (b); + /* We've already printed what needs to be printed. */ + bs->print_it = print_it_done; + break; + } + } #if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS) else real_breakpoint = 1; @@ -1208,6 +1420,17 @@ bpstat_stop_status (pc, frame_address, not_a_breakpoint) } } #endif /* DECR_PC_AFTER_BREAK != 0. */ + + /* The value of a hardware watchpoint hasn't changed, but the + intermediate memory locations we are watching may have. */ + if (bs && ! bs->stop && + (bs->breakpoint_at->type == bp_hardware_watchpoint || + bs->breakpoint_at->type == bp_read_watchpoint || + bs->breakpoint_at->type == bp_access_watchpoint)) + { + remove_breakpoints (); + insert_breakpoints (); + } return bs; } @@ -1242,6 +1465,12 @@ bpstat_what (bs) /* We hit the longjmp_resume breakpoint. */ long_resume, + /* We hit the step_resume breakpoint. */ + step_resume, + + /* We hit the through_sigtramp breakpoint. */ + through_sig, + /* This is just used to count how many enums there are. */ class_last }; @@ -1256,6 +1485,9 @@ bpstat_what (bs) #define setlr BPSTAT_WHAT_SET_LONGJMP_RESUME #define clrlr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME #define clrlrs BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE +#define sr BPSTAT_WHAT_STEP_RESUME +#define ts BPSTAT_WHAT_THROUGH_SIGTRAMP + /* "Can't happen." Might want to print an error message. abort() is not out of the question, but chances are GDB is just a bit confused, not unusable. */ @@ -1268,20 +1500,29 @@ bpstat_what (bs) (BPSTAT_WHAT_SINGLE type stuff) is handled in proceed() without reference to how we stopped. We retain separate wp_silent and bp_silent codes in case we want to change that someday. */ + + /* step_resume entries: a step resume breakpoint overrides another + breakpoint of signal handling (see comment in wait_for_inferior + at first IN_SIGTRAMP where we set the step_resume breakpoint). */ + /* We handle the through_sigtramp_breakpoint the same way; having both + one of those and a step_resume_breakpoint is probably very rare (?). */ + static const enum bpstat_what_main_action table[(int)class_last][(int)BPSTAT_WHAT_LAST] = { /* old action */ - /* keep_c stop_s stop_n single setlr clrlr clrlrs */ - -/*no_effect*/ {keep_c, stop_s, stop_n, single, setlr , clrlr , clrlrs}, -/*wp_silent*/ {stop_s, stop_s, stop_n, stop_s, stop_s, stop_s, stop_s}, -/*wp_noisy*/ {stop_n, stop_n, stop_n, stop_n, stop_n, stop_n, stop_n}, -/*bp_nostop*/ {single, stop_s, stop_n, single, setlr , clrlrs, clrlrs}, -/*bp_silent*/ {stop_s, stop_s, stop_n, stop_s, stop_s, stop_s, stop_s}, -/*bp_noisy*/ {stop_n, stop_n, stop_n, stop_n, stop_n, stop_n, stop_n}, -/*long_jump*/ {setlr , stop_s, stop_n, setlr , err , err , err }, -/*long_resume*/ {clrlr , stop_s, stop_n, clrlrs, err , err , err } + /* keep_c stop_s stop_n single setlr clrlr clrlrs sr ts + */ +/*no_effect*/ {keep_c,stop_s,stop_n,single, setlr , clrlr , clrlrs, sr, ts}, +/*wp_silent*/ {stop_s,stop_s,stop_n,stop_s, stop_s, stop_s, stop_s, sr, ts}, +/*wp_noisy*/ {stop_n,stop_n,stop_n,stop_n, stop_n, stop_n, stop_n, sr, ts}, +/*bp_nostop*/ {single,stop_s,stop_n,single, setlr , clrlrs, clrlrs, sr, ts}, +/*bp_silent*/ {stop_s,stop_s,stop_n,stop_s, stop_s, stop_s, stop_s, sr, ts}, +/*bp_noisy*/ {stop_n,stop_n,stop_n,stop_n, stop_n, stop_n, stop_n, sr, ts}, +/*long_jump*/ {setlr ,stop_s,stop_n,setlr , err , err , err , sr, ts}, +/*long_resume*/ {clrlr ,stop_s,stop_n,clrlrs, err , err , err , sr, ts}, +/*step_resume*/ {sr ,sr ,sr ,sr , sr , sr , sr , sr, ts}, +/*through_sig*/ {ts ,ts ,ts ,ts , ts , ts , ts , ts, ts} }; #undef keep_c #undef stop_s @@ -1291,11 +1532,12 @@ bpstat_what (bs) #undef clrlr #undef clrlrs #undef err +#undef sr +#undef ts enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING; struct bpstat_what retval; retval.call_dummy = 0; - retval.step_resume = 0; for (; bs != NULL; bs = bs->next) { enum class bs_class = no_effect; @@ -1306,6 +1548,7 @@ bpstat_what (bs) switch (bs->breakpoint_at->type) { case bp_breakpoint: + case bp_hardware_breakpoint: case bp_until: case bp_finish: if (bs->stop) @@ -1319,6 +1562,9 @@ bpstat_what (bs) bs_class = bp_nostop; break; case bp_watchpoint: + case bp_hardware_watchpoint: + case bp_read_watchpoint: + case bp_access_watchpoint: if (bs->stop) { if (bs->print) @@ -1338,24 +1584,21 @@ bpstat_what (bs) bs_class = long_resume; break; case bp_step_resume: -#if 0 - /* Need to temporarily disable this until we can fix the bug - with nexting over a breakpoint with ->stop clear causing - an infinite loop. For now, treat the breakpoint as having - been hit even if the frame is wrong. */ if (bs->stop) { -#endif - retval.step_resume = 1; - /* We don't handle this via the main_action. */ - bs_class = no_effect; -#if 0 + bs_class = step_resume; } else /* It is for the wrong frame. */ bs_class = bp_nostop; -#endif break; + case bp_through_sigtramp: + bs_class = through_sig; + break; + case bp_watchpoint_scope: + bs_class = bp_nostop; + break; + case bp_call_dummy: /* Make sure the action is stop (silent or noisy), so infrun.c pops the dummy frame. */ @@ -1397,9 +1640,12 @@ breakpoint_1 (bnum, allflag) register struct symbol *sym; CORE_ADDR last_addr = (CORE_ADDR)-1; int found_a_breakpoint = 0; - static char *bptypes[] = {"breakpoint", "until", "finish", "watchpoint", - "longjmp", "longjmp resume", "step resume", - "call dummy" }; + static char *bptypes[] = {"breakpoint", "hw breakpoint", + "until", "finish", "watchpoint", + "hw watchpoint", "read watchpoint", + "acc watchpoint", "longjmp", + "longjmp resume", "step resume", + "watchpoint scope", "call dummy" }; static char *bpdisps[] = {"del", "dis", "keep"}; static char bpenables[] = "ny"; char wrap_indent[80]; @@ -1411,36 +1657,84 @@ breakpoint_1 (bnum, allflag) /* We only print out user settable breakpoints unless the allflag is set. */ if (!allflag && b->type != bp_breakpoint - && b->type != bp_watchpoint) + && b->type != bp_hardware_breakpoint + && b->type != bp_watchpoint + && b->type != bp_read_watchpoint + && b->type != bp_access_watchpoint + && b->type != bp_hardware_watchpoint) continue; if (!found_a_breakpoint++) - printf_filtered ("Num Type Disp Enb %sWhat\n", - addressprint ? "Address " : ""); + { + annotate_breakpoints_headers (); + + annotate_field (0); + printf_filtered ("Num "); + annotate_field (1); + printf_filtered ("Type "); + annotate_field (2); + printf_filtered ("Disp "); + annotate_field (3); + printf_filtered ("Enb "); + if (addressprint) + { + annotate_field (4); + printf_filtered ("Address "); + } + annotate_field (5); + printf_filtered ("What\n"); + + annotate_breakpoints_table (); + } + + annotate_record (); + annotate_field (0); + printf_filtered ("%-3d ", b->number); + annotate_field (1); + printf_filtered ("%-14s ", bptypes[(int)b->type]); + annotate_field (2); + printf_filtered ("%-4s ", bpdisps[(int)b->disposition]); + annotate_field (3); + printf_filtered ("%-3c ", bpenables[(int)b->enable]); - printf_filtered ("%-3d %-14s %-4s %-3c ", - b->number, - bptypes[(int)b->type], - bpdisps[(int)b->disposition], - bpenables[(int)b->enable]); strcpy (wrap_indent, " "); if (addressprint) strcat (wrap_indent, " "); switch (b->type) { case bp_watchpoint: - print_expression (b->exp, stdout); + case bp_hardware_watchpoint: + case bp_read_watchpoint: + case bp_access_watchpoint: + /* Field 4, the address, is omitted (which makes the columns + not line up too nicely with the headers, but the effect + is relatively readable). */ + annotate_field (5); + print_expression (b->exp, gdb_stdout); break; case bp_breakpoint: + case bp_hardware_breakpoint: case bp_until: case bp_finish: case bp_longjmp: case bp_longjmp_resume: case bp_step_resume: + case bp_through_sigtramp: + case bp_watchpoint_scope: case bp_call_dummy: if (addressprint) - printf_filtered ("%s ", local_hex_string_custom ((unsigned long) b->address, "08l")); + { + annotate_field (4); + /* FIXME-32x64: need a print_address_numeric with + field width */ + printf_filtered + ("%s ", + local_hex_string_custom + ((unsigned long) b->address, "08l")); + } + + annotate_field (5); last_addr = b->address; if (b->source_file) @@ -1448,40 +1742,66 @@ breakpoint_1 (bnum, allflag) sym = find_pc_function (b->address); if (sym) { - fputs_filtered ("in ", stdout); - fputs_filtered (SYMBOL_SOURCE_NAME (sym), stdout); + fputs_filtered ("in ", gdb_stdout); + fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout); wrap_here (wrap_indent); - fputs_filtered (" at ", stdout); + fputs_filtered (" at ", gdb_stdout); } - fputs_filtered (b->source_file, stdout); + fputs_filtered (b->source_file, gdb_stdout); printf_filtered (":%d", b->line_number); } else - print_address_symbolic (b->address, stdout, demangle, " "); + print_address_symbolic (b->address, gdb_stdout, demangle, " "); break; } printf_filtered ("\n"); if (b->frame) - printf_filtered ("\tstop only in stack frame at %s\n", - local_hex_string((unsigned long) b->frame)); - if (b->cond) { - printf_filtered ("\tstop only if "); - print_expression (b->cond, stdout); + annotate_field (6); + + printf_filtered ("\tstop only in stack frame at "); + print_address_numeric (b->frame, 1, gdb_stdout); printf_filtered ("\n"); } + + if (b->cond) + { + annotate_field (7); + + printf_filtered ("\tstop only if "); + print_expression (b->cond, gdb_stdout); + printf_filtered ("\n"); + } + + if (show_breakpoint_hit_counts && b->hit_count) + { + /* FIXME should make an annotation for this */ + + printf_filtered ("\tbreakpoint already hit %d times\n", + b->hit_count); + } + if (b->ignore_count) - printf_filtered ("\tignore next %d hits\n", b->ignore_count); + { + annotate_field (8); + + printf_filtered ("\tignore next %d hits\n", b->ignore_count); + } + if ((l = b->commands)) - while (l) - { - fputs_filtered ("\t", stdout); - fputs_filtered (l->line, stdout); - fputs_filtered ("\n", stdout); - l = l->next; - } + { + annotate_field (9); + + while (l) + { + fputs_filtered ("\t", gdb_stdout); + fputs_filtered (l->line, gdb_stdout); + fputs_filtered ("\n", gdb_stdout); + l = l->next; + } + } } if (!found_a_breakpoint) @@ -1496,6 +1816,8 @@ breakpoint_1 (bnum, allflag) that a comparison of an unsigned with -1 is always false. */ if (last_addr != (CORE_ADDR)-1) set_next_address (last_addr); + + annotate_breakpoints_table_end (); } /* ARGSUSED */ @@ -1544,17 +1866,20 @@ describe_other_breakpoints (pc) others++; if (others > 0) { - printf ("Note: breakpoint%s ", (others > 1) ? "s" : ""); + printf_filtered ("Note: breakpoint%s ", (others > 1) ? "s" : ""); ALL_BREAKPOINTS (b) if (b->address == pc) { others--; - printf ("%d%s%s ", - b->number, - (b->enable == disabled) ? " (disabled)" : "", - (others > 1) ? "," : ((others == 1) ? " and" : "")); + printf_filtered + ("%d%s%s ", + b->number, + (b->enable == disabled) ? " (disabled)" : "", + (others > 1) ? "," : ((others == 1) ? " and" : "")); } - printf ("also set at pc %s.\n", local_hex_string((unsigned long) pc)); + printf_filtered ("also set at pc "); + print_address_numeric (pc, 1, gdb_stdout); + printf_filtered (".\n"); } } @@ -1644,6 +1969,7 @@ set_raw_breakpoint (sal) } check_duplicates (sal.pc); + breakpoints_changed (); return b; } @@ -1715,6 +2041,45 @@ disable_longjmp_breakpoint() } } +int +hw_breakpoint_used_count() +{ + register struct breakpoint *b; + int i = 0; + + ALL_BREAKPOINTS (b) + { + if (b->type == bp_hardware_breakpoint && b->enable == enabled) + i++; + } + + return i; +} + +int +hw_watchpoint_used_count(type, other_type_used) + enum bptype type; + int *other_type_used; +{ + register struct breakpoint *b; + int i = 0; + + *other_type_used = 0; + ALL_BREAKPOINTS (b) + { + if (b->enable == enabled) + { + if (b->type == type) i++; + else if ((b->type == bp_hardware_watchpoint || + b->type == bp_read_watchpoint || + b->type == bp_access_watchpoint) + && b->enable == enabled) + *other_type_used = 1; + } + } + return i; +} + /* Call this after hitting the longjmp() breakpoint. Use this to set a new breakpoint at the target of the jmp_buf. @@ -1777,30 +2142,60 @@ clear_momentary_breakpoints () #endif /* Tell the user we have just set a breakpoint B. */ + static void mention (b) struct breakpoint *b; { + int say_where = 0; + switch (b->type) { case bp_watchpoint: printf_filtered ("Watchpoint %d: ", b->number); - print_expression (b->exp, stdout); + print_expression (b->exp, gdb_stdout); + break; + case bp_hardware_watchpoint: + printf_filtered ("Hardware watchpoint %d: ", b->number); + print_expression (b->exp, gdb_stdout); + break; + case bp_read_watchpoint: + printf_filtered ("Hardware read watchpoint %d: ", b->number); + print_expression (b->exp, gdb_stdout); + break; + case bp_access_watchpoint: + printf_filtered ("Hardware access(read/write) watchpoint %d: ",b->number); + print_expression (b->exp, gdb_stdout); break; case bp_breakpoint: - printf_filtered ("Breakpoint %d at %s", b->number, - local_hex_string((unsigned long) b->address)); - if (b->source_file) - printf_filtered (": file %s, line %d.", - b->source_file, b->line_number); + printf_filtered ("Breakpoint %d", b->number); + say_where = 1; + break; + case bp_hardware_breakpoint: + printf_filtered ("Hardware assisted breakpoint %d", b->number); + say_where = 1; break; case bp_until: case bp_finish: case bp_longjmp: case bp_longjmp_resume: case bp_step_resume: + case bp_through_sigtramp: + case bp_call_dummy: + case bp_watchpoint_scope: break; } + if (say_where) + { + if (addressprint || b->source_file == NULL) + { + printf_filtered (" at "); + print_address_numeric (b->address, 1, gdb_stdout); + } + if (b->source_file) + printf_filtered (": file %s, line %d.", + b->source_file, b->line_number); + } printf_filtered ("\n"); } @@ -1843,13 +2238,15 @@ set_breakpoint (s, line, tempflag, addr_string) #endif /* 0 */ /* Set a breakpoint according to ARG (function, linenum or *address) - and make it temporary if TEMPFLAG is nonzero. */ + flag: first bit : 0 non-temporary, 1 temporary. + second bit : 0 normal breakpoint, 1 hardware breakpoint. */ static void -break_command_1 (arg, tempflag, from_tty) +break_command_1 (arg, flag, from_tty) char *arg; - int tempflag, from_tty; + int flag, from_tty; { + int tempflag, hardwareflag; struct symtabs_and_lines sals; struct symtab_and_line sal; register struct expression *cond = 0; @@ -1868,6 +2265,9 @@ break_command_1 (arg, tempflag, from_tty) int i; int thread; + hardwareflag = flag & 2; + tempflag = flag & 1; + sals.sals = NULL; sals.nelts = 0; @@ -1975,6 +2375,18 @@ break_command_1 (arg, tempflag, from_tty) error ("Junk at end of arguments."); } } + if (hardwareflag) + { + int i, target_resources_ok; + + i = hw_breakpoint_used_count (); + target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT ( + bp_hardware_breakpoint, i + sals.nelts, 0); + if (target_resources_ok == 0) + error ("No hardware breakpoint support in the target."); + else if (target_resources_ok < 0) + error ("Hardware breakpoints used exceeds limit."); + } /* Remove the canonical strings from the cleanup, they are needed below. */ if (canonical != (char **)NULL) @@ -1991,7 +2403,7 @@ break_command_1 (arg, tempflag, from_tty) b = set_raw_breakpoint (sal); set_breakpoint_count (breakpoint_count + 1); b->number = breakpoint_count; - b->type = bp_breakpoint; + b->type = hardwareflag ? bp_hardware_breakpoint : bp_breakpoint; b->cond = cond; b->thread = thread; @@ -2012,8 +2424,8 @@ break_command_1 (arg, tempflag, from_tty) if (sals.nelts > 1) { - printf ("Multiple breakpoints were set.\n"); - printf ("Use the \"delete\" command to delete unwanted breakpoints.\n"); + printf_filtered ("Multiple breakpoints were set.\n"); + printf_filtered ("Use the \"delete\" command to delete unwanted breakpoints.\n"); } do_cleanups (old_chain); } @@ -2036,6 +2448,8 @@ resolve_sal_pc (sal) } } +#define BP_TEMPFLAG 1 +#define BP_HARDWAREFLAG 2 void break_command (arg, from_tty) char *arg; @@ -2049,20 +2463,50 @@ tbreak_command (arg, from_tty) char *arg; int from_tty; { - break_command_1 (arg, 1, from_tty); + break_command_1 (arg, BP_TEMPFLAG, from_tty); +} + +static void +hbreak_command (arg, from_tty) + char *arg; + int from_tty; +{ + break_command_1 (arg, BP_HARDWAREFLAG, from_tty); +} + +static void +thbreak_command (arg, from_tty) + char *arg; + int from_tty; +{ + break_command_1 (arg, (BP_TEMPFLAG | BP_HARDWAREFLAG), from_tty); } /* ARGSUSED */ +/* accessflag: 0: watch write, 1: watch read, 2: watch access(read or write) +*/ static void -watch_command (arg, from_tty) +watch_command_1 (arg, accessflag, from_tty) char *arg; + int accessflag; int from_tty; { struct breakpoint *b; struct symtab_and_line sal; struct expression *exp; struct block *exp_valid_block; - struct value *val; + struct value *val, *mark; + FRAME frame, prev_frame; + char *exp_start = NULL; + char *exp_end = NULL; + char *tok, *end_tok; + int toklen; + char *cond_start = NULL; + char *cond_end = NULL; + struct expression *cond = NULL; + int i, other_type_used, target_resources_ok; + enum bptype bp_type; + int mem_cnt = 0; sal.pc = 0; sal.symtab = NULL; @@ -2070,27 +2514,170 @@ watch_command (arg, from_tty) /* Parse arguments. */ innermost_block = NULL; - exp = parse_expression (arg); + exp_start = arg; + exp = parse_exp_1 (&arg, 0, 0); + exp_end = arg; exp_valid_block = innermost_block; + mark = value_mark (); val = evaluate_expression (exp); release_value (val); if (VALUE_LAZY (val)) value_fetch_lazy (val); + tok = arg; + while (*tok == ' ' || *tok == '\t') + tok++; + end_tok = tok; + + while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000') + end_tok++; + + toklen = end_tok - tok; + if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) + { + tok = cond_start = end_tok + 1; + cond = parse_exp_1 (&tok, 0, 0); + cond_end = tok; + } + if (*tok) + error("Junk at end of command."); + + if (accessflag == 1) bp_type = bp_read_watchpoint; + else if (accessflag == 2) bp_type = bp_access_watchpoint; + else bp_type = bp_hardware_watchpoint; + + mem_cnt = can_use_hardware_watchpoint (val); + if (mem_cnt == 0 && bp_type != bp_hardware_watchpoint) + error ("Expression cannot be implemented with read/access watchpoint."); + if (mem_cnt != 0) { + i = hw_watchpoint_used_count (bp_type, &other_type_used); + target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT( + bp_type, i + mem_cnt, other_type_used); + if (target_resources_ok == 0 && bp_type != bp_hardware_watchpoint) + error ("Target does not have this type of hardware watchpoint support."); + if (target_resources_ok < 0 && bp_type != bp_hardware_watchpoint) + error ("Target resources have been allocated for other types of watchpoints."); + } + /* Now set up the breakpoint. */ b = set_raw_breakpoint (sal); set_breakpoint_count (breakpoint_count + 1); b->number = breakpoint_count; - b->type = bp_watchpoint; b->disposition = donttouch; b->exp = exp; b->exp_valid_block = exp_valid_block; + b->exp_string = savestring (exp_start, exp_end - exp_start); b->val = val; - b->cond = 0; - b->cond_string = NULL; - b->exp_string = savestring (arg, strlen (arg)); + b->cond = cond; + if (cond_start) + b->cond_string = savestring (cond_start, cond_end - cond_start); + else + b->cond_string = 0; + + frame = block_innermost_frame (exp_valid_block); + if (frame) + { + prev_frame = get_prev_frame (frame); + b->watchpoint_frame = FRAME_FP (frame); + } + else + b->watchpoint_frame = (CORE_ADDR)0; + + if (mem_cnt && target_resources_ok > 0) + b->type = bp_type; + else + b->type = bp_watchpoint; + + /* If the expression is "local", then set up a "watchpoint scope" + breakpoint at the point where we've left the scope of the watchpoint + expression. */ + if (innermost_block) + { + struct breakpoint *scope_breakpoint; + struct symtab_and_line scope_sal; + + if (prev_frame) + { + scope_sal.pc = get_frame_pc (prev_frame); + scope_sal.symtab = NULL; + scope_sal.line = 0; + + scope_breakpoint = set_raw_breakpoint (scope_sal); + set_breakpoint_count (breakpoint_count + 1); + scope_breakpoint->number = breakpoint_count; + + scope_breakpoint->type = bp_watchpoint_scope; + scope_breakpoint->enable = enabled; + + /* Automatically delete the breakpoint when it hits. */ + scope_breakpoint->disposition = delete; + + /* Only break in the proper frame (help with recursion). */ + scope_breakpoint->frame = prev_frame->frame; + + /* Set the address at which we will stop. */ + scope_breakpoint->address = get_frame_pc (prev_frame); + + /* The scope breakpoint is related to the watchpoint. We + will need to act on them together. */ + b->related_breakpoint = scope_breakpoint; + } + } + value_free_to_mark (mark); mention (b); } + +/* Return count of locations need to be watched and can be handled + in hardware. If the watchpoint can not be handled + in hardware return zero. */ + +static int +can_use_hardware_watchpoint (v) + struct value *v; +{ + int found_memory_cnt = 0; + + /* Make sure all the intermediate values are in memory. Also make sure + we found at least one memory expression. Guards against watch 0x12345, + which is meaningless, but could cause errors if one tries to insert a + hardware watchpoint for the constant expression. */ + for ( ; v; v = v->next) + { + if (v->lval == lval_memory) + { + if (TYPE_LENGTH (VALUE_TYPE (v)) <= REGISTER_SIZE) + found_memory_cnt++; + } + else if (v->lval != not_lval && v->modifiable == 0) + return 0; + } + + /* The expression itself looks suitable for using a hardware + watchpoint, but give the target machine a chance to reject it. */ + return found_memory_cnt; +} + +static void watch_command (arg, from_tty) + char *arg; + int from_tty; +{ + watch_command_1 (arg, 0, from_tty); +} + +static void rwatch_command (arg, from_tty) + char *arg; + int from_tty; +{ + watch_command_1 (arg, 1, from_tty); +} + +static void awatch_command (arg, from_tty) + char *arg; + int from_tty; +{ + watch_command_1 (arg, 2, from_tty); +} + /* * Helper routine for the until_command routine in infcmd.c. Here @@ -2147,7 +2734,7 @@ until_break_command (arg, from_tty) make_cleanup(delete_breakpoint, breakpoint); } - proceed (-1, -1, 0); + proceed (-1, TARGET_SIGNAL_DEFAULT, 0); do_cleanups(old_chain); } @@ -2234,7 +2821,7 @@ map_catch_names (args, function) goto win; } #endif - printf ("No catch clause for exception %s.\n", p); + printf_unfiltered ("No catch clause for exception %s.\n", p); #if 0 win: #endif @@ -2440,8 +3027,8 @@ catch_command_1 (arg, tempflag, from_tty) if (sals.nelts > 1) { - printf ("Multiple breakpoints were set.\n"); - printf ("Use the \"delete\" command to delete unwanted breakpoints.\n"); + printf_unfiltered ("Multiple breakpoints were set.\n"); + printf_unfiltered ("Use the \"delete\" command to delete unwanted breakpoints.\n"); } free ((PTR)sals.sals); } @@ -2533,6 +3120,9 @@ clear_command (arg, from_tty) ALL_BREAKPOINTS (b) while (b->next && b->next->type != bp_watchpoint + && b->next->type != bp_hardware_watchpoint + && b->next->type != bp_read_watchpoint + && b->next->type != bp_access_watchpoint && (sal.pc ? b->next->address == sal.pc : (b->next->source_file != NULL @@ -2555,15 +3145,16 @@ clear_command (arg, from_tty) } if (found->next) from_tty = 1; /* Always report if deleted more than one */ - if (from_tty) printf ("Deleted breakpoint%s ", found->next ? "s" : ""); + if (from_tty) printf_unfiltered ("Deleted breakpoint%s ", found->next ? "s" : ""); + breakpoints_changed (); while (found) { - if (from_tty) printf ("%d ", found->number); + if (from_tty) printf_unfiltered ("%d ", found->number); b1 = found->next; delete_breakpoint (found); found = b1; } - if (from_tty) putchar ('\n'); + if (from_tty) putchar_unfiltered ('\n'); } free ((PTR)sals.sals); } @@ -2591,8 +3182,8 @@ delete_breakpoint (bpt) register bpstat bs; if (bpt->inserted) - target_remove_breakpoint(bpt->address, bpt->shadow_contents); - + remove_breakpoint (bpt); + if (breakpoint_chain == bpt) breakpoint_chain = bpt->next; @@ -2606,7 +3197,10 @@ delete_breakpoint (bpt) check_duplicates (bpt->address); /* If this breakpoint was inserted, and there is another breakpoint at the same address, we need to insert the other breakpoint. */ - if (bpt->inserted) + if (bpt->inserted + && bpt->type != bp_hardware_watchpoint + && bpt->type != bp_read_watchpoint + && bpt->type != bp_access_watchpoint) { ALL_BREAKPOINTS (b) if (b->address == bpt->address @@ -2617,7 +3211,8 @@ delete_breakpoint (bpt) val = target_insert_breakpoint (b->address, b->shadow_contents); if (val != 0) { - fprintf (stderr, "Cannot insert breakpoint %d:\n", b->number); + target_terminal_ours_for_output (); + fprintf_unfiltered (gdb_stderr, "Cannot insert breakpoint %d:\n", b->number); memory_error (val, b->address); /* which bombs us out */ } else @@ -2637,11 +3232,11 @@ delete_breakpoint (bpt) if (bpt->source_file != NULL) free (bpt->source_file); - if (xgdb_verbose && bpt->type == bp_breakpoint) - printf ("breakpoint #%d deleted\n", bpt->number); + breakpoints_changed (); /* Be sure no bpstat's are pointing at it after it's been freed. */ - /* FIXME, how can we find all bpstat's? We just check stop_bpstat for now. */ + /* FIXME, how can we find all bpstat's? + We just check stop_bpstat for now. */ for (bs = stop_bpstat; bs; bs = bs->next) if (bs->breakpoint_at == bpt) bs->breakpoint_at = NULL; @@ -2678,6 +3273,7 @@ breakpoint_re_set_one (bint) char *bint; { struct breakpoint *b = (struct breakpoint *)bint; /* get past catch_errs */ + struct value *mark; int i; struct symtabs_and_lines sals; char *s; @@ -2686,6 +3282,7 @@ breakpoint_re_set_one (bint) switch (b->type) { case bp_breakpoint: + case bp_hardware_breakpoint: if (b->addr_string == NULL) { /* Anything without a string can't be re-set. */ @@ -2741,6 +3338,10 @@ breakpoint_re_set_one (bint) check_duplicates (b->address); mention (b); + + /* Might be better to do this just once per breakpoint_re_set, + rather than once for every breakpoint. */ + breakpoints_changed (); } b->enable = save_enable; /* Restore it, this worked. */ } @@ -2748,6 +3349,9 @@ breakpoint_re_set_one (bint) break; case bp_watchpoint: + case bp_hardware_watchpoint: + case bp_read_watchpoint: + case bp_access_watchpoint: innermost_block = NULL; /* The issue arises of what context to evaluate this in. The same one as when it was set, but what does that mean when symbols have @@ -2759,6 +3363,7 @@ breakpoint_re_set_one (bint) /* So for now, just use a global context. */ b->exp = parse_expression (b->exp_string); b->exp_valid_block = innermost_block; + mark = value_mark (); b->val = evaluate_expression (b->exp); release_value (b->val); if (VALUE_LAZY (b->val)) @@ -2771,6 +3376,7 @@ breakpoint_re_set_one (bint) } if (b->enable == enabled) mention (b); + value_free_to_mark (mark); break; default: @@ -2780,6 +3386,7 @@ breakpoint_re_set_one (bint) case bp_finish: case bp_longjmp: case bp_longjmp_resume: + case bp_watchpoint_scope: case bp_call_dummy: delete_breakpoint (b); break; @@ -2844,6 +3451,7 @@ set_ignore_count (bptnum, count, from_tty) else printf_filtered ("Will ignore next %d crossings of breakpoint %d.", count, bptnum); + breakpoints_changed (); return; } @@ -2882,6 +3490,7 @@ ignore_command (args, from_tty) longest_to_int (value_as_long (parse_and_eval (p))), from_tty); printf_filtered ("\n"); + breakpoints_changed (); } /* Call FUNCTION on each of the breakpoints @@ -2909,10 +3518,13 @@ map_breakpoint_numbers (args, function) ALL_BREAKPOINTS (b) if (b->number == num) { + struct breakpoint *related_breakpoint = b->related_breakpoint; function (b); + if (related_breakpoint) + function (related_breakpoint); goto win; } - printf ("No breakpoint number %d.\n", num); + printf_unfiltered ("No breakpoint number %d.\n", num); win: p = p1; } @@ -2924,18 +3536,30 @@ enable_breakpoint (bpt) { FRAME save_selected_frame = NULL; int save_selected_frame_level = -1; + int target_resources_ok, other_type_used; + struct value *mark; + if (bpt->type == bp_hardware_breakpoint) + { + int i; + i = hw_breakpoint_used_count(); + target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT( + bp_hardware_breakpoint, i+1, 0); + if (target_resources_ok == 0) + error ("No hardware breakpoint support in the target."); + else if (target_resources_ok < 0) + error ("Hardware breakpoints used exceeds limit."); + } bpt->enable = enabled; - - if (xgdb_verbose && bpt->type == bp_breakpoint) - printf ("breakpoint #%d enabled\n", bpt->number); - + breakpoints_changed (); check_duplicates (bpt->address); - if (bpt->type == bp_watchpoint) + + if (bpt->type == bp_watchpoint || bpt->type == bp_hardware_watchpoint || + bpt->type == bp_read_watchpoint || bpt->type == bp_access_watchpoint) { if (bpt->exp_valid_block != NULL) { - FRAME fr = within_scope (bpt->exp_valid_block); + FRAME fr = find_frame_addr_in_frame_chain (bpt->watchpoint_frame); if (fr == NULL) { printf_filtered ("\ @@ -2944,20 +3568,44 @@ is valid is not currently in scope.\n", bpt->number); bpt->enable = disabled; return; } + save_selected_frame = selected_frame; save_selected_frame_level = selected_frame_level; select_frame (fr, -1); } value_free (bpt->val); - + mark = value_mark (); bpt->val = evaluate_expression (bpt->exp); release_value (bpt->val); if (VALUE_LAZY (bpt->val)) value_fetch_lazy (bpt->val); + if (bpt->type == bp_hardware_watchpoint || + bpt->type == bp_read_watchpoint || + bpt->type == bp_access_watchpoint) + { + int i = hw_watchpoint_used_count (bpt->type, &other_type_used); + int mem_cnt = can_use_hardware_watchpoint (bpt->val); + + target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT( + bpt->type, i + mem_cnt, other_type_used); + /* we can consider of type is bp_hardware_watchpoint, convert to + bp_watchpoint in the following condition */ + if (target_resources_ok < 0) + { + printf_filtered("\ +Cannot enable watchpoint %d because target watch resources\n\ +have been allocated for other watchpoints.\n", bpt->number); + bpt->enable = disabled; + value_free_to_mark (mark); + return; + } + } + if (save_selected_frame_level >= 0) select_frame (save_selected_frame, save_selected_frame_level); + value_free_to_mark (mark); } } @@ -2973,7 +3621,11 @@ enable_command (args, from_tty) switch (bpt->type) { case bp_breakpoint: + case bp_hardware_breakpoint: case bp_watchpoint: + case bp_hardware_watchpoint: + case bp_read_watchpoint: + case bp_access_watchpoint: enable_breakpoint (bpt); default: continue; @@ -2986,10 +3638,15 @@ static void disable_breakpoint (bpt) struct breakpoint *bpt; { + /* Never disable a watchpoint scope breakpoint; we want to + hit them when we leave scope so we can delete both the + watchpoint and its scope breakpoint at that time. */ + if (bpt->type == bp_watchpoint_scope) + return; + bpt->enable = disabled; - if (xgdb_verbose && bpt->type == bp_breakpoint) - printf_filtered ("breakpoint #%d disabled\n", bpt->number); + breakpoints_changed (); check_duplicates (bpt->address); } @@ -3006,7 +3663,11 @@ disable_command (args, from_tty) switch (bpt->type) { case bp_breakpoint: - case bp_watchpoint: + case bp_hardware_breakpoint: + case bp_watchpoint: + case bp_hardware_watchpoint: + case bp_read_watchpoint: + case bp_access_watchpoint: disable_breakpoint (bpt); default: continue; @@ -3019,10 +3680,79 @@ static void enable_once_breakpoint (bpt) struct breakpoint *bpt; { + FRAME save_selected_frame = NULL; + int save_selected_frame_level = -1; + int target_resources_ok, other_type_used; + struct value *mark; + + if (bpt->type == bp_hardware_breakpoint) + { + int i; + i = hw_breakpoint_used_count(); + target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT( + bp_hardware_breakpoint, i+1, 0); + if (target_resources_ok == 0) + error ("No hardware breakpoint support in the target."); + else if (target_resources_ok < 0) + error ("Hardware breakpoints used exceeds limit."); + } + bpt->enable = enabled; bpt->disposition = disable; - check_duplicates (bpt->address); + breakpoints_changed (); + + if (bpt->type == bp_watchpoint || bpt->type == bp_hardware_watchpoint || + bpt->type == bp_read_watchpoint || bpt->type == bp_access_watchpoint) + { + if (bpt->exp_valid_block != NULL) + { + FRAME fr = find_frame_addr_in_frame_chain (bpt->watchpoint_frame); + if (fr == NULL) + { + printf_filtered ("\ +Cannot enable watchpoint %d because the block in which its expression\n\ +is valid is not currently in scope.\n", bpt->number); + bpt->enable = disabled; + return; + } + + save_selected_frame = selected_frame; + save_selected_frame_level = selected_frame_level; + select_frame (fr, -1); + } + + value_free (bpt->val); + mark = value_mark (); + bpt->val = evaluate_expression (bpt->exp); + release_value (bpt->val); + if (VALUE_LAZY (bpt->val)) + value_fetch_lazy (bpt->val); + + if (bpt->type == bp_hardware_watchpoint || + bpt->type == bp_read_watchpoint || + bpt->type == bp_access_watchpoint) + { + int i = hw_watchpoint_used_count (bpt->type, &other_type_used); + int mem_cnt = can_use_hardware_watchpoint(bpt->val); + target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT( + bpt->type, i+mem_cnt, other_type_used); + /* we can consider of type is bp_hardware_watchpoint, convert to + bp_watchpoint in the following condition */ + if (target_resources_ok < 0) + { + printf_filtered("\ +Cannot enable watchpoint %d because target watch resources\n\ +have been allocated for other watchpoints.\n", bpt->number); + bpt->enable = disabled; + value_free_to_mark (mark); + } + } + + if (save_selected_frame_level >= 0) + select_frame (save_selected_frame, save_selected_frame_level); + value_free_to_mark (mark); + } } /* ARGSUSED */ @@ -3042,6 +3772,7 @@ enable_delete_breakpoint (bpt) bpt->disposition = delete; check_duplicates (bpt->address); + breakpoints_changed (); } /* ARGSUSED */ @@ -3085,7 +3816,8 @@ _initialize_breakpoint () breakpoint_count = 0; add_com ("ignore", class_breakpoint, ignore_command, - "Set ignore-count of breakpoint number N to COUNT."); + "Set ignore-count of breakpoint number N to COUNT.\n\ +Usage is `ignore N COUNT'."); add_com ("commands", class_breakpoint, commands_command, "Set commands to be executed when a breakpoint is hit.\n\ @@ -3098,14 +3830,24 @@ then no output is printed when it is hit, except what the commands print."); add_com ("condition", class_breakpoint, condition_command, "Specify breakpoint number N to break only if COND is true.\n\ -N is an integer; COND is an expression to be evaluated whenever\n\ -breakpoint N is reached. "); +Usage is `condition N COND', where N is an integer and COND is an\n\ +expression to be evaluated whenever breakpoint N is reached. "); add_com ("tbreak", class_breakpoint, tbreak_command, "Set a temporary breakpoint. Args like \"break\" command.\n\ -Like \"break\" except the breakpoint is only enabled temporarily,\n\ -so it will be disabled when hit. Equivalent to \"break\" followed\n\ -by using \"enable once\" on the breakpoint number."); +Like \"break\" except the breakpoint is only temporary,\n\ +so it will be deleted when hit. Equivalent to \"break\" followed\n\ +by using \"enable delete\" on the breakpoint number."); + + add_com ("hbreak", class_breakpoint, hbreak_command, + "Set a hardware assisted breakpoint. Args like \"break\" command.\n\ +Like \"break\" except the breakpoint requires hardware support,\n\ +some target hardware may not have this support."); + + add_com ("thbreak", class_breakpoint, thbreak_command, + "Set a temporary hardware assisted breakpoint. Args like \"break\" command.\n\ +Like \"hbreak\" except the breakpoint is only temporary,\n\ +so it will be deleted when hit."); add_prefix_cmd ("enable", class_breakpoint, enable_command, "Enable some breakpoints.\n\ @@ -3124,8 +3866,7 @@ May be abbreviated to simply \"enable\".\n", add_cmd ("once", no_class, enable_once_command, "Enable breakpoints for one hit. Give breakpoint numbers.\n\ -If a breakpoint is hit while enabled in this fashion, it becomes disabled.\n\ -See the \"tbreak\" command which sets a breakpoint and enables it once.", +If a breakpoint is hit while enabled in this fashion, it becomes disabled.", &enablebreaklist); add_cmd ("delete", no_class, enable_delete_command, @@ -3140,8 +3881,7 @@ If a breakpoint is hit while enabled in this fashion, it is deleted.", add_cmd ("once", no_class, enable_once_command, "Enable breakpoints for one hit. Give breakpoint numbers.\n\ -If a breakpoint is hit while enabled in this fashion, it becomes disabled.\n\ -See the \"tbreak\" command which sets a breakpoint and enables it once.", +If a breakpoint is hit while enabled in this fashion, it becomes disabled.", &enablelist); add_prefix_cmd ("disable", class_breakpoint, disable_command, @@ -3260,8 +4000,19 @@ Do \"help breakpoints\" for info on other commands dealing with breakpoints."); A watchpoint stops execution of your program whenever the value of\n\ an expression changes."); + add_com ("rwatch", class_breakpoint, rwatch_command, + "Set a read watchpoint for an expression.\n\ +A watchpoint stops execution of your program whenever the value of\n\ +an expression is read."); + + add_com ("awatch", class_breakpoint, awatch_command, + "Set a watchpoint for an expression.\n\ +A watchpoint stops execution of your program whenever the value of\n\ +an expression is either read or written."); + add_info ("watchpoints", breakpoints_info, "Synonym for ``info breakpoints''."); + } /* OK, when we call objfile_relocate, we need to relocate breakpoints diff --git a/gnu/usr.bin/gdb/gdb/breakpoint.h b/gnu/usr.bin/gdb/gdb/breakpoint.h index 5005450804dc..a3ce41c342a8 100644 --- a/gnu/usr.bin/gdb/gdb/breakpoint.h +++ b/gnu/usr.bin/gdb/gdb/breakpoint.h @@ -1,5 +1,5 @@ /* Data structures associated with breakpoints in GDB. - Copyright (C) 1992 Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -39,9 +39,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ enum bptype { bp_breakpoint, /* Normal breakpoint */ + bp_hardware_breakpoint, /* Hardware assisted breakpoint */ bp_until, /* used by until command */ bp_finish, /* used by finish command */ bp_watchpoint, /* Watchpoint */ + bp_hardware_watchpoint, /* Hardware assisted watchpoint */ + bp_read_watchpoint, /* read watchpoint, (hardware assisted) */ + bp_access_watchpoint, /* access watchpoint, (hardware assisted) */ bp_longjmp, /* secret breakpoint to find longjmp() */ bp_longjmp_resume, /* secret breakpoint to escape longjmp() */ @@ -49,6 +53,23 @@ enum bptype { stepping over signal handlers, and for skipping prologues. */ bp_step_resume, + /* Used by wait_for_inferior for stepping over signal handlers. */ + bp_through_sigtramp, + + /* Used to detect when a watchpoint expression has gone out of + scope. These breakpoints are usually not visible to the user. + + This breakpoint has some interesting properties: + + 1) There's always a 1:1 mapping between watchpoints + on local variables and watchpoint_scope breakpoints. + + 2) It automatically deletes itself and the watchpoint it's + associated with when hit. + + 3) It can never be disabled. */ + bp_watchpoint_scope, + /* The breakpoint at the end of a call dummy. */ /* FIXME: What if the function we are calling longjmp()s out of the call, or the user gets out with the "return" command? We currently @@ -144,9 +165,31 @@ struct breakpoint valid anywhere (e.g. consists just of global symbols). */ struct block *exp_valid_block; /* Value of the watchpoint the last time we checked it. */ - value val; + value_ptr val; + + /* Holds the value chain for a hardware watchpoint expression. */ + value_ptr val_chain; + + /* Holds the address of the related watchpoint_scope breakpoint + when using watchpoints on local variables (might the concept + of a related breakpoint be useful elsewhere, if not just call + it the watchpoint_scope breakpoint or something like that. FIXME). */ + struct breakpoint *related_breakpoint; + + /* Holds the frame address which identifies the frame this watchpoint + should be evaluated in, or NULL if the watchpoint should be evaluated + on the outermost frame. */ + FRAME_ADDR watchpoint_frame; + /* Thread number for thread-specific breakpoint, or -1 if don't care */ int thread; + + /* Count of the number of times this breakpoint was taken, dumped + with the info, but not used for anything else. Useful for + seeing how many times you hit a break prior to the program + aborting, so you can back up to just before the abort. */ + int hit_count; + }; /* The following stuff is an abstract data type "bpstat" ("breakpoint status"). @@ -207,6 +250,13 @@ enum bpstat_what_main_action { /* Clear longjmp_resume breakpoint, then handle as BPSTAT_WHAT_SINGLE. */ BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE, + /* Clear step resume breakpoint, and keep checking. */ + BPSTAT_WHAT_STEP_RESUME, + + /* Clear through_sigtramp breakpoint, muck with trap_expected, and keep + checking. */ + BPSTAT_WHAT_THROUGH_SIGTRAMP, + /* This is just used to keep track of how many enums there are. */ BPSTAT_WHAT_LAST }; @@ -214,11 +264,6 @@ enum bpstat_what_main_action { struct bpstat_what { enum bpstat_what_main_action main_action; - /* Did we hit the step resume breakpoint? This is separate from the - main_action to allow for it to be combined with any of the main - actions. */ - int step_resume; - /* Did we hit a call dummy breakpoint? This only goes with a main_action of BPSTAT_WHAT_STOP_SILENT or BPSTAT_WHAT_STOP_NOISY (the concept of continuing from a call dummy without popping the frame is not a @@ -274,7 +319,7 @@ struct bpstat /* Commands left to be done. */ struct command_line *commands; /* Old value associated with a watchpoint. */ - value old_val; + value_ptr old_val; /* Nonzero if this breakpoint tells us to print the frame. */ char print; @@ -294,11 +339,11 @@ struct bpstat struct frame_info; #endif -extern int -breakpoint_here_p PARAMS ((CORE_ADDR)); +extern int breakpoint_here_p PARAMS ((CORE_ADDR)); -extern int -breakpoint_thread_match PARAMS ((CORE_ADDR, int)); +extern int frame_in_dummy PARAMS ((struct frame_info *)); + +extern int breakpoint_thread_match PARAMS ((CORE_ADDR, int)); extern void until_break_command PARAMS ((char *, int)); @@ -354,6 +399,8 @@ disable_longjmp_breakpoint PARAMS ((void)); extern void set_longjmp_resume_breakpoint PARAMS ((CORE_ADDR, FRAME)); +extern void clear_breakpoint_hit_counts PARAMS ((void)); + /* The following are for displays, which aren't really breakpoints, but here is as good a place as any for them. */ diff --git a/gnu/usr.bin/gdb/gdb/buildsym.c b/gnu/usr.bin/gdb/gdb/buildsym.c index dfa9be131625..e4dcbddc5687 100644 --- a/gnu/usr.bin/gdb/gdb/buildsym.c +++ b/gnu/usr.bin/gdb/gdb/buildsym.c @@ -39,6 +39,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "buildsym.h" /* Our own declarations */ #undef EXTERN +/* For cleanup_undefined_types and finish_global_stabs (somewhat + questionable--see comment where we call them). */ +#include "stabsread.h" + static int compare_line_numbers PARAMS ((const void *, const void *)); @@ -347,6 +351,15 @@ make_blockvector (objfile) if (BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i-1)) > BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i))) { + + /* FIXME-32x64: loses if CORE_ADDR doesn't fit in a + long. Possible solutions include a version of + complain which takes a callback, a + sprintf_address_numeric to match + print_address_numeric, or a way to set up a GDB_FILE + * which causes sprintf rather than fprintf to be + called. */ + complain (&blockvector_complaint, (unsigned long) BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i))); } @@ -392,8 +405,9 @@ start_subfile (name, dirname) current_subfile = subfile; /* Save its name and compilation directory name */ - subfile->name = (name == NULL)? NULL : strdup (name); - subfile->dirname = (dirname == NULL) ? NULL : strdup (dirname); + subfile->name = (name == NULL) ? NULL : savestring (name, strlen (name)); + subfile->dirname = + (dirname == NULL) ? NULL : savestring (dirname, strlen (dirname)); /* Initialize line-number recording for this subfile. */ subfile->line_vector = NULL; @@ -466,7 +480,7 @@ patch_subfile_names (subfile, name) && subfile->name[strlen(subfile->name)-1] == '/') { subfile->dirname = subfile->name; - subfile->name = strdup (name); + subfile->name = savestring (name, strlen (name)); /* Default the source language to whatever can be deduced from the filename. If nothing can be deduced (such as for a C/C++ diff --git a/gnu/usr.bin/gdb/gdb/c-lang.c b/gnu/usr.bin/gdb/gdb/c-lang.c index ea0795915f56..422bde8f34db 100644 --- a/gnu/usr.bin/gdb/gdb/c-lang.c +++ b/gnu/usr.bin/gdb/gdb/c-lang.c @@ -1,5 +1,5 @@ /* C language support routines for GDB, the GNU debugger. - Copyright 1992, 1993 Free Software Foundation, Inc. + Copyright 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -32,7 +32,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ static void emit_char (c, stream, quoter) register int c; - FILE *stream; + GDB_FILE *stream; int quoter; { @@ -81,7 +81,7 @@ emit_char (c, stream, quoter) static void c_printchar (c, stream) int c; - FILE *stream; + GDB_FILE *stream; { fputs_filtered ("'", stream); emit_char (c, stream, '\''); @@ -95,7 +95,7 @@ c_printchar (c, stream) static void c_printstr (stream, string, length, force_ellipses) - FILE *stream; + GDB_FILE *stream; char *string; unsigned int length; int force_ellipses; @@ -116,7 +116,7 @@ c_printstr (stream, string, length, force_ellipses) if (length == 0) { - fputs_filtered ("\"\"", stdout); + fputs_filtered ("\"\"", stream); return; } @@ -243,7 +243,7 @@ c_create_fundamental_type (objfile, typeid) case FT_SIGNED_CHAR: type = init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_SIGNED, "signed char", objfile); + 0, "signed char", objfile); break; case FT_UNSIGNED_CHAR: type = init_type (TYPE_CODE_INT, @@ -258,7 +258,7 @@ c_create_fundamental_type (objfile, typeid) case FT_SIGNED_SHORT: type = init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_SIGNED, "short", objfile); /* FIXME-fnf */ + 0, "short", objfile); /* FIXME-fnf */ break; case FT_UNSIGNED_SHORT: type = init_type (TYPE_CODE_INT, @@ -273,7 +273,7 @@ c_create_fundamental_type (objfile, typeid) case FT_SIGNED_INTEGER: type = init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_SIGNED, "int", objfile); /* FIXME -fnf */ + 0, "int", objfile); /* FIXME -fnf */ break; case FT_UNSIGNED_INTEGER: type = init_type (TYPE_CODE_INT, @@ -288,7 +288,7 @@ c_create_fundamental_type (objfile, typeid) case FT_SIGNED_LONG: type = init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_SIGNED, "long", objfile); /* FIXME -fnf */ + 0, "long", objfile); /* FIXME -fnf */ break; case FT_UNSIGNED_LONG: type = init_type (TYPE_CODE_INT, @@ -303,7 +303,7 @@ c_create_fundamental_type (objfile, typeid) case FT_SIGNED_LONG_LONG: type = init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_SIGNED, "signed long long", objfile); + 0, "signed long long", objfile); break; case FT_UNSIGNED_LONG_LONG: type = init_type (TYPE_CODE_INT, @@ -404,8 +404,7 @@ const struct language_defn c_language_defn = { c_create_fundamental_type, /* Create fundamental type in this language */ c_print_type, /* Print a type using appropriate syntax */ c_val_print, /* Print a value using appropriate syntax */ - &BUILTIN_TYPE_LONGEST, /* longest signed integral type */ - &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */ + c_value_print, /* Print a top-level value */ &builtin_type_double, /* longest floating point type */ /*FIXME*/ {"", "", "", ""}, /* Binary format info */ {"0%lo", "0", "o", ""}, /* Octal format info */ @@ -428,8 +427,7 @@ const struct language_defn cplus_language_defn = { c_create_fundamental_type, /* Create fundamental type in this language */ c_print_type, /* Print a type using appropriate syntax */ c_val_print, /* Print a value using appropriate syntax */ - &BUILTIN_TYPE_LONGEST, /* longest signed integral type */ - &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */ + c_value_print, /* Print a top-level value */ &builtin_type_double, /* longest floating point type */ /*FIXME*/ {"", "", "", ""}, /* Binary format info */ {"0%lo", "0", "o", ""}, /* Octal format info */ @@ -439,9 +437,33 @@ const struct language_defn cplus_language_defn = { LANG_MAGIC }; +const struct language_defn asm_language_defn = { + "asm", /* Language name */ + language_asm, + c_builtin_types, + range_check_off, + type_check_off, + c_parse, + c_error, + c_printchar, /* Print a character constant */ + c_printstr, /* Function to print string constant */ + c_create_fundamental_type, /* Create fundamental type in this language */ + c_print_type, /* Print a type using appropriate syntax */ + c_val_print, /* Print a value using appropriate syntax */ + c_value_print, /* Print a top-level value */ + &builtin_type_double, /* longest floating point type */ /*FIXME*/ + {"", "", "", ""}, /* Binary format info */ + {"0%lo", "0", "o", ""}, /* Octal format info */ + {"%ld", "", "d", ""}, /* Decimal format info */ + {"0x%lx", "0x", "x", ""}, /* Hex format info */ + c_op_print_tab, /* expression operators for printing */ + LANG_MAGIC +}; + void _initialize_c_language () { add_language (&c_language_defn); add_language (&cplus_language_defn); + add_language (&asm_language_defn); } diff --git a/gnu/usr.bin/gdb/gdb/c-lang.h b/gnu/usr.bin/gdb/gdb/c-lang.h index 4c343a9a5aa7..0ea013d2a99e 100644 --- a/gnu/usr.bin/gdb/gdb/c-lang.h +++ b/gnu/usr.bin/gdb/gdb/c-lang.h @@ -17,6 +17,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef __STDC__ /* Forward decls for prototypes */ +struct value; +#endif + extern int c_parse PARAMS ((void)); /* Defined in c-exp.y */ @@ -24,8 +28,11 @@ extern void c_error PARAMS ((char *)); /* Defined in c-exp.y */ extern void /* Defined in c-typeprint.c */ -c_print_type PARAMS ((struct type *, char *, FILE *, int, int)); +c_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int)); extern int -c_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int, +c_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); + +extern int +c_value_print PARAMS ((struct value *, GDB_FILE *, int, enum val_prettyprint)); diff --git a/gnu/usr.bin/gdb/gdb/c-typeprint.c b/gnu/usr.bin/gdb/gdb/c-typeprint.c index fa4035b00ac8..fa5d6f29f216 100644 --- a/gnu/usr.bin/gdb/gdb/c-typeprint.c +++ b/gnu/usr.bin/gdb/gdb/c-typeprint.c @@ -36,22 +36,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include -extern int demangle; /* whether to print C++ syms raw or source-form */ +static void +c_type_print_args PARAMS ((struct type *, GDB_FILE *)); static void -c_type_print_args PARAMS ((struct type *, FILE *)); +c_type_print_varspec_suffix PARAMS ((struct type *, GDB_FILE *, int, int, int)); static void -c_type_print_varspec_suffix PARAMS ((struct type *, FILE *, int, int, int)); - -static void -cp_type_print_derivation_info PARAMS ((FILE *, struct type *)); +cp_type_print_derivation_info PARAMS ((GDB_FILE *, struct type *)); void -c_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int)); +c_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *, int, int)); void -c_type_print_base PARAMS ((struct type *, FILE *, int, int)); +c_type_print_base PARAMS ((struct type *, GDB_FILE *, int, int)); /* Print a description of a type in the format of a @@ -62,7 +60,7 @@ void c_typedef_print (type, new, stream) struct type *type; struct symbol *new; - FILE *stream; + GDB_FILE *stream; { switch (current_language->la_language) { @@ -104,7 +102,7 @@ void c_print_type (type, varstring, stream, show, level) struct type *type; char *varstring; - FILE *stream; + GDB_FILE *stream; int show; int level; { @@ -145,7 +143,7 @@ cp_type_print_method_args (args, prefix, varstring, staticp, stream) char *prefix; char *varstring; int staticp; - FILE *stream; + GDB_FILE *stream; { int i; @@ -199,7 +197,7 @@ cp_type_print_method_args (args, prefix, varstring, staticp, stream) static void cp_type_print_derivation_info (stream, type) - FILE *stream; + GDB_FILE *stream; struct type *type; { char *name; @@ -231,7 +229,7 @@ cp_type_print_derivation_info (stream, type) void c_type_print_varspec_prefix (type, stream, show, passed_a_ptr) struct type *type; - FILE *stream; + GDB_FILE *stream; int show; int passed_a_ptr; { @@ -266,7 +264,7 @@ c_type_print_varspec_prefix (type, stream, show, passed_a_ptr) case TYPE_CODE_METHOD: if (passed_a_ptr) - fprintf (stream, "("); + fprintf_unfiltered (stream, "("); c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); if (passed_a_ptr) { @@ -316,7 +314,7 @@ c_type_print_varspec_prefix (type, stream, show, passed_a_ptr) static void c_type_print_args (type, stream) struct type *type; - FILE *stream; + GDB_FILE *stream; { int i; struct type **args; @@ -358,7 +356,7 @@ c_type_print_args (type, stream) static void c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args) struct type *type; - FILE *stream; + GDB_FILE *stream; int show; int passed_a_ptr; int demangled_args; @@ -409,12 +407,12 @@ c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args) break; case TYPE_CODE_FUNC: - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr, 0); if (passed_a_ptr) fprintf_filtered (stream, ")"); if (!demangled_args) fprintf_filtered (stream, "()"); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, + passed_a_ptr, 0); break; case TYPE_CODE_UNDEF: @@ -443,12 +441,12 @@ c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args) SHOW positive means print details about the type (e.g. enum values), and print structure elements passing SHOW - 1 for show. - SHOW zero means just print the type name or struct tag if there is one. + SHOW negative means just print the type name or struct tag if there is one. If there is no name, print something sensible but concise like "struct {...}". - SHOW negative means the same things as SHOW zero. The difference is that - zero is used for printing structure elements and -1 is used for the - "whatis" command. But I don't see any need to distinguish. + SHOW zero means just print the type name or struct tag if there is one. + If there is no name, print something sensible but not as concise like + "struct {int x; int y;}". LEVEL is the number of spaces to indent by. We increase it for some recursive calls. */ @@ -456,7 +454,7 @@ c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args) void c_type_print_base (type, stream, show, level) struct type *type; - FILE *stream; + GDB_FILE *stream; int show; int level; { @@ -488,6 +486,8 @@ c_type_print_base (type, stream, show, level) return; } + check_stub_type (type); + switch (TYPE_CODE (type)) { case TYPE_CODE_ARRAY: @@ -521,16 +521,14 @@ c_type_print_base (type, stream, show, level) fputs_filtered (" ", stream); } wrap_here (" "); - if (show <= 0) + if (show < 0) { /* If we just printed a tag name, no need to print anything else. */ if (TYPE_TAG_NAME (type) == NULL) fprintf_filtered (stream, "{...}"); } - else if (show > 0) + else if (show > 0 || TYPE_TAG_NAME (type) == NULL) { - check_stub_type (type); - cp_type_print_derivation_info (stream, type); fprintf_filtered (stream, "{\n"); @@ -665,7 +663,7 @@ c_type_print_base (type, stream, show, level) if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0) { /* Keep GDB from crashing here. */ - fprintf (stream, " %s;\n", + fprintf_unfiltered (stream, " %s;\n", TYPE_FN_FIELD_PHYSNAME (f, j)); break; } @@ -730,13 +728,13 @@ c_type_print_base (type, stream, show, level) } wrap_here (" "); - if (show <= 0) + if (show < 0) { /* If we just printed a tag name, no need to print anything else. */ if (TYPE_TAG_NAME (type) == NULL) fprintf_filtered (stream, "{...}"); } - else if (show > 0) + else if (show > 0 || TYPE_TAG_NAME (type) == NULL) { fprintf_filtered (stream, "{"); len = TYPE_NFIELDS (type); diff --git a/gnu/usr.bin/gdb/gdb/c-valprint.c b/gnu/usr.bin/gdb/gdb/c-valprint.c index bcf0a2876732..ee98fc46e3f5 100644 --- a/gnu/usr.bin/gdb/gdb/c-valprint.c +++ b/gnu/usr.bin/gdb/gdb/c-valprint.c @@ -1,5 +1,6 @@ /* Support for printing C values for GDB, the GNU debugger. - Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc. + Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -29,16 +30,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* BEGIN-FIXME */ extern int vtblprint; /* Controls printing of vtbl's */ -extern int demangle; /* whether to print C++ syms raw or src-form */ extern void -cp_print_class_member PARAMS ((char *, struct type *, FILE *, char *)); +cp_print_class_member PARAMS ((char *, struct type *, GDB_FILE *, char *)); extern void -cp_print_class_method PARAMS ((char *, struct type *, FILE *)); +cp_print_class_method PARAMS ((char *, struct type *, GDB_FILE *)); extern void -cp_print_value_fields PARAMS ((struct type *, char *, FILE *, int, int, +cp_print_value_fields PARAMS ((struct type *, char *, GDB_FILE *, int, int, enum val_prettyprint, struct type **)); extern int @@ -53,11 +53,11 @@ cp_is_vtbl_member PARAMS ((struct type *)); /* BEGIN-FIXME: Hooks into c-typeprint.c */ extern void -c_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int)); +c_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *, int, int)); extern void cp_type_print_method_args PARAMS ((struct type **, char *, char *, int, - FILE *)); + GDB_FILE *)); /* END-FIXME */ @@ -83,7 +83,7 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, struct type *type; char *valaddr; CORE_ADDR address; - FILE *stream; + GDB_FILE *stream; int format; int deref_ref; int recurse; @@ -109,9 +109,26 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, print_spaces_filtered (2 + 2 * recurse, stream); } /* For an array of chars, print with string syntax. */ - if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT + if (eltlen == 1 && + ((TYPE_CODE (elttype) == TYPE_CODE_INT) + || ((current_language->la_language == language_m2) + && (TYPE_CODE (elttype) == TYPE_CODE_CHAR))) && (format == 0 || format == 's')) { + /* If requested, look for the first null char and only print + elements up to it. */ + if (stop_print_at_null) + { + int temp_len; + + /* Look for a NULL char. */ + for (temp_len = 0; + valaddr[temp_len] + && temp_len < len && temp_len < print_max; + temp_len++); + len = temp_len; + } + LA_PRINT_STRING (stream, valaddr, len, 0); i = len; } @@ -145,6 +162,15 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, print_scalar_formatted (valaddr, type, format, 0, stream); break; } + if (vtblprint && cp_is_vtbl_ptr_type(type)) + { + /* Print the unmangled name if desired. */ + /* Print vtable entry - we only get here if we ARE using + -fvtable_thunks. (Otherwise, look under TYPE_CODE_STRUCT.) */ + print_address_demangle(extract_address (valaddr, TYPE_LENGTH (type)), + stream, demangle); + break; + } if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD) { cp_print_class_method (valaddr, type, stream); @@ -171,7 +197,7 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, if (addressprint && format != 's') { - fprintf_filtered (stream, "0x%lx", (unsigned long)addr); + print_address_numeric (addr, 1, stream); } /* For a pointer to char or unsigned char, also print the string @@ -197,17 +223,17 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, fputs_filtered (SYMBOL_SOURCE_NAME (msymbol), stream); fputs_filtered (">", stream); } - if (vtblprint) + if (vt_address && vtblprint) { - value vt_val; + value_ptr vt_val; struct symbol *wsym = (struct symbol *)NULL; struct type *wtype; struct symtab *s; struct block *block = (struct block *)NULL; int is_this_fld; - - wsym = lookup_symbol (SYMBOL_NAME(msymbol), block, + if (msymbol != NULL) + wsym = lookup_symbol (SYMBOL_NAME(msymbol), block, VAR_NAMESPACE, &is_this_fld, &s); if (wsym) @@ -230,9 +256,10 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, } } - /* Return number of characters printed, plus one for the - terminating null if we have "reached the end". */ - return (i + (print_max && i != print_max)); + /* Return number of characters printed, including the terminating + '\0' if we reached the end. val_print_string takes care including + the terminating '\0' if necessary. */ + return i; } break; @@ -250,8 +277,10 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, } if (addressprint) { - fprintf_filtered (stream, "@0x%lx", - unpack_long (builtin_type_int, valaddr)); + fprintf_filtered (stream, "@"); + print_address_numeric + (extract_address (valaddr, + TARGET_PTR_BIT / HOST_CHAR_BIT), 1, stream); if (deref_ref) fputs_filtered (": ", stream); } @@ -260,7 +289,7 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, { if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF) { - value deref_val = + value_ptr deref_val = value_at (TYPE_TARGET_TYPE (type), unpack_pointer (lookup_pointer_type (builtin_type_void), @@ -286,6 +315,8 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, if (vtblprint && cp_is_vtbl_ptr_type(type)) { /* Print the unmangled name if desired. */ + /* Print vtable entry - we only get here if NOT using + -fvtable_thunks. (Otherwise, look under TYPE_CODE_PTR.) */ print_address_demangle(*((int *) (valaddr + /* FIXME bytesex */ TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8)), stream, demangle); @@ -340,6 +371,16 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, /* Do something at least vaguely reasonable, for example if the language is set wrong. */ + case TYPE_CODE_RANGE: + /* FIXME: create_range_type does not set the unsigned bit in a + range type (I think it probably should copy it from the target + type), so we won't print values which are too large to + fit in a signed integer correctly. */ + /* FIXME: Doesn't handle ranges of enums correctly. (Can't just + print with the target type, though, because the size of our type + and the target type might differ). */ + /* FALLTHROUGH */ + case TYPE_CODE_INT: format = format ? format : output_format; if (format) @@ -396,11 +437,6 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, fprintf_filtered (stream, ""); break; - case TYPE_CODE_RANGE: - /* FIXME, we should not ever have to print one of these yet. */ - fprintf_filtered (stream, ""); - break; - case TYPE_CODE_UNDEF: /* This happens (without TYPE_FLAG_STUB set) on systems which don't use dbx xrefs (NO_DBX_XREFS in gcc) if a file has a "struct foo *bar" @@ -411,6 +447,67 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, default: error ("Invalid C/C++ type code %d in symbol table.", TYPE_CODE (type)); } - fflush (stream); + gdb_flush (stream); return (0); } + +int +c_value_print (val, stream, format, pretty) + value_ptr val; + GDB_FILE *stream; + int format; + enum val_prettyprint pretty; +{ + /* A "repeated" value really contains several values in a row. + They are made by the @ operator. + Print such values as if they were arrays. */ + + if (VALUE_REPEATED (val)) + { + register unsigned int n = VALUE_REPETITIONS (val); + register unsigned int typelen = TYPE_LENGTH (VALUE_TYPE (val)); + fprintf_filtered (stream, "{"); + /* Print arrays of characters using string syntax. */ + if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT + && format == 0) + LA_PRINT_STRING (stream, VALUE_CONTENTS (val), n, 0); + else + { + value_print_array_elements (val, stream, format, pretty); + } + fprintf_filtered (stream, "}"); + return (n * typelen); + } + else + { + struct type *type = VALUE_TYPE (val); + + /* If it is a pointer, indicate what it points to. + + Print type also if it is a reference. + + C++: if it is a member pointer, we will take care + of that when we print it. */ + if (TYPE_CODE (type) == TYPE_CODE_PTR || + TYPE_CODE (type) == TYPE_CODE_REF) + { + /* Hack: remove (char *) for char strings. Their + type is indicated by the quoted string anyway. */ + if (TYPE_CODE (type) == TYPE_CODE_PTR && + TYPE_LENGTH (TYPE_TARGET_TYPE (type)) == sizeof(char) && + TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_INT && + !TYPE_UNSIGNED (TYPE_TARGET_TYPE (type))) + { + /* Print nothing */ + } + else + { + fprintf_filtered (stream, "("); + type_print (type, "", stream, -1); + fprintf_filtered (stream, ") "); + } + } + return (val_print (type, VALUE_CONTENTS (val), + VALUE_ADDRESS (val), stream, format, 1, 0, pretty)); + } +} diff --git a/gnu/usr.bin/gdb/gdb/ch-lang.c b/gnu/usr.bin/gdb/gdb/ch-lang.c index 2f7406103d0c..b3128fdc08e8 100644 --- a/gnu/usr.bin/gdb/gdb/ch-lang.c +++ b/gnu/usr.bin/gdb/gdb/ch-lang.c @@ -52,7 +52,7 @@ chill_demangle (mangled) static void chill_printchar (c, stream) register int c; - FILE *stream; + GDB_FILE *stream; { c &= 0xFF; /* Avoid sign bit follies */ @@ -79,7 +79,7 @@ chill_printchar (c, stream) static void chill_printstr (stream, string, length, force_ellipses) - FILE *stream; + GDB_FILE *stream; char *string; unsigned int length; int force_ellipses; @@ -95,7 +95,7 @@ chill_printstr (stream, string, length, force_ellipses) if (length == 0) { - chill_printchar ('\0', stream); + fputs_filtered ("\"\"", stream); return; } @@ -128,7 +128,7 @@ chill_printstr (stream, string, length, force_ellipses) { if (in_control_form || in_literal_form) { - fputs_filtered ("'//", stream); + fputs_filtered ("\"//", stream); in_control_form = in_literal_form = 0; } chill_printchar (c, stream); @@ -145,10 +145,10 @@ chill_printstr (stream, string, length, force_ellipses) { if (in_control_form) { - fputs_filtered ("'//", stream); + fputs_filtered ("\"//", stream); in_control_form = 0; } - fputs_filtered ("'", stream); + fputs_filtered ("\"", stream); in_literal_form = 1; } fprintf_filtered (stream, "%c", c); @@ -159,10 +159,10 @@ chill_printstr (stream, string, length, force_ellipses) { if (in_literal_form) { - fputs_filtered ("'//", stream); + fputs_filtered ("\"//", stream); in_literal_form = 0; } - fputs_filtered ("c'", stream); + fputs_filtered ("c\"", stream); in_control_form = 1; } fprintf_filtered (stream, "%.2x", c); @@ -174,7 +174,7 @@ chill_printstr (stream, string, length, force_ellipses) /* Terminate the quotes if necessary. */ if (in_literal_form || in_control_form) { - fputs_filtered ("'", stream); + fputs_filtered ("\"", stream); } if (force_ellipses || (i < length)) { @@ -182,6 +182,21 @@ chill_printstr (stream, string, length, force_ellipses) } } +/* Return 1 if TYPE is a varying string or array. */ + +int +chill_is_varying_struct (type) + struct type *type; +{ + if (TYPE_CODE (type) != TYPE_CODE_STRUCT) + return 0; + if (TYPE_NFIELDS (type) != 2) + return 0; + if (strcmp (TYPE_FIELD_NAME (type, 0), "__var_length") != 0) + return 0; + return 1; +} + static struct type * chill_create_fundamental_type (objfile, typeid) struct objfile *objfile; @@ -212,13 +227,13 @@ chill_create_fundamental_type (objfile, typeid) type = init_type (TYPE_CODE_CHAR, 1, TYPE_FLAG_UNSIGNED, "CHAR", objfile); break; case FT_SIGNED_CHAR: - type = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_SIGNED, "BYTE", objfile); + type = init_type (TYPE_CODE_INT, 1, 0, "BYTE", objfile); break; case FT_UNSIGNED_CHAR: type = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_UNSIGNED, "UBYTE", objfile); break; case FT_SHORT: /* Chill ints are 2 bytes */ - type = init_type (TYPE_CODE_INT, 2, TYPE_FLAG_SIGNED, "INT", objfile); + type = init_type (TYPE_CODE_INT, 2, 0, "INT", objfile); break; case FT_UNSIGNED_SHORT: /* Chill ints are 2 bytes */ type = init_type (TYPE_CODE_INT, 2, TYPE_FLAG_UNSIGNED, "UINT", objfile); @@ -227,7 +242,7 @@ chill_create_fundamental_type (objfile, typeid) case FT_SIGNED_INTEGER: /* FIXME? */ case FT_LONG: /* Chill longs are 4 bytes */ case FT_SIGNED_LONG: /* Chill longs are 4 bytes */ - type = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_SIGNED, "LONG", objfile); + type = init_type (TYPE_CODE_INT, 4, 0, "LONG", objfile); break; case FT_UNSIGNED_INTEGER: /* FIXME? */ case FT_UNSIGNED_LONG: /* Chill longs are 4 bytes */ @@ -300,8 +315,7 @@ const struct language_defn chill_language_defn = { chill_create_fundamental_type,/* Create fundamental type in this language */ chill_print_type, /* Print a type using appropriate syntax */ chill_val_print, /* Print a value using appropriate syntax */ - &BUILTIN_TYPE_LONGEST, /* longest signed integral type */ - &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */ + chill_value_print, /* Print a top-levl value */ &builtin_type_chill_real, /* longest floating point type */ {"", "B'", "", ""}, /* Binary format info */ {"O'%lo", "O'", "o", ""}, /* Octal format info */ diff --git a/gnu/usr.bin/gdb/gdb/ch-lang.h b/gnu/usr.bin/gdb/gdb/ch-lang.h index 13579d9d47cb..0fcb8d62fb56 100644 --- a/gnu/usr.bin/gdb/gdb/ch-lang.h +++ b/gnu/usr.bin/gdb/gdb/ch-lang.h @@ -17,6 +17,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef __STDC__ /* Forward decls for prototypes */ +struct value; +#endif + extern int chill_parse PARAMS ((void)); /* Defined in ch-exp.y */ @@ -24,8 +28,17 @@ extern void chill_error PARAMS ((char *)); /* Defined in ch-exp.y */ extern void /* Defined in ch-typeprint.c */ -chill_print_type PARAMS ((struct type *, char *, FILE *, int, int)); +chill_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int)); extern int -chill_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int, +chill_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); + +extern int +chill_value_print PARAMS ((struct value *, GDB_FILE *, + int, enum val_prettyprint)); + +extern int +chill_is_varying_struct PARAMS ((struct type *type)); + + diff --git a/gnu/usr.bin/gdb/gdb/ch-typeprint.c b/gnu/usr.bin/gdb/gdb/ch-typeprint.c index c3cdcd2a1885..9bc4303e58f8 100644 --- a/gnu/usr.bin/gdb/gdb/ch-typeprint.c +++ b/gnu/usr.bin/gdb/gdb/ch-typeprint.c @@ -31,18 +31,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "language.h" #include "demangle.h" #include "ch-lang.h" +#include "typeprint.h" #include #include static void -chill_type_print_base PARAMS ((struct type *, FILE *, int, int)); +chill_type_print_base PARAMS ((struct type *, GDB_FILE *, int, int)); void chill_print_type (type, varstring, stream, show, level) struct type *type; char *varstring; - FILE *stream; + GDB_FILE *stream; int show; int level; { @@ -69,11 +70,10 @@ chill_print_type (type, varstring, stream, show, level) static void chill_type_print_base (type, stream, show, level) struct type *type; - FILE *stream; + GDB_FILE *stream; int show; int level; { - char *name; register int len; register int i; struct type *index_type; @@ -99,6 +99,8 @@ chill_type_print_base (type, stream, show, level) return; } + check_stub_type (type); + switch (TYPE_CODE (type)) { case TYPE_CODE_PTR: @@ -111,6 +113,14 @@ chill_type_print_base (type, stream, show, level) chill_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); break; + case TYPE_CODE_BOOL: + /* FIXME: we should probably just print the TYPE_NAME, in case + anyone ever fixes the compiler to give us the real names + in the presence of the chill equivalent of typedef (assuming + there is one). */ + fprintf_filtered (stream, "BOOL"); + break; + case TYPE_CODE_ARRAY: range_type = TYPE_FIELD_TYPE (type, 0); index_type = TYPE_TARGET_TYPE (range_type); @@ -124,11 +134,22 @@ chill_type_print_base (type, stream, show, level) chill_print_type (TYPE_TARGET_TYPE (type), "", stream, show, level); break; + case TYPE_CODE_BITSTRING: + fprintf_filtered (stream, "BOOLS (%d)", + TYPE_FIELD_BITPOS (TYPE_FIELD_TYPE(type,0), 1) + 1); + break; + + case TYPE_CODE_SET: + fputs_filtered ("POWERSET ", stream); + chill_print_type (TYPE_FIELD_TYPE (type, 0), "", stream, + show - 1, level); + break; + case TYPE_CODE_STRING: range_type = TYPE_FIELD_TYPE (type, 0); index_type = TYPE_TARGET_TYPE (range_type); high_bound = TYPE_FIELD_BITPOS (range_type, 1); - fputs_filtered ("CHAR (", stream); + fputs_filtered ("CHARS (", stream); print_type_scalar (index_type, high_bound + 1, stream); fputs_filtered (")", stream); break; @@ -147,20 +168,16 @@ chill_type_print_base (type, stream, show, level) break; case TYPE_CODE_STRUCT: - fprintf_filtered (stream, "STRUCT "); - if ((name = type_name_no_tag (type)) != NULL) + if (chill_is_varying_struct (type)) { - fputs_filtered (name, stream); - fputs_filtered (" ", stream); - wrap_here (" "); - } - if (show < 0) - { - fprintf_filtered (stream, "(...)"); + chill_type_print_base (TYPE_FIELD_TYPE (type, 1), + stream, show, level); + fputs_filtered (" VARYING", stream); } else { - check_stub_type (type); + fprintf_filtered (stream, "STRUCT "); + fprintf_filtered (stream, "(\n"); if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0)) { @@ -178,11 +195,42 @@ chill_type_print_base (type, stream, show, level) len = TYPE_NFIELDS (type); for (i = TYPE_N_BASECLASSES (type); i < len; i++) { + struct type *field_type = TYPE_FIELD_TYPE (type, i); QUIT; print_spaces_filtered (level + 4, stream); - chill_print_type (TYPE_FIELD_TYPE (type, i), - TYPE_FIELD_NAME (type, i), - stream, show - 1, level + 4); + if (TYPE_CODE (field_type) == TYPE_CODE_UNION) + { int j; /* variant number */ + fputs_filtered ("CASE OF\n", stream); + for (j = 0; j < TYPE_NFIELDS (field_type); j++) + { int k; /* variant field index */ + struct type *variant_type + = TYPE_FIELD_TYPE (field_type, j); + int var_len = TYPE_NFIELDS (variant_type); + print_spaces_filtered (level + 4, stream); + if (strcmp (TYPE_FIELD_NAME (field_type, j), + "else") == 0) + fputs_filtered ("ELSE\n", stream); + else + fputs_filtered (":\n", stream); + if (TYPE_CODE (variant_type) != TYPE_CODE_STRUCT) + error ("variant record confusion"); + for (k = 0; k < var_len; k++) + { + print_spaces_filtered (level + 8, stream); + chill_print_type (TYPE_FIELD_TYPE (variant_type, k), + TYPE_FIELD_NAME (variant_type, k), + stream, show - 1, level + 8); + if (k < (var_len - 1)) + fputs_filtered (",", stream); + fputs_filtered ("\n", stream); + } + } + fputs_filtered ("ESAC\n", stream); + } + else + chill_print_type (field_type, + TYPE_FIELD_NAME (type, i), + stream, show - 1, level + 4); if (i < (len - 1)) { fputs_filtered (",", stream); @@ -194,11 +242,53 @@ chill_type_print_base (type, stream, show, level) } break; + case TYPE_CODE_RANGE: + if (TYPE_DUMMY_RANGE (type)) + chill_type_print_base (TYPE_TARGET_TYPE (type), + stream, show, level); + else if (TYPE_TARGET_TYPE (type)) + { + chill_type_print_base (TYPE_TARGET_TYPE (type), + stream, show, level); + fputs_filtered (" (", stream); + print_type_scalar (TYPE_TARGET_TYPE (type), + TYPE_FIELD_BITPOS (type, 0), stream); + fputs_filtered (":", stream); + print_type_scalar (TYPE_TARGET_TYPE (type), + TYPE_FIELD_BITPOS (type, 1), stream); + fputs_filtered (")", stream); + } + else + fprintf_filtered (stream, "RANGE? (%s : %d)", + TYPE_FIELD_BITPOS (type, 0), + TYPE_FIELD_BITPOS (type, 1)); + break; + + case TYPE_CODE_ENUM: + { + register int lastval = 0; + fprintf_filtered (stream, "SET ("); + len = TYPE_NFIELDS (type); + for (i = 0; i < len; i++) + { + QUIT; + if (i) fprintf_filtered (stream, ", "); + wrap_here (" "); + fputs_filtered (TYPE_FIELD_NAME (type, i), stream); + if (lastval != TYPE_FIELD_BITPOS (type, i)) + { + fprintf_filtered (stream, " = %d", TYPE_FIELD_BITPOS (type, i)); + lastval = TYPE_FIELD_BITPOS (type, i); + } + lastval++; + } + fprintf_filtered (stream, ")"); + } + break; + case TYPE_CODE_VOID: case TYPE_CODE_UNDEF: case TYPE_CODE_ERROR: - case TYPE_CODE_RANGE: - case TYPE_CODE_ENUM: case TYPE_CODE_UNION: case TYPE_CODE_METHOD: error ("missing language support in chill_type_print_base"); diff --git a/gnu/usr.bin/gdb/gdb/ch-valprint.c b/gnu/usr.bin/gdb/gdb/ch-valprint.c index 261b22ee62c6..00f556529e66 100644 --- a/gnu/usr.bin/gdb/gdb/ch-valprint.c +++ b/gnu/usr.bin/gdb/gdb/ch-valprint.c @@ -1,5 +1,6 @@ /* Support for printing Chill values for GDB, the GNU debugger. - Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc. + Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -26,12 +27,106 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "value.h" #include "language.h" #include "demangle.h" +#include "c-lang.h" /* For c_val_print */ +#include "typeprint.h" +#include "ch-lang.h" static void -chill_print_value_fields PARAMS ((struct type *, char *, FILE *, int, int, +chill_print_value_fields PARAMS ((struct type *, char *, GDB_FILE *, int, int, enum val_prettyprint, struct type **)); +/* Print the elements of an array. + Similar to val_print_array_elements, but prints + element indexes (in Chill syntax). */ + +static void +chill_val_print_array_elements (type, valaddr, address, stream, + format, deref_ref, recurse, pretty) + struct type *type; + char *valaddr; + CORE_ADDR address; + GDB_FILE *stream; + int format; + int deref_ref; + int recurse; + enum val_prettyprint pretty; +{ + unsigned int i = 0; + unsigned int things_printed = 0; + unsigned len; + struct type *elttype; + struct type *range_type = TYPE_FIELD_TYPE (type, 0); + struct type *index_type = TYPE_TARGET_TYPE (range_type); + unsigned eltlen; + /* Position of the array element we are examining to see + whether it is repeated. */ + unsigned int rep1; + /* Number of repetitions we have detected so far. */ + unsigned int reps; + LONGEST low_bound = TYPE_FIELD_BITPOS (range_type, 0); + LONGEST high_bound = TYPE_FIELD_BITPOS (range_type, 1); + + elttype = TYPE_TARGET_TYPE (type); + eltlen = TYPE_LENGTH (elttype); + len = TYPE_LENGTH (type) / eltlen; + + annotate_array_section_begin (i, elttype); + + for (; i < len && things_printed < print_max; i++) + { + if (i != 0) + { + if (prettyprint_arrays) + { + fprintf_filtered (stream, ",\n"); + print_spaces_filtered (2 + 2 * recurse, stream); + } + else + { + fprintf_filtered (stream, ", "); + } + } + wrap_here (n_spaces (2 + 2 * recurse)); + + rep1 = i + 1; + reps = 1; + while ((rep1 < len) && + !memcmp (valaddr + i * eltlen, valaddr + rep1 * eltlen, eltlen)) + { + ++reps; + ++rep1; + } + + fputs_filtered ("(", stream); + print_type_scalar (index_type, low_bound + i, stream); + if (reps > 1) + { + fputs_filtered (":", stream); + print_type_scalar (index_type, low_bound + i + reps - 1, stream); + fputs_filtered ("): ", stream); + val_print (elttype, valaddr + i * eltlen, 0, stream, format, + deref_ref, recurse + 1, pretty); + + i = rep1 - 1; + things_printed += 1; + } + else + { + fputs_filtered ("): ", stream); + val_print (elttype, valaddr + i * eltlen, 0, stream, format, + deref_ref, recurse + 1, pretty); + annotate_elt (); + things_printed++; + } + } + annotate_array_section_end (); + if (i < len) + { + fprintf_filtered (stream, "..."); + } +} + /* Print data of type TYPE located at VALADDR (within GDB), which came from the inferior at address ADDRESS, onto stdio stream STREAM according to FORMAT (a letter or 0 for natural format). The data at VALADDR is in @@ -51,7 +146,7 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, struct type *type; char *valaddr; CORE_ADDR address; - FILE *stream; + GDB_FILE *stream; int format; int deref_ref; int recurse; @@ -72,8 +167,8 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, print_spaces_filtered (2 + 2 * recurse, stream); } fprintf_filtered (stream, "["); - val_print_array_elements (type, valaddr, address, stream, format, - deref_ref, recurse, pretty, 0); + chill_val_print_array_elements (type, valaddr, address, stream, + format, deref_ref, recurse, pretty); fprintf_filtered (stream, "]"); } else @@ -126,6 +221,7 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, } else { + /* FIXME: Why is this using builtin_type_chill_bool not type? */ val = unpack_long (builtin_type_chill_bool, valaddr); fprintf_filtered (stream, val ? "TRUE" : "FALSE"); } @@ -146,6 +242,13 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, } addr = unpack_pointer (type, valaddr); elttype = TYPE_TARGET_TYPE (type); + + /* We assume a NULL pointer is all zeros ... */ + if (addr == 0) + { + fputs_filtered ("NULL", stream); + return 0; + } if (TYPE_CODE (elttype) == TYPE_CODE_FUNC) { @@ -156,7 +259,7 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, } if (addressprint && format != 's') { - fprintf_filtered (stream, "H'%lx", (unsigned long) addr); + print_address_numeric (addr, 1, stream); } /* For a pointer to char or unsigned char, also print the string @@ -182,12 +285,6 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, print_scalar_formatted (valaddr, type, format, 0, stream); break; } - if (addressprint && format != 's') - { - /* This used to say `addr', which is unset at this point. - Is `address' what is meant? */ - fprintf_filtered (stream, "H'%lx ", (unsigned long) address); - } i = TYPE_LENGTH (type); LA_PRINT_STRING (stream, valaddr, i, 0); /* Return number of characters printed, plus one for the terminating @@ -195,7 +292,81 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, return (i + (print_max && i != print_max)); break; + case TYPE_CODE_BITSTRING: + case TYPE_CODE_SET: + elttype = TYPE_FIELD_TYPE (type, 0); + check_stub_type (elttype); + if (TYPE_FLAGS (elttype) & TYPE_FLAG_STUB) + { + fprintf_filtered (stream, ""); + gdb_flush (stream); + break; + } + { + struct type *range = elttype; + int low_bound = TYPE_LOW_BOUND (range); + int high_bound = TYPE_HIGH_BOUND (range); + int i; + int is_bitstring = TYPE_CODE (type) == TYPE_CODE_BITSTRING; + int need_comma = 0; + + if (is_bitstring) + fputs_filtered ("B'", stream); + else + fputs_filtered ("[", stream); + for (i = low_bound; i <= high_bound; i++) + { + int element = value_bit_index (type, valaddr, i); + if (is_bitstring) + fprintf_filtered (stream, "%d", element); + else if (element) + { + if (need_comma) + fputs_filtered (", ", stream); + print_type_scalar (TYPE_TARGET_TYPE (range), i, stream); + need_comma = 1; + + /* Look for a continuous range of true elements. */ + if (i+1 <= high_bound && value_bit_index (type, valaddr, ++i)) + { + int j = i; /* j is the upper bound so far of the range */ + fputs_filtered (":", stream); + while (i+1 <= high_bound + && value_bit_index (type, valaddr, ++i)) + j = i; + print_type_scalar (TYPE_TARGET_TYPE (range), j, stream); + } + } + } + if (is_bitstring) + fputs_filtered ("'", stream); + else + fputs_filtered ("]", stream); + } + break; + case TYPE_CODE_STRUCT: + if (chill_is_varying_struct (type)) + { + struct type *inner = TYPE_FIELD_TYPE (type, 1); + long length = unpack_long (TYPE_FIELD_TYPE (type, 0), valaddr); + char *data_addr = valaddr + TYPE_FIELD_BITPOS (type, 1) / 8; + + switch (TYPE_CODE (inner)) + { + case TYPE_CODE_STRING: + if (length > TYPE_LENGTH (type)) + { + fprintf_filtered (stream, + " static length %d>", + length, TYPE_LENGTH (type)); + } + LA_PRINT_STRING (stream, data_addr, length, 0); + return length; + default: + break; + } + } chill_print_value_fields (type, valaddr, stream, format, recurse, pretty, 0); break; @@ -203,8 +374,12 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, case TYPE_CODE_REF: if (addressprint) { - fprintf_filtered (stream, "LOC(H'%lx)", - unpack_long (builtin_type_int, valaddr)); + fprintf_filtered (stream, "LOC("); + print_address_numeric + (extract_address (valaddr, TARGET_PTR_BIT / HOST_CHAR_BIT), + 1, + stream); + fprintf_filtered (stream, ")"); if (deref_ref) fputs_filtered (": ", stream); } @@ -213,7 +388,7 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, { if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF) { - value deref_val = + value_ptr deref_val = value_at (TYPE_TARGET_TYPE (type), unpack_pointer (lookup_pointer_type (builtin_type_void), @@ -233,19 +408,24 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, deref_ref, recurse, pretty); break; + case TYPE_CODE_RANGE: + if (TYPE_TARGET_TYPE (type)) + chill_val_print (TYPE_TARGET_TYPE (type), valaddr, address, stream, + format, deref_ref, recurse, pretty); + break; + case TYPE_CODE_MEMBER: case TYPE_CODE_UNION: case TYPE_CODE_FUNC: case TYPE_CODE_VOID: case TYPE_CODE_ERROR: - case TYPE_CODE_RANGE: default: - /* Let's derfer printing to the C printer, rather than + /* Let's defer printing to the C printer, rather than print an error message. FIXME! */ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty); } - fflush (stream); + gdb_flush (stream); return (0); } @@ -263,7 +443,7 @@ chill_print_value_fields (type, valaddr, stream, format, recurse, pretty, dont_print) struct type *type; char *valaddr; - FILE *stream; + GDB_FILE *stream; int format; int recurse; enum val_prettyprint pretty; @@ -304,7 +484,7 @@ chill_print_value_fields (type, valaddr, stream, format, recurse, pretty, fputs_filtered (": ", stream); if (TYPE_FIELD_PACKED (type, i)) { - value v; + value_ptr v; /* Bitfields require special handling, especially due to byte order problems. */ @@ -329,4 +509,73 @@ chill_print_value_fields (type, valaddr, stream, format, recurse, pretty, } fprintf_filtered (stream, "]"); } + +int +chill_value_print (val, stream, format, pretty) + value_ptr val; + GDB_FILE *stream; + int format; + enum val_prettyprint pretty; +{ + /* A "repeated" value really contains several values in a row. + They are made by the @ operator. + Print such values as if they were arrays. */ + + if (VALUE_REPEATED (val)) + { + register unsigned int n = VALUE_REPETITIONS (val); + register unsigned int typelen = TYPE_LENGTH (VALUE_TYPE (val)); + fprintf_filtered (stream, "["); + /* Print arrays of characters using string syntax. */ + if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT + && format == 0) + LA_PRINT_STRING (stream, VALUE_CONTENTS (val), n, 0); + else + { + value_print_array_elements (val, stream, format, pretty); + } + fprintf_filtered (stream, "]"); + return (n * typelen); + } + else + { + struct type *type = VALUE_TYPE (val); + + /* If it is a pointer, indicate what it points to. + + Print type also if it is a reference. + + C++: if it is a member pointer, we will take care + of that when we print it. */ + if (TYPE_CODE (type) == TYPE_CODE_PTR || + TYPE_CODE (type) == TYPE_CODE_REF) + { + char *valaddr = VALUE_CONTENTS (val); + CORE_ADDR addr = unpack_pointer (type, valaddr); + if (TYPE_CODE (type) != TYPE_CODE_PTR || addr != 0) + { + int i; + char *name = TYPE_NAME (type); + if (name) + fputs_filtered (name, stream); + else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID) + fputs_filtered ("PTR", stream); + else + { + fprintf_filtered (stream, "("); + type_print (type, "", stream, -1); + fprintf_filtered (stream, ")"); + } + fprintf_filtered (stream, "("); + i = val_print (type, valaddr, VALUE_ADDRESS (val), + stream, format, 1, 0, pretty); + fprintf_filtered (stream, ")"); + return i; + } + } + return (val_print (type, VALUE_CONTENTS (val), + VALUE_ADDRESS (val), stream, format, 1, 0, pretty)); + } +} + diff --git a/gnu/usr.bin/gdb/gdb/coff/ecoff.h b/gnu/usr.bin/gdb/gdb/coff/ecoff.h index 8c7cee243ea9..7f149eb1058d 100644 --- a/gnu/usr.bin/gdb/gdb/coff/ecoff.h +++ b/gnu/usr.bin/gdb/gdb/coff/ecoff.h @@ -36,56 +36,39 @@ #define _RDATA ".rdata" #define _SDATA ".sdata" #define _SBSS ".sbss" +#define _LITA ".lita" #define _LIT4 ".lit4" #define _LIT8 ".lit8" #define _LIB ".lib" #define _INIT ".init" #define _FINI ".fini" +#define _PDATA ".pdata" +#define _XDATA ".xdata" /* ECOFF uses some additional section flags. */ -#define STYP_RDATA 0x100 -#define STYP_SDATA 0x200 -#define STYP_SBSS 0x400 -#define STYP_ECOFF_FINI 0x1000000 -#define STYP_LIT8 0x8000000 -#define STYP_LIT4 0x10000000 +#define STYP_RDATA 0x100 +#define STYP_SDATA 0x200 +#define STYP_SBSS 0x400 +#define STYP_ECOFF_FINI 0x1000000 +#define STYP_EXTENDESC 0x2000000 /* 0x02FFF000 bits => scn type, rest clr */ +#define STYP_LITA 0x4000000 +#define STYP_LIT8 0x8000000 +#define STYP_LIT4 0x10000000 +#define STYP_ECOFF_LIB 0x40000000 #define STYP_ECOFF_INIT 0x80000000 #define STYP_OTHER_LOAD (STYP_ECOFF_INIT | STYP_ECOFF_FINI) +/* extended section types */ +#define STYP_COMMENT 0x2100000 +#define STYP_XDATA 0x2400000 +#define STYP_PDATA 0x2800000 + /* The linker needs a section to hold small common variables while linking. There is no convenient way to create it when the linker needs it, so we always create one for each BFD. We then avoid writing it out. */ #define SCOMMON ".scommon" -/* The ECOFF a.out header carries information about register masks and - the gp value. The assembler needs to be able to write out this - information, and objcopy needs to be able to copy it from one file - to another. To handle this in BFD, we use a dummy section to hold - the information. We call this section .reginfo, since MIPS ELF has - a .reginfo section which serves a similar purpose. When BFD - recognizes an ECOFF object, it copies the information into a - private data structure. When the .reginfo section is read, the - information is retrieved from the private data structure. When the - .reginfo section is written, the information in the private data - structure is updated. The contents of the .reginfo section, as - seen by programs outside BFD, is a ecoff_reginfo structure. The - contents of the structure are as seen on the host, so no swapping - issues arise. - - The assembler used to update the private BFD data structures - directly. With this approach, it instead just creates a .reginfo - section and updates that. The real advantage of this approach is - that objcopy works automatically. */ -#define REGINFO ".reginfo" -struct ecoff_reginfo -{ - bfd_vma gp_value; /* GP register value. */ - unsigned long gprmask; /* General registers used. */ - unsigned long cprmask[4]; /* Coprocessor registers used. */ - unsigned long fprmask; /* Floating pointer registers used. */ -}; - /* If the extern bit in a reloc is 1, then r_symndx is an index into the external symbol table. If the extern bit is 0, then r_symndx indicates a section, and is one of the following values. */ @@ -105,6 +88,8 @@ struct ecoff_reginfo #define RELOC_SECTION_LITA 13 #define RELOC_SECTION_ABS 14 +#define NUM_RELOC_SECTIONS 15 + /********************** STABS **********************/ /* gcc uses mips-tfile to output type information in special stabs @@ -146,42 +131,42 @@ struct tir_ext { unsigned char t_tq23[1]; }; -#define TIR_BITS1_FBITFIELD_BIG 0x80 -#define TIR_BITS1_FBITFIELD_LITTLE 0x01 +#define TIR_BITS1_FBITFIELD_BIG ((unsigned int) 0x80) +#define TIR_BITS1_FBITFIELD_LITTLE ((unsigned int) 0x01) -#define TIR_BITS1_CONTINUED_BIG 0x40 -#define TIR_BITS1_CONTINUED_LITTLE 0x02 +#define TIR_BITS1_CONTINUED_BIG ((unsigned int) 0x40) +#define TIR_BITS1_CONTINUED_LITTLE ((unsigned int) 0x02) -#define TIR_BITS1_BT_BIG 0x3F +#define TIR_BITS1_BT_BIG ((unsigned int) 0x3F) #define TIR_BITS1_BT_SH_BIG 0 -#define TIR_BITS1_BT_LITTLE 0xFC +#define TIR_BITS1_BT_LITTLE ((unsigned int) 0xFC) #define TIR_BITS1_BT_SH_LITTLE 2 -#define TIR_BITS_TQ4_BIG 0xF0 +#define TIR_BITS_TQ4_BIG ((unsigned int) 0xF0) #define TIR_BITS_TQ4_SH_BIG 4 -#define TIR_BITS_TQ5_BIG 0x0F +#define TIR_BITS_TQ5_BIG ((unsigned int) 0x0F) #define TIR_BITS_TQ5_SH_BIG 0 -#define TIR_BITS_TQ4_LITTLE 0x0F +#define TIR_BITS_TQ4_LITTLE ((unsigned int) 0x0F) #define TIR_BITS_TQ4_SH_LITTLE 0 -#define TIR_BITS_TQ5_LITTLE 0xF0 +#define TIR_BITS_TQ5_LITTLE ((unsigned int) 0xF0) #define TIR_BITS_TQ5_SH_LITTLE 4 -#define TIR_BITS_TQ0_BIG 0xF0 +#define TIR_BITS_TQ0_BIG ((unsigned int) 0xF0) #define TIR_BITS_TQ0_SH_BIG 4 -#define TIR_BITS_TQ1_BIG 0x0F +#define TIR_BITS_TQ1_BIG ((unsigned int) 0x0F) #define TIR_BITS_TQ1_SH_BIG 0 -#define TIR_BITS_TQ0_LITTLE 0x0F +#define TIR_BITS_TQ0_LITTLE ((unsigned int) 0x0F) #define TIR_BITS_TQ0_SH_LITTLE 0 -#define TIR_BITS_TQ1_LITTLE 0xF0 +#define TIR_BITS_TQ1_LITTLE ((unsigned int) 0xF0) #define TIR_BITS_TQ1_SH_LITTLE 4 -#define TIR_BITS_TQ2_BIG 0xF0 +#define TIR_BITS_TQ2_BIG ((unsigned int) 0xF0) #define TIR_BITS_TQ2_SH_BIG 4 -#define TIR_BITS_TQ3_BIG 0x0F +#define TIR_BITS_TQ3_BIG ((unsigned int) 0x0F) #define TIR_BITS_TQ3_SH_BIG 0 -#define TIR_BITS_TQ2_LITTLE 0x0F +#define TIR_BITS_TQ2_LITTLE ((unsigned int) 0x0F) #define TIR_BITS_TQ2_SH_LITTLE 0 -#define TIR_BITS_TQ3_LITTLE 0xF0 +#define TIR_BITS_TQ3_LITTLE ((unsigned int) 0xF0) #define TIR_BITS_TQ3_SH_LITTLE 4 /* Relative symbol external record */ @@ -191,19 +176,19 @@ struct rndx_ext { }; #define RNDX_BITS0_RFD_SH_LEFT_BIG 4 -#define RNDX_BITS1_RFD_BIG 0xF0 +#define RNDX_BITS1_RFD_BIG ((unsigned int) 0xF0) #define RNDX_BITS1_RFD_SH_BIG 4 #define RNDX_BITS0_RFD_SH_LEFT_LITTLE 0 -#define RNDX_BITS1_RFD_LITTLE 0x0F +#define RNDX_BITS1_RFD_LITTLE ((unsigned int) 0x0F) #define RNDX_BITS1_RFD_SH_LEFT_LITTLE 8 -#define RNDX_BITS1_INDEX_BIG 0x0F +#define RNDX_BITS1_INDEX_BIG ((unsigned int) 0x0F) #define RNDX_BITS1_INDEX_SH_LEFT_BIG 16 #define RNDX_BITS2_INDEX_SH_LEFT_BIG 8 #define RNDX_BITS3_INDEX_SH_LEFT_BIG 0 -#define RNDX_BITS1_INDEX_LITTLE 0xF0 +#define RNDX_BITS1_INDEX_LITTLE ((unsigned int) 0xF0) #define RNDX_BITS1_INDEX_SH_LITTLE 4 #define RNDX_BITS2_INDEX_SH_LEFT_LITTLE 4 #define RNDX_BITS3_INDEX_SH_LEFT_LITTLE 12 @@ -249,14 +234,136 @@ union aux_ext { #define AUX_PUT_COUNT(bigend, val, ax) \ AUX_PUT_ANY ((bigend), (val), (ax), a_count) -/* Prototypes for the swapping functions. These require that sym.h be - included before this file. */ +/********************** SYMBOLS **********************/ -extern void ecoff_swap_tir_in PARAMS ((int bigend, struct tir_ext *, TIR *)); -extern void ecoff_swap_tir_out PARAMS ((int bigend, TIR *, struct tir_ext *)); -extern void ecoff_swap_rndx_in PARAMS ((int bigend, struct rndx_ext *, - RNDXR *)); -extern void ecoff_swap_rndx_out PARAMS ((int bigend, RNDXR *, - struct rndx_ext *)); +/* For efficiency, gdb deals directly with the unswapped symbolic + information (that way it only takes the time to swap information + that it really needs to read). gdb originally retrieved the + information directly from the BFD backend information, but that + strategy, besides being sort of ugly, does not work for MIPS ELF, + which also uses ECOFF debugging information. This structure holds + pointers to the (mostly) unswapped symbolic information. */ + +struct ecoff_debug_info +{ + /* The swapped ECOFF symbolic header. */ + HDRR symbolic_header; + + /* Pointers to the unswapped symbolic information. Note that the + pointers to external structures point to different sorts of + information on different ECOFF targets. The ecoff_debug_swap + structure provides the sizes of the structures and the functions + needed to swap the information in and out. These pointers are + all pointers to arrays, not single structures. They will be NULL + if there are no instances of the relevant structure. These + fields are also used by the assembler to output ECOFF debugging + information. */ + unsigned char *line; + PTR external_dnr; /* struct dnr_ext */ + PTR external_pdr; /* struct pdr_ext */ + PTR external_sym; /* struct sym_ext */ + PTR external_opt; /* struct opt_ext */ + union aux_ext *external_aux; + char *ss; + char *ssext; + PTR external_fdr; /* struct fdr_ext */ + PTR external_rfd; /* struct rfd_ext */ + PTR external_ext; /* struct ext_ext */ + + /* These fields are used when linking. They may disappear at some + point. */ + char *ssext_end; + PTR external_ext_end; + + /* When linking, this field holds a mapping from the input FDR + numbers to the output numbers, and is used when writing out the + external symbols. It is NULL if no mapping is required. */ + RFDT *ifdmap; + + /* The swapped FDR information. Currently this is never NULL, but + code using this structure should probably double-check in case + this changes in the future. This is a pointer to an array, not a + single structure. */ + FDR *fdr; + + /* When relaxing MIPS embedded PIC code, we may need to adjust + symbol values when they are output. This is a linked list of + structures indicating how values should be adjusted. There is no + requirement that the entries be in any order, or that they not + overlap. This field is normally NULL, in which case no + adjustments need to be made. */ + struct ecoff_value_adjust *adjust; +}; + +/* This structure describes how to adjust symbol values when + outputting MIPS embedded PIC code. These adjustments only apply to + the internal symbols, as the external symbol values will come from + the hash table and have already been adjusted. */ + +struct ecoff_value_adjust +{ + /* Next entry on adjustment list. */ + struct ecoff_value_adjust *next; + /* Starting VMA of adjustment. This is the VMA in the ECOFF file, + not the offset from the start of the section. Thus it should + indicate a particular section. */ + bfd_vma start; + /* Ending VMA of adjustment. */ + bfd_vma end; + /* Adjustment. This should be added to the value of the symbol, or + FDR. This is zero for the last entry in the array. */ + long adjust; +}; + +/********************** SWAPPING **********************/ + +/* The generic ECOFF code needs to be able to swap debugging + information in and out in the specific format used by a particular + ECOFF implementation. This structure provides the information + needed to do this. */ + +struct ecoff_debug_swap +{ + /* Symbol table magic number. */ + int sym_magic; + /* Alignment of debugging information. E.g., 4. */ + bfd_size_type debug_align; + /* Sizes of external symbolic information. */ + bfd_size_type external_hdr_size; + bfd_size_type external_dnr_size; + bfd_size_type external_pdr_size; + bfd_size_type external_sym_size; + bfd_size_type external_opt_size; + bfd_size_type external_fdr_size; + bfd_size_type external_rfd_size; + bfd_size_type external_ext_size; + /* Functions to swap in external symbolic data. */ + void (*swap_hdr_in) PARAMS ((bfd *, PTR, HDRR *)); + void (*swap_dnr_in) PARAMS ((bfd *, PTR, DNR *)); + void (*swap_pdr_in) PARAMS ((bfd *, PTR, PDR *)); + void (*swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)); + void (*swap_opt_in) PARAMS ((bfd *, PTR, OPTR *)); + void (*swap_fdr_in) PARAMS ((bfd *, PTR, FDR *)); + void (*swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *)); + void (*swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)); + void (*swap_tir_in) PARAMS ((int, const struct tir_ext *, TIR *)); + void (*swap_rndx_in) PARAMS ((int, const struct rndx_ext *, RNDXR *)); + /* Functions to swap out external symbolic data. */ + void (*swap_hdr_out) PARAMS ((bfd *, const HDRR *, PTR)); + void (*swap_dnr_out) PARAMS ((bfd *, const DNR *, PTR)); + void (*swap_pdr_out) PARAMS ((bfd *, const PDR *, PTR)); + void (*swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR)); + void (*swap_opt_out) PARAMS ((bfd *, const OPTR *, PTR)); + void (*swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR)); + void (*swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR)); + void (*swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR)); + void (*swap_tir_out) PARAMS ((int, const TIR *, struct tir_ext *)); + void (*swap_rndx_out) PARAMS ((int, const RNDXR *, struct rndx_ext *)); + /* Function to read symbol data and set up pointers in + ecoff_debug_info structure. The section argument is used for + ELF, not straight ECOFF. */ + boolean (*read_debug_info) PARAMS ((bfd *, asection *, + struct ecoff_debug_info *)); +}; #endif /* ! defined (ECOFF_H) */ diff --git a/gnu/usr.bin/gdb/gdb/coff/internal.h b/gnu/usr.bin/gdb/gdb/coff/internal.h index e8cf98470cfb..53f73ac4cf57 100644 --- a/gnu/usr.bin/gdb/gdb/coff/internal.h +++ b/gnu/usr.bin/gdb/gdb/coff/internal.h @@ -78,9 +78,9 @@ struct internal_aouthdr unsigned long fprmask; /* Floating pointer registers used. */ /* Apollo stuff */ - long o_inlib; - long o_sri; - long vid[2]; + long o_inlib; /* inlib data */ + long o_sri; /* Static Resource Information */ + long vid[2]; /* Version id */ }; /********************** STORAGE CLASSES **********************/ @@ -365,7 +365,11 @@ union internal_auxent ******************************************/ struct { - long x_scnlen; /* csect length */ + union + { /* csect length or enclosing csect */ + long l; + struct coff_ptr_struct *p; + } x_scnlen; long x_parmhash; /* parm type hash index */ unsigned short x_snhash; /* sect num with parm hash */ unsigned char x_smtyp; /* symbol align and type */ @@ -440,7 +444,7 @@ struct internal_reloc unsigned short r_type; /* Relocation type */ unsigned char r_size; /* Used by RS/6000 and ECOFF */ unsigned char r_extern; /* Used by ECOFF */ - unsigned long r_offset; /* Used by RS/6000 and ECOFF */ + unsigned long r_offset; /* Used by Alpha ECOFF, SPARC, others */ }; #define R_RELBYTE 017 @@ -499,7 +503,7 @@ struct internal_reloc #define R_CALLR 0x05 /* callr 12 bit disp */ #define R_SEG 0x10 /* set if in segmented mode */ #define R_IMM4H 0x24 /* high nibble */ - +#define R_DISP7 0x25 /* djnz displacement */ /* H8500 modes */ @@ -533,6 +537,6 @@ struct internal_reloc #define R_SH_IMM4BY4 21 #define R_SH_PCRELIMM8BY2 22 #define R_SH_PCRELIMM8BY4 23 - +#define R_SH_IMM16 24 /* 16 bit immediate */ diff --git a/gnu/usr.bin/gdb/gdb/coff/sym.h b/gnu/usr.bin/gdb/gdb/coff/sym.h index 990eeacc6809..93bb3a1583cd 100644 --- a/gnu/usr.bin/gdb/gdb/coff/sym.h +++ b/gnu/usr.bin/gdb/gdb/coff/sym.h @@ -184,7 +184,7 @@ typedef struct pdr { * for use by the static exception system. */ typedef struct runtime_pdr { - unsigned long adr; /* memory address of start of procedure */ + bfd_vma adr; /* memory address of start of procedure */ long regmask; /* save register mask */ long regoffset; /* save register offset */ long fregmask; /* save floating point register mask */ @@ -224,7 +224,7 @@ typedef long LINER, *pLINER; typedef struct { long iss; /* index into String Space of name */ - long value; /* value of symbol */ + bfd_vma value; /* value of symbol */ unsigned st : 6; /* symbol type */ unsigned sc : 5; /* storage class - text, data, etc */ unsigned reserved : 1; /* reserved */ @@ -248,7 +248,7 @@ typedef struct { * Same as the SYMR except it contains file context to determine where * the index is. */ -typedef struct { +typedef struct ecoff_extr { unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */ unsigned cobol_main:1; /* symbol is a cobol main procedure */ unsigned weakext:1; /* symbol is weak external */ diff --git a/gnu/usr.bin/gdb/gdb/coff/symconst.h b/gnu/usr.bin/gdb/gdb/coff/symconst.h index e4ed620131dc..46d68e8a1e56 100644 --- a/gnu/usr.bin/gdb/gdb/coff/symconst.h +++ b/gnu/usr.bin/gdb/gdb/coff/symconst.h @@ -112,7 +112,8 @@ #define stStruct 26 /* Beginning of block defining a struct type */ #define stUnion 27 /* Beginning of block defining a union type */ #define stEnum 28 /* Beginning of block defining an enum type */ - /* Psuedo-symbols - internal to debugger */ +#define stIndirect 34 /* Indirect type specification */ + /* Pseudo-symbols - internal to debugger */ #define stStr 60 /* string */ #define stNumber 61 /* pure number (ie. 4 NOR 2+2) */ #define stExpr 62 /* 2+2 vs. 4 */ diff --git a/gnu/usr.bin/gdb/gdb/coffread.c b/gnu/usr.bin/gdb/gdb/coffread.c index eb0905b867ac..dfc2d3be6403 100644 --- a/gnu/usr.bin/gdb/gdb/coffread.c +++ b/gnu/usr.bin/gdb/gdb/coffread.c @@ -1,6 +1,6 @@ /* Read coff symbol tables and convert to internal format, for GDB. Contributed by David D. Johnson, Brown University (ddj@cs.brown.edu). - Copyright 1987, 1988, 1989, 1990, 1991, 1992, 1993 + Copyright 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -23,12 +23,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "symtab.h" #include "gdbtypes.h" #include "breakpoint.h" + #include "bfd.h" -#include "symfile.h" -#include "objfiles.h" -#include "buildsym.h" -#include "gdb-stabs.h" -#include "complaints.h" #include #include @@ -39,6 +35,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "coff/internal.h" /* Internal format of COFF symbols in BFD */ #include "libcoff.h" /* FIXME secret internal data from BFD */ +#include "symfile.h" +#include "objfiles.h" +#include "buildsym.h" +#include "gdb-stabs.h" +#include "stabsread.h" +#include "complaints.h" + struct coff_symfile_info { file_ptr min_lineno_offset; /* Where in file lowest line#s are */ file_ptr max_lineno_offset; /* 1+last byte of line#s in file */ @@ -75,13 +78,10 @@ struct coff_symfile_info { static CORE_ADDR cur_src_start_addr; static CORE_ADDR cur_src_end_addr; -/* Core address of the end of the first object file. */ -static CORE_ADDR first_object_file_end; - /* The addresses of the symbol table stream and number of symbols of the object file we are reading (as copied into core). */ -static FILE *nlist_stream_global; +static GDB_FILE *nlist_stream_global; static int nlist_nsyms_global; /* Vector of line number information. */ @@ -143,8 +143,6 @@ static struct symbol *opaque_type_chain[HASHSIZE]; struct type *in_function_type; #endif -struct pending_block *pending_blocks; - /* Complaints about various problems in the file being read */ struct complaint ef_complaint = @@ -223,9 +221,6 @@ free_linetab PARAMS ((void)); static int init_lineno PARAMS ((int, long, int)); -static char * -getfilename PARAMS ((union internal_auxent *)); - static char * getsymname PARAMS ((struct internal_syment *)); @@ -257,8 +252,8 @@ coff_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int)); static void coff_symfile_finish PARAMS ((struct objfile *)); -static void -record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type)); +static void record_minimal_symbol + PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type, struct objfile *)); static void coff_end_symtab PARAMS ((struct objfile *)); @@ -483,15 +478,17 @@ coff_end_symtab (objfile) } static void -record_minimal_symbol (name, address, type) +record_minimal_symbol (name, address, type, objfile) char *name; CORE_ADDR address; enum minimal_symbol_type type; + struct objfile *objfile; { /* We don't want TDESC entry points in the minimal symbol table */ if (name[0] == '@') return; - prim_record_minimal_symbol (savestring (name, strlen (name)), address, type); + prim_record_minimal_symbol (savestring (name, strlen (name)), address, type, + objfile); } /* coff_symfile_init () @@ -513,7 +510,7 @@ static void coff_symfile_init (objfile) struct objfile *objfile; { - asection *section, *strsection; + asection *section; bfd *abfd = objfile->obfd; /* Allocate struct to keep track of stab reading. */ @@ -609,7 +606,7 @@ coff_symfile_read (objfile, section_offsets, mainline) symfile_bfd = abfd; /* Kludge for swap routines */ /* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */ - desc = fileno ((FILE *)(abfd->iostream)); /* File descriptor */ + desc = fileno ((GDB_FILE *)(abfd->iostream)); /* File descriptor */ num_symbols = bfd_get_symcount (abfd); /* How many syms */ symtab_offset = cdata->sym_filepos; /* Symbol table file offset */ stringtab_offset = symtab_offset + /* String table file offset */ @@ -662,7 +659,13 @@ coff_symfile_read (objfile, section_offsets, mainline) /* Sort symbols alphabetically within each block. */ - sort_all_symtab_syms (); + { + struct symtab *s; + for (s = objfile -> symtabs; s != NULL; s = s -> next) + { + sort_symtab_syms (s); + } + } /* Install any minimal symbols that have been collected as the current minimal symbols for this objfile. */ @@ -675,7 +678,7 @@ coff_symfile_read (objfile, section_offsets, mainline) { /* FIXME: dubious. Why can't we use something normal like bfd_get_section_contents? */ - fseek ((FILE *) abfd->iostream, abfd->where, 0); + fseek ((GDB_FILE *) abfd->iostream, abfd->where, 0); stabsize = bfd_section_size (abfd, info->stabsect); stabstrsize = bfd_section_size (abfd, info->stabstrsect); @@ -723,7 +726,7 @@ read_coff_symtab (symtab_offset, nsyms, objfile) int nsyms; struct objfile *objfile; { - FILE *stream; + GDB_FILE *stream; register struct context_stack *new; struct coff_symbol coff_symbol; register struct coff_symbol *cs = &coff_symbol; @@ -736,7 +739,6 @@ read_coff_symtab (symtab_offset, nsyms, objfile) /* A .file is open. */ int in_source_file = 0; - int num_object_files = 0; int next_file_symnum = -1; /* Name of the current file. */ @@ -807,7 +809,7 @@ read_coff_symtab (symtab_offset, nsyms, objfile) coff_end_symtab (objfile); coff_start_symtab (); - complete_symtab ("_globals_", 0, first_object_file_end); + complete_symtab ("_globals_", 0, 0); /* done with all files, everything from here on out is globals */ } @@ -820,7 +822,7 @@ read_coff_symtab (symtab_offset, nsyms, objfile) if (ISFCN (cs->c_type) && cs->c_sclass != C_TPDEF) { /* Record all functions -- external and static -- in minsyms. */ - record_minimal_symbol (cs->c_name, cs->c_value, mst_text); + record_minimal_symbol (cs->c_name, cs->c_value, mst_text, objfile); fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr; fcn_start_addr = cs->c_value; @@ -849,7 +851,7 @@ read_coff_symtab (symtab_offset, nsyms, objfile) */ next_file_symnum = cs->c_value; if (cs->c_naux > 0) - filestring = getfilename (&main_aux); + filestring = coff_getfilename (&main_aux); else filestring = ""; @@ -870,11 +872,6 @@ read_coff_symtab (symtab_offset, nsyms, objfile) if (STREQ (cs->c_name, ".text")) { /* FIXME: don't wire in ".text" as section name or symbol name! */ - if (++num_object_files == 1) { - /* last address of startup file */ - first_object_file_end = cs->c_value + - main_aux.x_scn.x_scnlen; - } /* Check for in_source_file deals with case of a file with debugging symbols followed by a later file with no symbols. */ @@ -901,29 +898,32 @@ read_coff_symtab (symtab_offset, nsyms, objfile) break; /* fall in for static symbols that don't start with '.' */ case C_EXT: - /* Record external symbols in minsyms if we don't have debug - info for them. FIXME, this is probably the wrong thing - to do. Why don't we record them even if we do have - debug symbol info? What really belongs in the minsyms - anyway? Fred!?? */ - if (!SDB_TYPE (cs->c_type)) { - /* FIXME: This is BOGUS Will Robinson! - Coff should provide the SEC_CODE flag for executable sections, - then if we could look up sections by section number we - could see if the flags indicate SEC_CODE. If so, then - record this symbol as a function in the minimal symbol table. - But why are absolute syms recorded as functions, anyway? */ - if (cs->c_secnum <= text_bfd_scnum+1) {/* text or abs */ - record_minimal_symbol (cs->c_name, cs->c_value, - mst_text); - break; - } else { - record_minimal_symbol (cs->c_name, cs->c_value, - mst_data); - break; - } - } - process_coff_symbol (cs, &main_aux, objfile); + /* Record it in the minimal symbols regardless of SDB_TYPE. + This parallels what we do for other debug formats, and + probably is needed to make print_address_symbolic work right + without the "set fast-symbolic-addr off" kludge. */ + + /* FIXME: This bogusly assumes the sections are in a certain + order, text (SEC_CODE) sections are before data sections, + etc. */ + if (cs->c_secnum <= text_bfd_scnum+1) + { + /* text or absolute. (FIXME, should use mst_abs if + absolute). */ + record_minimal_symbol + (cs->c_name, cs->c_value, + cs->c_sclass == C_STAT ? mst_file_text : mst_text, + objfile); + } + else + { + record_minimal_symbol + (cs->c_name, cs->c_value, + cs->c_sclass == C_STAT ? mst_file_data : mst_data, + objfile); + } + if (SDB_TYPE (cs->c_type)) + process_coff_symbol (cs, &main_aux, objfile); break; case C_FCN: @@ -1119,7 +1119,7 @@ read_one_sym (cs, sym, aux) { fread (temp_aux, local_auxesz, 1, nlist_stream_global); bfd_coff_swap_aux_in (symfile_bfd, temp_aux, sym->n_type, sym->n_sclass, - (char *)aux); + 0, cs->c_naux, (char *)aux); /* If more than one aux entry, read past it (only the first aux is important). */ for (i = 1; i < cs->c_naux; i++) @@ -1151,6 +1151,11 @@ init_stringtab (chan, offset) free_stringtab (); + /* If the file is stripped, the offset might be zero, indicating no + string table. Just return with `stringtab' set to null. */ + if (offset == 0) + return 0; + if (lseek (chan, offset, 0) < 0) return -1; @@ -1206,8 +1211,8 @@ getsymname (symbol_entry) only the last component of the name. Result is in static storage and is only good for temporary use. */ -static char * -getfilename (aux_entry) +char * +coff_getfilename (aux_entry) union internal_auxent *aux_entry; { static char buffer[BUFSIZ]; @@ -1413,7 +1418,6 @@ process_coff_symbol (cs, aux, objfile) = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); char *name; - struct type *temptype; memset (sym, 0, sizeof (struct symbol)); name = cs->c_name; @@ -1503,17 +1507,21 @@ process_coff_symbol (cs, aux, objfile) #endif add_symbol_to_list (sym, &local_symbols); #if !defined (BELIEVE_PCC_PROMOTION) && (TARGET_BYTE_ORDER == BIG_ENDIAN) - /* If PCC says a parameter is a short or a char, - aligned on an int boundary, realign it to the "little end" - of the int. */ - temptype = lookup_fundamental_type (current_objfile, FT_INTEGER); - if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (temptype) - && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT - && 0 == SYMBOL_VALUE (sym) % TYPE_LENGTH (temptype)) + { + /* If PCC says a parameter is a short or a char, + aligned on an int boundary, realign it to the "little end" + of the int. */ + struct type *temptype; + temptype = lookup_fundamental_type (current_objfile, FT_INTEGER); + if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (temptype) + && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT + && 0 == SYMBOL_VALUE (sym) % TYPE_LENGTH (temptype)) { - SYMBOL_VALUE (sym) += TYPE_LENGTH (temptype) - - TYPE_LENGTH (SYMBOL_TYPE (sym)); + SYMBOL_VALUE (sym) += + TYPE_LENGTH (temptype) + - TYPE_LENGTH (SYMBOL_TYPE (sym)); } + } #endif break; @@ -1524,17 +1532,22 @@ process_coff_symbol (cs, aux, objfile) #if !defined (BELIEVE_PCC_PROMOTION) /* FIXME: This should retain the current type, since it's just a register value. gnu@adobe, 26Feb93 */ - /* If PCC says a parameter is a short or a char, - it is really an int. */ - temptype = lookup_fundamental_type (current_objfile, FT_INTEGER); - if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (temptype) - && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT) - { - SYMBOL_TYPE (sym) = TYPE_UNSIGNED (SYMBOL_TYPE (sym)) - ? lookup_fundamental_type (current_objfile, - FT_UNSIGNED_INTEGER) - : temptype; - } + { + /* If PCC says a parameter is a short or a char, + it is really an int. */ + struct type *temptype; + temptype = + lookup_fundamental_type (current_objfile, FT_INTEGER); + if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (temptype) + && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT) + { + SYMBOL_TYPE (sym) = + (TYPE_UNSIGNED (SYMBOL_TYPE (sym)) + ? lookup_fundamental_type (current_objfile, + FT_UNSIGNED_INTEGER) + : temptype); + } + } #endif break; @@ -1544,7 +1557,34 @@ process_coff_symbol (cs, aux, objfile) /* If type has no name, give it one */ if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) = concat (SYMBOL_NAME (sym), NULL); + { + if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR + || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FUNC) + { + /* If we are giving a name to a type such as "pointer to + foo" or "function returning foo", we better not set + the TYPE_NAME. If the program contains "typedef char + *caddr_t;", we don't want all variables of type char + * to print as caddr_t. This is not just a + consequence of GDB's type management; CC and GCC (at + least through version 2.4) both output variables of + either type char * or caddr_t with the type + refering to the C_TPDEF symbol for caddr_t. If a future + compiler cleans this up it GDB is not ready for it + yet, but if it becomes ready we somehow need to + disable this check (without breaking the PCC/GCC2.4 + case). + + Sigh. + + Fortunately, this check seems not to be necessary + for anything except pointers or functions. */ + ; + } + else + TYPE_NAME (SYMBOL_TYPE (sym)) = + concat (SYMBOL_NAME (sym), NULL); + } /* Keep track of any type which points to empty structured type, so it can be filled from a definition from another file. A @@ -2018,16 +2058,6 @@ coff_read_enum_type (index, length, lastsym) break; } -#if 0 - /* This screws up perfectly good C programs with enums. FIXME. */ - /* Is this Modula-2's BOOLEAN type? Flag it as such if so. */ - if(TYPE_NFIELDS(type) == 2 && - ((STREQ(TYPE_FIELD_NAME(type,0),"TRUE") && - STREQ(TYPE_FIELD_NAME(type,1),"FALSE")) || - (STREQ(TYPE_FIELD_NAME(type,1),"TRUE") && - STREQ(TYPE_FIELD_NAME(type,0),"FALSE")))) - TYPE_CODE(type) = TYPE_CODE_BOOL; -#endif return type; } @@ -2038,11 +2068,12 @@ coff_symfile_offsets (objfile, addr) { struct section_offsets *section_offsets; int i; - + + objfile->num_sections = SECT_OFF_MAX; section_offsets = (struct section_offsets *) obstack_alloc (&objfile -> psymbol_obstack, - sizeof (struct section_offsets) + - sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1)); + sizeof (struct section_offsets) + + sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1)); for (i = 0; i < SECT_OFF_MAX; i++) ANOFFSET (section_offsets, i) = addr; @@ -2054,8 +2085,7 @@ coff_symfile_offsets (objfile, addr) static struct sym_fns coff_sym_fns = { - "coff", /* sym_name: name or name prefix of BFD target type */ - 4, /* sym_namelen: number of significant sym_name chars */ + bfd_target_coff_flavour, coff_new_init, /* sym_new_init: init anything gbl to entire symtab */ coff_symfile_init, /* sym_init: read initial info, setup for sym_read() */ coff_symfile_read, /* sym_read: read a symbol file into symtab */ diff --git a/gnu/usr.bin/gdb/gdb/command.c b/gnu/usr.bin/gdb/gdb/command.c index abc2d84499c0..f2af0d5aa129 100644 --- a/gnu/usr.bin/gdb/gdb/command.c +++ b/gnu/usr.bin/gdb/gdb/command.c @@ -31,7 +31,7 @@ static void show_user PARAMS ((char *, int)); static void -show_user_1 PARAMS ((struct cmd_list_element *, FILE *)); +show_user_1 PARAMS ((struct cmd_list_element *, GDB_FILE *)); static void make_command PARAMS ((char *, int)); @@ -43,7 +43,7 @@ static int parse_binary_operation PARAMS ((char *)); static void -print_doc_line PARAMS ((FILE *, char *)); +print_doc_line PARAMS ((GDB_FILE *, char *)); /* Add element named NAME. CLASS is the top level category into which commands are broken down @@ -190,7 +190,7 @@ add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname, return c; } -/* ARGSUSED */ +/* This is an empty "cfunc". */ void not_just_help_class_command (args, from_tty) char *args; @@ -198,6 +198,17 @@ not_just_help_class_command (args, from_tty) { } +/* This is an empty "sfunc". */ +static void empty_sfunc PARAMS ((char *, int, struct cmd_list_element *)); + +static void +empty_sfunc (args, from_tty, c) + char *args; + int from_tty; + struct cmd_list_element *c; +{ +} + /* Add element named NAME to command list LIST (the list for set or some sublist thereof). CLASS is as in add_cmd. @@ -214,17 +225,15 @@ add_set_cmd (name, class, var_type, var, doc, list) char *doc; struct cmd_list_element **list; { - /* For set/show, we have to call do_setshow_command - differently than an ordinary function (take commandlist as - well as arg), so the function field isn't helpful. However, - function == NULL means that it's a help class, so set the function - to not_just_help_class_command. */ struct cmd_list_element *c - = add_cmd (name, class, not_just_help_class_command, doc, list); + = add_cmd (name, class, NO_FUNCTION, doc, list); c->type = set_cmd; c->var_type = var_type; c->var = var; + /* This needs to be something besides NO_FUNCTION so that this isn't + treated as a help class. */ + c->function.sfunc = empty_sfunc; return c; } @@ -247,7 +256,7 @@ add_show_from_set (setcmd, list) && setcmd->doc[2] == 't' && setcmd->doc[3] == ' ') showcmd->doc = concat ("Show ", setcmd->doc + 4, NULL); else - fprintf (stderr, "GDB internal error: Bad docstring for set command\n"); + fprintf_unfiltered (gdb_stderr, "GDB internal error: Bad docstring for set command\n"); showcmd->next = *list; *list = showcmd; @@ -303,7 +312,7 @@ delete_cmd (name, list) void help_cmd (command, stream) char *command; - FILE *stream; + GDB_FILE *stream; { struct cmd_list_element *c; extern struct cmd_list_element *cmdlist; @@ -368,7 +377,7 @@ help_list (list, cmdtype, class, stream) struct cmd_list_element *list; char *cmdtype; enum command_class class; - FILE *stream; + GDB_FILE *stream; { int len; char *cmdtype1, *cmdtype2; @@ -409,7 +418,7 @@ Command name abbreviations are allowed if unambiguous.\n", /* Print only the first line of STR on STREAM. */ static void print_doc_line (stream, str) - FILE *stream; + GDB_FILE *stream; char *str; { static char *line_buffer = 0; @@ -460,7 +469,7 @@ help_cmd_list (list, class, prefix, recurse, stream) enum command_class class; char *prefix; int recurse; - FILE *stream; + GDB_FILE *stream; { register struct cmd_list_element *c; @@ -675,12 +684,15 @@ lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes) struct cmd_list_element *last_list = 0; struct cmd_list_element *c = lookup_cmd_1 (line, list, &last_list, ignore_help_classes); +#if 0 + /* This is wrong for complete_command. */ char *ptr = (*line) + strlen (*line) - 1; /* Clear off trailing whitespace. */ while (ptr >= *line && (*ptr == ' ' || *ptr == '\t')) ptr--; *(ptr + 1) = '\0'; +#endif if (!c) { @@ -1041,6 +1053,11 @@ do_setshow_command (arg, from_tty, c) { /* \ at end of argument is used after spaces so they won't be lost. */ + /* This is obsolete now that we no longer strip + trailing whitespace and actually, the backslash + didn't get here in my test, readline or + something did something funky with a backslash + right before a newline. */ if (*p == 0) break; ch = parse_escape (&p); @@ -1052,8 +1069,10 @@ do_setshow_command (arg, from_tty, c) else *q++ = ch; } +#if 0 if (*(p - 1) != '\\') *q++ = ' '; +#endif *q++ = '\0'; new = (char *) xrealloc (new, q - new); if (*(char **)c->var != NULL) @@ -1111,52 +1130,52 @@ do_setshow_command (arg, from_tty, c) else if (c->type == show_cmd) { /* Print doc minus "show" at start. */ - print_doc_line (stdout, c->doc + 5); + print_doc_line (gdb_stdout, c->doc + 5); - fputs_filtered (" is ", stdout); + fputs_filtered (" is ", gdb_stdout); wrap_here (" "); switch (c->var_type) { case var_string: { unsigned char *p; - fputs_filtered ("\"", stdout); + fputs_filtered ("\"", gdb_stdout); for (p = *(unsigned char **) c->var; *p != '\0'; p++) - gdb_printchar (*p, stdout, '"'); - fputs_filtered ("\"", stdout); + gdb_printchar (*p, gdb_stdout, '"'); + fputs_filtered ("\"", gdb_stdout); } break; case var_string_noescape: case var_filename: - fputs_filtered ("\"", stdout); - fputs_filtered (*(char **) c->var, stdout); - fputs_filtered ("\"", stdout); + fputs_filtered ("\"", gdb_stdout); + fputs_filtered (*(char **) c->var, gdb_stdout); + fputs_filtered ("\"", gdb_stdout); break; case var_boolean: - fputs_filtered (*(int *) c->var ? "on" : "off", stdout); + fputs_filtered (*(int *) c->var ? "on" : "off", gdb_stdout); break; case var_uinteger: if (*(unsigned int *) c->var == UINT_MAX) { - fputs_filtered ("unlimited", stdout); + fputs_filtered ("unlimited", gdb_stdout); break; } /* else fall through */ case var_zinteger: - fprintf_filtered (stdout, "%u", *(unsigned int *) c->var); + fprintf_filtered (gdb_stdout, "%u", *(unsigned int *) c->var); break; case var_integer: if (*(int *) c->var == INT_MAX) { - fputs_filtered ("unlimited", stdout); + fputs_filtered ("unlimited", gdb_stdout); } else - fprintf_filtered (stdout, "%d", *(int *) c->var); + fprintf_filtered (gdb_stdout, "%d", *(int *) c->var); break; default: error ("gdb internal error: bad var_type in do_setshow_command"); } - fputs_filtered (".\n", stdout); + fputs_filtered (".\n", gdb_stdout); } else error ("gdb internal error: bad cmd_type in do_setshow_command"); @@ -1178,9 +1197,9 @@ cmd_show_list (list, from_tty, prefix) cmd_show_list (*list->prefixlist, from_tty, list->prefixname + 5); if (list->type == show_cmd) { - fputs_filtered (prefix, stdout); - fputs_filtered (list->name, stdout); - fputs_filtered (": ", stdout); + fputs_filtered (prefix, gdb_stdout); + fputs_filtered (list->name, gdb_stdout); + fputs_filtered (": ", gdb_stdout); do_setshow_command ((char *)NULL, from_tty, list); } } @@ -1216,8 +1235,10 @@ shell_escape (arg, from_tty) else execl (user_shell, p, "-c", arg, 0); - fprintf (stderr, "Exec of shell failed\n"); - exit (0); + fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", user_shell, + safe_strerror (errno)); + gdb_flush (gdb_stderr); + _exit (0177); } if (pid != -1) @@ -1250,7 +1271,7 @@ make_command (arg, from_tty) static void show_user_1 (c, stream) struct cmd_list_element *c; - FILE *stream; + GDB_FILE *stream; { register struct command_line *cmdlines; @@ -1283,14 +1304,14 @@ show_user (args, from_tty) c = lookup_cmd (&args, cmdlist, "", 0, 1); if (c->class != class_user) error ("Not a user command."); - show_user_1 (c, stdout); + show_user_1 (c, gdb_stdout); } else { for (c = cmdlist; c; c = c->next) { if (c->class == class_user) - show_user_1 (c, stdout); + show_user_1 (c, gdb_stdout); } } } diff --git a/gnu/usr.bin/gdb/gdb/command.h b/gnu/usr.bin/gdb/gdb/command.h index ee587c30659d..360d78a4a453 100644 --- a/gnu/usr.bin/gdb/gdb/command.h +++ b/gnu/usr.bin/gdb/gdb/command.h @@ -69,13 +69,18 @@ struct cmd_list_element enum command_class class; /* Function definition of this command. - Zero for command class names and for help topics that + NO_FUNCTION for command class names and for help topics that are not really commands. */ - union { + union + { + /* If type is not_set_cmd, call it like this: */ void (*cfunc) PARAMS ((char *args, int from_tty)); + + /* If type is cmd_set or show_cmd, first set the variables, and + then call this. */ void (*sfunc) PARAMS ((char *args, int from_tty, struct cmd_list_element *c)); - } function; + } function; # define NO_FUNCTION ((void (*) PARAMS((char *args, int from_tty))) 0) /* Documentation of this command (or help topic). @@ -194,15 +199,15 @@ extern void delete_cmd PARAMS ((char *, struct cmd_list_element **)); extern void -help_cmd PARAMS ((char *, FILE *)); +help_cmd PARAMS ((char *, GDB_FILE *)); extern void help_list PARAMS ((struct cmd_list_element *, char *, enum command_class, - FILE *)); + GDB_FILE *)); extern void help_cmd_list PARAMS ((struct cmd_list_element *, enum command_class, char *, - int, FILE *)); + int, GDB_FILE *)); extern struct cmd_list_element * add_set_cmd PARAMS ((char *, enum command_class, var_types, char *, char *, diff --git a/gnu/usr.bin/gdb/gdb/complaints.c b/gnu/usr.bin/gdb/gdb/complaints.c index 079ca5adc643..e441db4218d7 100644 --- a/gnu/usr.bin/gdb/gdb/complaints.c +++ b/gnu/usr.bin/gdb/gdb/complaints.c @@ -112,7 +112,7 @@ complain (va_alist) /* If GDB dumps core, we'd like to see the complaints first. Presumably GDB will not be sending so many complaints that this becomes a performance hog. */ - fflush (stdout); + gdb_flush (gdb_stdout); va_end (args); } diff --git a/gnu/usr.bin/gdb/gdb/core.c b/gnu/usr.bin/gdb/gdb/core.c index 36c9ab5e75a0..974e55c1859d 100644 --- a/gnu/usr.bin/gdb/gdb/core.c +++ b/gnu/usr.bin/gdb/gdb/core.c @@ -1,5 +1,6 @@ /* Core dump and executable file functions above target vector, for GDB. - Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc. + Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -18,6 +19,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" +#include #include #include #include @@ -30,6 +32,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "target.h" #include "gdbcore.h" #include "dis-asm.h" +#include "language.h" extern char registers[]; @@ -135,19 +138,24 @@ memory_error (status, memaddr) int status; CORE_ADDR memaddr; { - if (status == EIO) { /* Actually, address between memaddr and memaddr + len was out of bounds. */ - error ("Cannot access memory at address %s.", - local_hex_string((unsigned long) memaddr)); + error_begin (); + printf_filtered ("Cannot access memory at address "); + print_address_numeric (memaddr, 1, gdb_stdout); + printf_filtered (".\n"); + return_to_top_level (RETURN_ERROR); } else { - error ("Error accessing memory address %s: %s.", - local_hex_string ((unsigned long) memaddr), - safe_strerror (status)); + error_begin (); + printf_filtered ("Error accessing memory address "); + print_address_numeric (memaddr, 1, gdb_stdout); + printf_filtered (": %s.\n", + safe_strerror (status)); + return_to_top_level (RETURN_ERROR); } } @@ -233,6 +241,46 @@ read_memory_unsigned_integer (memaddr, len) return extract_unsigned_integer (buf, len); } +#if 0 +/* Enable after 4.12. It is not tested. */ + +/* Search code. Targets can just make this their search function, or + if the protocol has a less general search function, they can call this + in the cases it can't handle. */ +void +generic_search (len, data, mask, startaddr, increment, lorange, hirange + addr_found, data_found) + int len; + char *data; + char *mask; + CORE_ADDR startaddr; + int increment; + CORE_ADDR lorange; + CORE_ADDR hirange; + CORE_ADDR *addr_found; + char *data_found; +{ + int i; + CORE_ADDR curaddr = startaddr; + + while (curaddr >= lorange && curaddr < hirange) + { + read_memory (curaddr, data_found, len); + for (i = 0; i < len; ++i) + if ((data_found[i] & mask[i]) != data[i]) + goto try_again; + /* It matches. */ + *addr_found = curaddr; + return; + + try_again: + curaddr += increment; + } + *addr_found = (CORE_ADDR)0; + return; +} +#endif /* 0 */ + /* The current default bfd target. Points to storage allocated for gnutarget_string. */ char *gnutarget; diff --git a/gnu/usr.bin/gdb/gdb/coredep.c b/gnu/usr.bin/gdb/gdb/coredep.c index d94fd9820c9d..e27d2e48ba6a 100644 --- a/gnu/usr.bin/gdb/gdb/coredep.c +++ b/gnu/usr.bin/gdb/gdb/coredep.c @@ -24,6 +24,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "gdbcore.h" +#include "value.h" /* For supply_register. */ +#include "inferior.h" /* These are needed on various systems to expand REGISTER_U_ADDR. */ #ifndef USG @@ -40,6 +42,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #endif /* NO_PTRACE_H */ #endif +#ifndef CORE_REGISTER_ADDR +#define CORE_REGISTER_ADDR(regno, regptr) register_addr(regno, regptr) +#endif /* CORE_REGISTER_ADDR */ + #ifdef NEED_SYS_CORE_H #include #endif @@ -68,19 +74,20 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) register unsigned int addr; int bad_reg = -1; register reg_ptr = -reg_addr; /* Original u.u_ar0 is -reg_addr. */ + int numregs = ARCH_NUM_REGS; /* If u.u_ar0 was an absolute address in the core file, relativize it now, so we can use it as an offset into core_reg_sect. When we're done, "register 0" will be at core_reg_sect+reg_ptr, and we can use - register_addr to offset to the other registers. If this is a modern + CORE_REGISTER_ADDR to offset to the other registers. If this is a modern core file without a upage, reg_ptr will be zero and this is all a big NOP. */ if (reg_ptr > core_reg_size) reg_ptr -= KERNEL_U_ADDR; - for (regno = 0; regno < NUM_REGS; regno++) + for (regno = 0; regno < numregs; regno++) { - addr = register_addr (regno, reg_ptr); + addr = CORE_REGISTER_ADDR (regno, reg_ptr); if (addr >= core_reg_size) { if (bad_reg < 0) bad_reg = regno; @@ -107,7 +114,7 @@ register_addr (regno, blockend) { int addr; - if (regno < 0 || regno >= NUM_REGS) + if (regno < 0 || regno >= ARCH_NUM_REGS) error ("Invalid register number %d.", regno); REGISTER_U_ADDR (addr, blockend, regno); diff --git a/gnu/usr.bin/gdb/gdb/corelow.c b/gnu/usr.bin/gdb/gdb/corelow.c index 1cebc48985ec..cc0d4f0dcb9d 100644 --- a/gnu/usr.bin/gdb/gdb/corelow.c +++ b/gnu/usr.bin/gdb/gdb/corelow.c @@ -1,5 +1,6 @@ /* Core dump and executable file functions below target vector, for GDB. - Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc. + Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -18,6 +19,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" +#include #include #include #include @@ -28,6 +30,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" #include "target.h" #include "gdbcore.h" +#include "thread.h" static void core_files_info PARAMS ((struct target_ops *)); @@ -69,13 +72,14 @@ core_close (quitting) } #ifdef SOLIB_ADD -/* Stub function for catch_errors around shared library hacking. */ +/* Stub function for catch_errors around shared library hacking. FROM_TTYP + is really an int * which points to from_tty. */ static int -solib_add_stub (from_tty) - char *from_tty; +solib_add_stub (from_ttyp) + char *from_ttyp; { - SOLIB_ADD (NULL, (int)from_tty, &core_ops); + SOLIB_ADD (NULL, *(int *)from_ttyp, &core_ops); return 0; } #endif /* SOLIB_ADD */ @@ -151,7 +155,7 @@ core_open (filename, from_tty) { /* Do it after the err msg */ make_cleanup (bfd_close, temp_bfd); - error ("\"%s\" is not a core dump: %s", filename, bfd_errmsg(bfd_error)); + error ("\"%s\" is not a core dump: %s", filename, bfd_errmsg(bfd_get_error ())); } /* Looks semi-reasonable. Toss the old core file and work on the new. */ @@ -167,7 +171,7 @@ core_open (filename, from_tty) if (build_section_table (core_bfd, &core_ops.to_sections, &core_ops.to_sections_end)) error ("Can't find sections in `%s': %s", bfd_get_filename(core_bfd), - bfd_errmsg (bfd_error)); + bfd_errmsg (bfd_get_error ())); ontop = !push_target (&core_ops); discard_cleanups (old_chain); @@ -193,7 +197,7 @@ core_open (filename, from_tty) /* Add symbols and section mappings for any shared libraries */ #ifdef SOLIB_ADD - catch_errors (solib_add_stub, (char *)from_tty, (char *)0, + catch_errors (solib_add_stub, &from_tty, (char *)0, RETURN_MASK_ALL); #endif @@ -260,8 +264,8 @@ get_core_registers (regno) else { cant: - fprintf_filtered (stderr, "Couldn't fetch registers from core file: %s\n", - bfd_errmsg (bfd_error)); + fprintf_filtered (gdb_stderr, "Couldn't fetch registers from core file: %s\n", + bfd_errmsg (bfd_get_error ())); } /* Now do it again for the float registers, if they exist. */ @@ -277,8 +281,8 @@ get_core_registers (regno) } else { - fprintf_filtered (stderr, "Couldn't fetch register set 2 from core file: %s\n", - bfd_errmsg (bfd_error)); + fprintf_filtered (gdb_stderr, "Couldn't fetch register set 2 from core file: %s\n", + bfd_errmsg (bfd_get_error ())); } } registers_fetched(); @@ -299,6 +303,7 @@ ignore (addr, contents) CORE_ADDR addr; char *contents; { + return 0; } struct target_ops core_ops = { diff --git a/gnu/usr.bin/gdb/gdb/cp-valprint.c b/gnu/usr.bin/gdb/gdb/cp-valprint.c index 47b38f803d9b..af8d76725ed5 100644 --- a/gnu/usr.bin/gdb/gdb/cp-valprint.c +++ b/gnu/usr.bin/gdb/gdb/cp-valprint.c @@ -26,6 +26,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "command.h" #include "gdbcmd.h" #include "demangle.h" +#include "annotate.h" int vtblprint; /* Controls printing of vtbl's */ int objectprint; /* Controls looking up an object's derived type @@ -33,39 +34,30 @@ int objectprint; /* Controls looking up an object's derived type struct obstack dont_print_obstack; static void -cplus_print_value PARAMS ((struct type *, char *, FILE *, int, int, +cplus_print_value PARAMS ((struct type *, char *, GDB_FILE *, int, int, enum val_prettyprint, struct type **)); /* BEGIN-FIXME: Hooks into typeprint.c, find a better home for prototypes. */ extern void -c_type_print_base PARAMS ((struct type *, FILE *, int, int)); +c_type_print_base PARAMS ((struct type *, GDB_FILE *, int, int)); extern void -c_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int)); +c_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *, int, int)); extern void cp_type_print_method_args PARAMS ((struct type **, char *, char *, int, - FILE *)); + GDB_FILE *)); extern struct obstack dont_print_obstack; /* END-FIXME */ - -/* BEGIN-FIXME: Hooks into c-valprint.c */ - -extern int -c_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int, int, - enum val_prettyprint)); -/* END-FIXME */ - - void cp_print_class_method (valaddr, type, stream) char *valaddr; struct type *type; - FILE *stream; + GDB_FILE *stream; { struct type *domain; struct fn_field *f = NULL; @@ -136,7 +128,7 @@ cp_print_class_method (valaddr, type, stream) { fprintf_filtered (stream, "&"); c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); - fprintf (stream, kind); + fprintf_unfiltered (stream, kind); if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == CPLUS_MARKER) { @@ -159,6 +151,13 @@ cp_print_class_method (valaddr, type, stream) } } +/* This was what it was for gcc 2.4.5 and earlier. */ +static const char vtbl_ptr_name_old[] = + { CPLUS_MARKER,'v','t','b','l','_','p','t','r','_','t','y','p','e', 0 }; +/* It was changed to this after 2.4.5. */ +const char vtbl_ptr_name[] = + { '_','_','v','t','b','l','_','p','t','r','_','t','y','p','e', 0 }; + /* Return truth value for assertion that TYPE is of the type "pointer to virtual function". */ @@ -167,12 +166,6 @@ cp_is_vtbl_ptr_type(type) struct type *type; { char *typename = type_name_no_tag (type); - /* This was what it was for gcc 2.4.5 and earlier. */ - static const char vtbl_ptr_name_old[] = - { CPLUS_MARKER,'v','t','b','l','_','p','t','r','_','t','y','p','e', 0 }; - /* It was changed to this after 2.4.5. */ - static const char vtbl_ptr_name[] = - { '_','_','v','t','b','l','_','p','t','r','_','t','y','p','e', 0 }; return (typename != NULL && (STREQ (typename, vtbl_ptr_name) @@ -187,14 +180,20 @@ cp_is_vtbl_member(type) struct type *type; { if (TYPE_CODE (type) == TYPE_CODE_PTR) - type = TYPE_TARGET_TYPE (type); - else - return 0; - - if (TYPE_CODE (type) == TYPE_CODE_ARRAY - && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT) - /* Virtual functions tables are full of pointers to virtual functions. */ - return cp_is_vtbl_ptr_type (TYPE_TARGET_TYPE (type)); + { + type = TYPE_TARGET_TYPE (type); + if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + type = TYPE_TARGET_TYPE (type); + if (TYPE_CODE (type) == TYPE_CODE_STRUCT /* if not using thunks */ + || TYPE_CODE (type) == TYPE_CODE_PTR) /* if using thunks */ + { + /* Virtual functions tables are full of pointers + to virtual functions. */ + return cp_is_vtbl_ptr_type (type); + } + } + } return 0; } @@ -212,7 +211,7 @@ cp_print_value_fields (type, valaddr, stream, format, recurse, pretty, dont_print) struct type *type; char *valaddr; - FILE *stream; + GDB_FILE *stream; int format; int recurse; enum val_prettyprint pretty; @@ -285,30 +284,51 @@ cp_print_value_fields (type, valaddr, stream, format, recurse, pretty, } else { + annotate_field_begin (TYPE_FIELD_TYPE (type, i)); + fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i), language_cplus, DMGL_PARAMS | DMGL_ANSI); + annotate_field_name_end (); fputs_filtered (" = ", stream); + annotate_field_value (); } + if (TYPE_FIELD_PACKED (type, i)) { - value v; + value_ptr v; /* Bitfields require special handling, especially due to byte order problems. */ - v = value_from_longest (TYPE_FIELD_TYPE (type, i), + if (TYPE_FIELD_IGNORE (type, i)) + { + fputs_filtered ("", stream); + } + else + { + v = value_from_longest (TYPE_FIELD_TYPE (type, i), unpack_field_as_long (type, valaddr, i)); - c_val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0, - stream, format, 0, recurse + 1, pretty); + val_print (TYPE_FIELD_TYPE(type, i), VALUE_CONTENTS (v), 0, + stream, format, 0, recurse + 1, pretty); + } } else { - c_val_print (TYPE_FIELD_TYPE (type, i), - valaddr + TYPE_FIELD_BITPOS (type, i) / 8, - 0, stream, format, 0, recurse + 1, pretty); + if (TYPE_FIELD_IGNORE (type, i)) + { + fputs_filtered ("", stream); + } + else + { + val_print (TYPE_FIELD_TYPE (type, i), + valaddr + TYPE_FIELD_BITPOS (type, i) / 8, + 0, stream, format, 0, recurse + 1, pretty); + } } + annotate_field_end (); } + if (pretty) { fprintf_filtered (stream, "\n"); @@ -325,7 +345,7 @@ static void cplus_print_value (type, valaddr, stream, format, recurse, pretty, dont_print) struct type *type; char *valaddr; - FILE *stream; + GDB_FILE *stream; int format; int recurse; enum val_prettyprint pretty; @@ -348,9 +368,14 @@ cplus_print_value (type, valaddr, stream, format, recurse, pretty, dont_print) for (i = 0; i < n_baseclasses; i++) { + /* FIXME-32x64--assumes that a target pointer can fit in a char *. + Fix it by nuking baseclass_addr. */ char *baddr; int err; - char *basename = TYPE_NAME (TYPE_BASECLASS (type, i)); + char *basename; + + check_stub_type (TYPE_BASECLASS (type, i)); + basename = TYPE_NAME (TYPE_BASECLASS (type, i)); if (BASETYPE_VIA_VIRTUAL (type, i)) { @@ -384,8 +409,11 @@ cplus_print_value (type, valaddr, stream, format, recurse, pretty, dont_print) fputs_filtered (basename ? basename : "", stream); fputs_filtered ("> = ", stream); if (err != 0) - fprintf_filtered (stream, - "", (unsigned long) baddr); + { + fprintf_filtered (stream, ""); + } else cp_print_value_fields (TYPE_BASECLASS (type, i), baddr, stream, format, recurse, pretty, @@ -411,7 +439,7 @@ void cp_print_class_member (valaddr, domain, stream, prefix) char *valaddr; struct type *domain; - FILE *stream; + GDB_FILE *stream; char *prefix; { diff --git a/gnu/usr.bin/gdb/gdb/dbxread.c b/gnu/usr.bin/gdb/gdb/dbxread.c index 7f4ef2632abb..2b3a6be079a2 100644 --- a/gnu/usr.bin/gdb/gdb/dbxread.c +++ b/gnu/usr.bin/gdb/gdb/dbxread.c @@ -1,5 +1,5 @@ /* Read dbx symbol tables and convert to internal format, for GDB. - Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993 + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -52,7 +52,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "command.h" #include "target.h" #include "gdbcore.h" /* for bfd stuff */ -#include "libbfd.h" /* FIXME Secret internal BFD stuff (bfd_read) */ #include "libaout.h" /* FIXME Secret internal BFD stuff for a.out */ #include "symfile.h" #include "objfiles.h" @@ -108,25 +107,6 @@ struct symloc { #define IGNORE_SYMBOL(type) (type == (int)N_NSYMS) #endif -/* Macro for name of symbol to indicate a file compiled with gcc. */ -#ifndef GCC_COMPILED_FLAG_SYMBOL -#define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled." -#endif - -/* Macro for name of symbol to indicate a file compiled with gcc2. */ -#ifndef GCC2_COMPILED_FLAG_SYMBOL -#define GCC2_COMPILED_FLAG_SYMBOL "gcc2_compiled." -#endif - -/* Define this as 1 if a pcc declaration of a char or short argument - gives the correct address. Otherwise assume pcc gives the - address of the corresponding int, which is not the same on a - big-endian machine. */ - -#ifndef BELIEVE_PCC_PROMOTION -#define BELIEVE_PCC_PROMOTION 0 -#endif - /* Remember what we deduced to be the source language of this psymtab. */ static enum language psymtab_language = language_unknown; @@ -158,6 +138,20 @@ static unsigned string_table_offset; static unsigned int file_string_table_offset; static unsigned int next_file_string_table_offset; +/* .o and NLM files contain unrelocated addresses which are based at 0. When + non-zero, this flag disables some of the special cases for Solaris elf+stab + text addresses at location 0. */ + +static int symfile_relocatable = 0; + + /* If this is nonzero, N_LBRAC, N_RBRAC, and N_SLINE entries are relative + to the function start address. */ + +static int block_address_function_relative = 0; + +/* This is the lowest text address we have yet encountered. */ +static CORE_ADDR lowest_text_address; + /* Complaints about the symbols we have encountered. */ struct complaint lbrac_complaint = @@ -170,7 +164,7 @@ struct complaint unknown_symtype_complaint = {"unknown symbol type %s", 0, 0}; struct complaint unknown_symchar_complaint = - {"unknown symbol type character `%c'", 0, 0}; + {"unknown symbol descriptor `%c'", 0, 0}; struct complaint lbrac_rbrac_complaint = {"block start larger than block end", 0, 0}; @@ -221,6 +215,10 @@ dbx_psymtab_to_symtab PARAMS ((struct partial_symtab *)); static void dbx_psymtab_to_symtab_1 PARAMS ((struct partial_symtab *)); +static void +read_dbx_dynamic_symtab PARAMS ((struct section_offsets *, + struct objfile *objfile)); + static void read_dbx_symtab PARAMS ((struct section_offsets *, struct objfile *, CORE_ADDR, int)); @@ -419,47 +417,46 @@ record_minimal_symbol (name, address, type, objfile) struct objfile *objfile; { enum minimal_symbol_type ms_type; + int section; switch (type) { - case N_TEXT | N_EXT: ms_type = mst_text; break; - case N_DATA | N_EXT: ms_type = mst_data; break; - case N_BSS | N_EXT: ms_type = mst_bss; break; - case N_ABS | N_EXT: ms_type = mst_abs; break; + case N_TEXT | N_EXT: + ms_type = mst_text; + section = SECT_OFF_TEXT; + break; + case N_DATA | N_EXT: + ms_type = mst_data; + section = SECT_OFF_DATA; + break; + case N_BSS | N_EXT: + ms_type = mst_bss; + section = SECT_OFF_BSS; + break; + case N_ABS | N_EXT: + ms_type = mst_abs; + section = -1; + break; #ifdef N_SETV - case N_SETV | N_EXT: ms_type = mst_data; break; + case N_SETV | N_EXT: + ms_type = mst_data; + section = SECT_OFF_DATA; + break; case N_SETV: /* I don't think this type actually exists; since a N_SETV is the result of going over many .o files, it doesn't make sense to have one file local. */ ms_type = mst_file_data; + section = SECT_OFF_DATA; break; #endif case N_TEXT: - /* Don't put gcc_compiled, __gnu_compiled_cplus, and friends into - the minimal symbols, because if there is also another symbol - at the same address (e.g. the first function of the file), - lookup_minimal_symbol_by_pc would have no way of getting the - right one. */ - if (name[0] == 'g' - && (strcmp (name, GCC_COMPILED_FLAG_SYMBOL) == 0 - || strcmp (name, GCC2_COMPILED_FLAG_SYMBOL) == 0)) - return; - - { - char *tempstring = name; - if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd)) - ++tempstring; - if (STREQN (tempstring, "__gnu_compiled", 14)) - return; - } - case N_NBTEXT: case N_FN: case N_FN_SEQ: ms_type = mst_file_text; + section = SECT_OFF_TEXT; break; - case N_DATA: ms_type = mst_file_data; @@ -478,19 +475,29 @@ record_minimal_symbol (name, address, type, objfile) if (VTBL_PREFIX_P ((tempstring))) ms_type = mst_data; } + section = SECT_OFF_DATA; break; - case N_BSS: ms_type = mst_file_bss; + section = SECT_OFF_BSS; + break; + default: + ms_type = mst_unknown; + section = -1; break; - - default: ms_type = mst_unknown; break; } - prim_record_minimal_symbol + if ((ms_type == mst_file_text || ms_type == mst_text) + && address < lowest_text_address) + lowest_text_address = address; + + prim_record_minimal_symbol_and_info (obsavestring (name, strlen (name), &objfile -> symbol_obstack), address, - ms_type); + ms_type, + NULL, + section, + objfile); } /* Scan and build partial symbols for a symbol file. @@ -513,6 +520,28 @@ dbx_symfile_read (objfile, section_offsets, mainline) int val; struct cleanup *back_to; + val = strlen (objfile->name); + + /* .o and .nlm files are relocatables with text, data and bss segs based at + 0. This flag disables special (Solaris stabs-in-elf only) fixups for + symbols with a value of 0. XXX - This is a Krock. Solaris stabs-in-elf + should be fixed to determine pst->textlow without using this text seg of + 0 fixup crap. */ + + if (strcmp (&objfile->name[val-2], ".o") == 0 + || strcmp (&objfile->name[val-4], ".nlm") == 0) + symfile_relocatable = 1; + + /* This is true for Solaris (and all other systems which put stabs + in sections, hopefully, since it would be silly to do things + differently from Solaris), and false for SunOS4 and other a.out + file formats. */ + block_address_function_relative = + ((0 == strncmp (bfd_get_target (objfile->obfd), "elf", 3)) + || (0 == strncmp (bfd_get_target (objfile->obfd), "som", 3)) + || (0 == strncmp (bfd_get_target (objfile->obfd), "coff", 4)) + || (0 == strncmp (bfd_get_target (objfile->obfd), "nlm", 3))); + sym_bfd = objfile->obfd; val = bfd_seek (objfile->obfd, DBX_SYMTAB_OFFSET (objfile), SEEK_SET); if (val < 0) @@ -538,17 +567,15 @@ dbx_symfile_read (objfile, section_offsets, mainline) bfd_section_vma (sym_bfd, DBX_TEXT_SECT (objfile)), bfd_section_size (sym_bfd, DBX_TEXT_SECT (objfile))); + /* Add the dynamic symbols. */ + + read_dbx_dynamic_symtab (section_offsets, objfile); + /* Install any minimal symbols that have been collected as the current minimal symbols for this objfile. */ install_minimal_symbols (objfile); - if (!have_partial_symbols ()) { - wrap_here (""); - printf_filtered ("(no debugging symbols found)..."); - wrap_here (""); - } - do_cleanups (back_to); } @@ -854,6 +881,150 @@ free_bincl_list (objfile) bincls_allocated = 0; } +/* Scan a SunOs dynamic symbol table for symbols of interest and + add them to the minimal symbol table. */ + +static void +read_dbx_dynamic_symtab (section_offsets, objfile) + struct section_offsets *section_offsets; + struct objfile *objfile; +{ + bfd *abfd = objfile->obfd; + struct cleanup *back_to; + int counter; + long dynsym_size; + long dynsym_count; + asymbol **dynsyms; + asymbol **symptr; + arelent **relptr; + long dynrel_size; + long dynrel_count; + arelent **dynrels; + CORE_ADDR sym_value; + + /* Check that the symbol file has dynamic symbols that we know about. + bfd_arch_unknown can happen if we are reading a sun3 symbol file + on a sun4 host (and vice versa) and bfd is not configured + --with-target=all. This would trigger an assertion in bfd/sunos.c, + so we ignore the dynamic symbols in this case. */ + if (bfd_get_flavour (abfd) != bfd_target_aout_flavour + || (bfd_get_file_flags (abfd) & DYNAMIC) == 0 + || bfd_get_arch (abfd) == bfd_arch_unknown) + return; + + dynsym_size = bfd_get_dynamic_symtab_upper_bound (abfd); + if (dynsym_size < 0) + return; + + dynsyms = (asymbol **) xmalloc (dynsym_size); + back_to = make_cleanup (free, dynsyms); + + dynsym_count = bfd_canonicalize_dynamic_symtab (abfd, dynsyms); + if (dynsym_count < 0) + { + do_cleanups (back_to); + return; + } + + /* Enter dynamic symbols into the minimal symbol table + if this is a stripped executable. */ + if (bfd_get_symcount (abfd) <= 0) + { + symptr = dynsyms; + for (counter = 0; counter < dynsym_count; counter++, symptr++) + { + asymbol *sym = *symptr; + asection *sec; + int type; + + sec = bfd_get_section (sym); + + /* BFD symbols are section relative. */ + sym_value = sym->value + sec->vma; + + if (bfd_get_section_flags (abfd, sec) & SEC_CODE) + { + sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT); + type = N_TEXT; + } + else if (bfd_get_section_flags (abfd, sec) & SEC_DATA) + { + sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA); + type = N_DATA; + } + else if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC) + { + sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS); + type = N_BSS; + } + else + continue; + + if (sym->flags & BSF_GLOBAL) + type |= N_EXT; + + record_minimal_symbol ((char *) bfd_asymbol_name (sym), sym_value, + type, objfile); + } + } + + /* Symbols from shared libraries have a dynamic relocation entry + that points to the associated slot in the procedure linkage table. + We make a mininal symbol table entry with type mst_solib_trampoline + at the address in the procedure linkage table. */ + dynrel_size = bfd_get_dynamic_reloc_upper_bound (abfd); + if (dynrel_size < 0) + { + do_cleanups (back_to); + return; + } + + dynrels = (arelent **) xmalloc (dynrel_size); + make_cleanup (free, dynrels); + + dynrel_count = bfd_canonicalize_dynamic_reloc (abfd, dynrels, dynsyms); + if (dynrel_count < 0) + { + do_cleanups (back_to); + return; + } + + for (counter = 0, relptr = dynrels; + counter < dynrel_count; + counter++, relptr++) + { + arelent *rel = *relptr; + CORE_ADDR address = + rel->address + ANOFFSET (section_offsets, SECT_OFF_DATA); + + switch (bfd_get_arch (abfd)) + { + case bfd_arch_sparc: + if (rel->howto->type != RELOC_JMP_SLOT) + continue; + break; + case bfd_arch_m68k: + /* `16' is the type BFD produces for a jump table relocation. */ + if (rel->howto->type != 16) + continue; + + /* Adjust address in the jump table to point to + the start of the bsr instruction. */ + address -= 2; + break; + default: + continue; + } + + prim_record_minimal_symbol (bfd_asymbol_name (*rel->sym_ptr_ptr), + address, + mst_solib_trampoline, + objfile); + } + + do_cleanups (back_to); +} + /* Given pointers to an a.out symbol table in core containing dbx style data, setup partial_symtab's describing each source file for which debugging information is available. @@ -876,9 +1047,6 @@ read_dbx_symtab (section_offsets, objfile, text_addr, text_size) struct cleanup *back_to; bfd *abfd; - /* End of the text segment of the executable file. */ - CORE_ADDR end_of_text_addr; - /* Current partial symtab */ struct partial_symtab *pst; @@ -917,12 +1085,7 @@ read_dbx_symtab (section_offsets, objfile, text_addr, text_size) last_source_file = NULL; -#ifdef END_OF_TEXT_DEFAULT - end_of_text_addr = END_OF_TEXT_DEFAULT; -#else - end_of_text_addr = text_addr + section_offsets->offsets[SECT_OFF_TEXT] - + text_size; /* Relocate */ -#endif + lowest_text_address = (CORE_ADDR)-1; symfile_bfd = objfile->obfd; /* For next_text_symbol */ abfd = objfile->obfd; @@ -965,7 +1128,7 @@ read_dbx_symtab (section_offsets, objfile, text_addr, text_size) if (((unsigned)bufp->n_strx + file_string_table_offset) >= \ DBX_STRINGTAB_SIZE (objfile)) { \ complain (&string_table_offset_complaint, symnum); \ - namestring = "foo"; \ + namestring = ""; \ } else \ namestring = bufp->n_strx + file_string_table_offset + \ DBX_STRINGTAB (objfile) @@ -995,7 +1158,11 @@ read_dbx_symtab (section_offsets, objfile, text_addr, text_size) if (pst) { end_psymtab (pst, psymtab_include_list, includes_used, - symnum * symbol_size, end_of_text_addr, + symnum * symbol_size, + (lowest_text_address == (CORE_ADDR)-1 + ? (text_addr + section_offsets->offsets[SECT_OFF_TEXT]) + : lowest_text_address) + + text_size, dependency_list, dependencies_used); } @@ -1061,16 +1228,15 @@ end_psymtab (pst, include_list, num_includes, capping_symbol_offset, CORE_ADDR capping_text; struct partial_symtab **dependency_list; int number_dependencies; -/* struct partial_symbol *capping_global, *capping_static;*/ { int i; - struct partial_symtab *p1; struct objfile *objfile = pst -> objfile; if (capping_symbol_offset != -1) LDSYMLEN(pst) = capping_symbol_offset - LDSYMOFF(pst); pst->texthigh = capping_text; +#ifdef N_SO_ADDRESS_MAYBE_MISSING /* Under Solaris, the N_SO symbols always have a value of 0, instead of the usual address of the .o file. Therefore, we have to do some tricks to fill in texthigh and textlow. @@ -1137,6 +1303,9 @@ end_psymtab (pst, include_list, num_includes, capping_symbol_offset, /* this test will be true if the last .o file is only data */ if (pst->textlow == 0) + /* This loses if the text section really starts at address zero + (generally true when we are debugging a .o file, for example). + That is why this whole thing is inside N_SO_ADDRESS_MAYBE_MISSING. */ pst->textlow = pst->texthigh; /* If we know our own starting text address, then walk through all other @@ -1145,6 +1314,8 @@ end_psymtab (pst, include_list, num_includes, capping_symbol_offset, own ending address to our starting address, nor to set addresses on `dependency' files that have both textlow and texthigh zero. */ if (pst->textlow) { + struct partial_symtab *p1; + ALL_OBJFILE_PSYMTABS (objfile, p1) { if (p1->texthigh == 0 && p1->textlow != 0 && p1 != pst) { p1->texthigh = pst->textlow; @@ -1156,7 +1327,7 @@ end_psymtab (pst, include_list, num_includes, capping_symbol_offset, } /* End of kludge for patching Solaris textlow and texthigh. */ - +#endif /* N_SO_ADDRESS_MAYBE_MISSING. */ pst->n_global_syms = objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset); @@ -1215,30 +1386,36 @@ end_psymtab (pst, include_list, num_includes, capping_symbol_offset, free_named_symtabs (pst->filename); if (num_includes == 0 - && number_dependencies == 0 - && pst->n_global_syms == 0 - && pst->n_static_syms == 0) { - /* Throw away this psymtab, it's empty. We can't deallocate it, since - it is on the obstack, but we can forget to chain it on the list. */ - struct partial_symtab *prev_pst; + && number_dependencies == 0 + && pst->n_global_syms == 0 + && pst->n_static_syms == 0) + { + /* Throw away this psymtab, it's empty. We can't deallocate it, since + it is on the obstack, but we can forget to chain it on the list. */ + /* Empty psymtabs happen as a result of header files which don't have + any symbols in them. There can be a lot of them. But this check + is wrong, in that a psymtab with N_SLINE entries but nothing else + is not empty, but we don't realize that. Fixing that without slowing + things down might be tricky. */ + struct partial_symtab *prev_pst; - /* First, snip it out of the psymtab chain */ + /* First, snip it out of the psymtab chain */ - if (pst->objfile->psymtabs == pst) - pst->objfile->psymtabs = pst->next; - else - for (prev_pst = pst->objfile->psymtabs; prev_pst; prev_pst = pst->next) - if (prev_pst->next == pst) - prev_pst->next = pst->next; + if (pst->objfile->psymtabs == pst) + pst->objfile->psymtabs = pst->next; + else + for (prev_pst = pst->objfile->psymtabs; prev_pst; prev_pst = pst->next) + if (prev_pst->next == pst) + prev_pst->next = pst->next; - /* Next, put it on a free list for recycling */ + /* Next, put it on a free list for recycling */ - pst->next = pst->objfile->free_psymtabs; - pst->objfile->free_psymtabs = pst; + pst->next = pst->objfile->free_psymtabs; + pst->objfile->free_psymtabs = pst; - /* Indicate that psymtab was thrown away. */ - pst = (struct partial_symtab *)NULL; - } + /* Indicate that psymtab was thrown away. */ + pst = (struct partial_symtab *)NULL; + } return pst; } @@ -1254,7 +1431,7 @@ dbx_psymtab_to_symtab_1 (pst) if (pst->readin) { - fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n", + fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n", pst->filename); return; } @@ -1266,13 +1443,13 @@ dbx_psymtab_to_symtab_1 (pst) /* Inform about additional files that need to be read in. */ if (info_verbose) { - fputs_filtered (" ", stdout); + fputs_filtered (" ", gdb_stdout); wrap_here (""); - fputs_filtered ("and ", stdout); + fputs_filtered ("and ", gdb_stdout); wrap_here (""); printf_filtered ("%s...", pst->dependencies[i]->filename); wrap_here (""); /* Flush output */ - fflush (stdout); + gdb_flush (gdb_stdout); } dbx_psymtab_to_symtab_1 (pst->dependencies[i]); } @@ -1311,7 +1488,7 @@ dbx_psymtab_to_symtab (pst) if (pst->readin) { - fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n", + fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n", pst->filename); return; } @@ -1323,7 +1500,7 @@ dbx_psymtab_to_symtab (pst) if (info_verbose) { printf_filtered ("Reading in symbols for %s...", pst->filename); - fflush (stdout); + gdb_flush (gdb_stdout); } sym_bfd = pst->objfile->obfd; @@ -1395,10 +1572,16 @@ read_ofile_symtab (pst) processing_gcc_compilation = 0; if (bufp->n_type == N_TEXT) { + const char *tempstring = namestring; + if (STREQ (namestring, GCC_COMPILED_FLAG_SYMBOL)) processing_gcc_compilation = 1; else if (STREQ (namestring, GCC2_COMPILED_FLAG_SYMBOL)) processing_gcc_compilation = 2; + if (tempstring[0] == bfd_get_symbol_leading_char (symfile_bfd)) + ++tempstring; + if (STREQN (tempstring, "__gnu_compiled", 14)) + processing_gcc_compilation = 2; } /* Try to select a C++ demangling based on the compilation unit @@ -1538,10 +1721,6 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile) used to relocate these symbol types rather than SECTION_OFFSETS. */ static CORE_ADDR function_start_offset; - /* If this is nonzero, N_LBRAC, N_RBRAC, and N_SLINE entries are relative - to the function start address. */ - int block_address_function_relative; - /* If this is nonzero, we've seen a non-gcc N_OPT symbol for this source file. Used to detect the SunPRO solaris compiler. */ static int n_opt_found; @@ -1550,12 +1729,6 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile) N_STSYM or N_GSYM for SunOS4 acc; N_FUN for other compilers. */ static int function_stab_type = 0; - /* This is true for Solaris (and all other stabs-in-elf systems, hopefully, - since it would be silly to do things differently from Solaris), and - false for SunOS4 and other a.out file formats. */ - block_address_function_relative = - 0 == strncmp (bfd_get_target (objfile->obfd), "elf", 3); - if (!block_address_function_relative) /* N_LBRAC, N_RBRAC and N_SLINE entries are not relative to the function start address, so just use the text offset. */ @@ -1643,33 +1816,38 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile) if (!VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation)) local_symbols = new->locals; - /* If this is not the outermost LBRAC...RBRAC pair in the - function, its local symbols preceded it, and are the ones - just recovered from the context stack. Defined the block for them. - - If this is the outermost LBRAC...RBRAC pair, there is no - need to do anything; leave the symbols that preceded it - to be attached to the function's own block. However, if - it is so, we need to indicate that we just moved outside - of the function. */ - if (local_symbols - && (context_stack_depth - > !VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))) + if (context_stack_depth + > !VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation)) { - /* FIXME Muzzle a compiler bug that makes end < start. */ - if (new->start_addr > valu) + /* This is not the outermost LBRAC...RBRAC pair in the function, + its local symbols preceded it, and are the ones just recovered + from the context stack. Define the block for them (but don't + bother if the block contains no symbols. Should we complain + on blocks without symbols? I can't think of any useful purpose + for them). */ + if (local_symbols != NULL) { - complain (&lbrac_rbrac_complaint); - new->start_addr = valu; + /* Muzzle a compiler bug that makes end < start. (which + compilers? Is this ever harmful?). */ + if (new->start_addr > valu) + { + complain (&lbrac_rbrac_complaint); + new->start_addr = valu; + } + /* Make a block for the local symbols within. */ + finish_block (0, &local_symbols, new->old_blocks, + new->start_addr, valu, objfile); } - /* Make a block for the local symbols within. */ - finish_block (0, &local_symbols, new->old_blocks, - new->start_addr, valu, objfile); } else { + /* This is the outermost LBRAC...RBRAC pair. There is no + need to do anything; leave the symbols that preceded it + to be attached to the function's own block. We need to + indicate that we just moved outside of the function. */ within_function = 0; } + if (VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation)) /* Now pop locals of block just finished. */ local_symbols = new->locals; @@ -1718,11 +1896,16 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile) end_symtab (valu, 0, 0, objfile, SECT_OFF_TEXT); end_stabs (); } + + /* Null name means this just marks the end of text for this .o file. + Don't start a new symtab in this case. */ + if (*name == '\000') + break; + start_stabs (); start_symtab (name, NULL, valu); break; - case N_SOL: /* This type of symbol indicates the start of data for a sub-source-file, one whose contents were copied or @@ -1784,13 +1967,30 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile) call level, which we really don't want to do). */ { char *p; - p = strchr (name, ':'); - if (p != 0 && p[1] == 'S') + + /* .o files and NLMs have non-zero text seg offsets, but don't need + their static syms offset in this fashion. XXX - This is really a + crock that should be fixed in the solib handling code so that I + don't have to work around it here. */ + + if (!symfile_relocatable) { - /* The linker relocated it. There used to be a kludge here - to add the text offset, but that will break if we ever - start using the text offset (currently it is always zero). */ - goto define_a_symbol; + p = strchr (name, ':'); + if (p != 0 && p[1] == 'S') + { + /* The linker relocated it. We don't want to add an + elfstab_offset_sections-type offset, but we *do* want + to add whatever solib.c passed to symbol_file_add as + addr (this is known to affect SunOS4, and I suspect ELF + too). Since elfstab_offset_sections currently does not + muck with the text offset (there is no Ttext.text + symbol), we can get addr from the text offset. If + elfstab_offset_sections ever starts dealing with the + text offset, and we still need to do this, we need to + invent a SECT_OFF_ADDR_KLUDGE or something. */ + valu += ANOFFSET (section_offsets, SECT_OFF_TEXT); + goto define_a_symbol; + } } /* Since it's not the kludge case, re-dispatch to the right handler. */ switch (type) { @@ -1836,8 +2036,7 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile) case N_NBBSS: case N_NBSTS: case N_NBLCS: - complain (&unknown_symtype_complaint, - local_hex_string((unsigned long) type)); + complain (&unknown_symtype_complaint, local_hex_string (type)); /* FALLTHROUGH */ /* The following symbol types don't need the address field relocated, @@ -2138,31 +2337,88 @@ elfstab_build_psymtabs (objfile, section_offsets, mainline, dbx_symfile_read (objfile, section_offsets, 0); } -/* Scan and build partial symbols for a PA symbol file. - This PA file has already been processed to get its minimal symbols. +/* Scan and build partial symbols for a file with special sections for stabs + and stabstrings. The file has already been processed to get its minimal + symbols, and any other symbols that might be necessary to resolve GSYMs. + + This routine is the equivalent of dbx_symfile_init and dbx_symfile_read + rolled into one. OBJFILE is the object file we are reading symbols from. - ADDR is the address relative to which the symbols are (e.g. - the base address of the text segment). - MAINLINE is true if we are reading the main symbol - table (as opposed to a shared lib or dynamically loaded file). + ADDR is the address relative to which the symbols are (e.g. the base address + of the text segment). + MAINLINE is true if we are reading the main symbol table (as opposed to a + shared lib or dynamically loaded file). + STAB_NAME is the name of the section that contains the stabs. + STABSTR_NAME is the name of the section that contains the stab strings. - */ + This routine is mostly copied from dbx_symfile_init and dbx_symfile_read. */ void -pastab_build_psymtabs (objfile, section_offsets, mainline) +stabsect_build_psymtabs (objfile, section_offsets, mainline, stab_name, + stabstr_name, text_name) struct objfile *objfile; struct section_offsets *section_offsets; int mainline; + char *stab_name; + char *stabstr_name; + char *text_name; { + int val; + bfd *sym_bfd = objfile->obfd; + char *name = bfd_get_filename (sym_bfd); + asection *stabsect; + asection *stabstrsect; + + stabsect = bfd_get_section_by_name (sym_bfd, stab_name); + stabstrsect = bfd_get_section_by_name (sym_bfd, stabstr_name); + + if (!stabsect) + return; + + if (!stabstrsect) + error ("stabsect_build_psymtabs: Found stabs (%s), but not string section (%s)", + stab_name, stabstr_name); + + objfile->sym_stab_info = (PTR) xmalloc (sizeof (struct dbx_symfile_info)); + memset (DBX_SYMFILE_INFO (objfile), 0, sizeof (struct dbx_symfile_info)); + + DBX_TEXT_SECT (objfile) = bfd_get_section_by_name (sym_bfd, text_name); + if (!DBX_TEXT_SECT (objfile)) + error ("Can't find %s section in symbol file", text_name); + + DBX_SYMBOL_SIZE (objfile) = sizeof (struct external_nlist); + DBX_SYMCOUNT (objfile) = bfd_section_size (sym_bfd, stabsect) + / DBX_SYMBOL_SIZE (objfile); + DBX_STRINGTAB_SIZE (objfile) = bfd_section_size (sym_bfd, stabstrsect); + DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos; /* XXX - FIXME: POKING INSIDE BFD DATA STRUCTURES */ + + if (DBX_STRINGTAB_SIZE (objfile) > bfd_get_size (sym_bfd)) + error ("ridiculous string table size: %d bytes", DBX_STRINGTAB_SIZE (objfile)); + DBX_STRINGTAB (objfile) = (char *) + obstack_alloc (&objfile->psymbol_obstack, DBX_STRINGTAB_SIZE (objfile) + 1); + + /* Now read in the string table in one big gulp. */ + + val = bfd_get_section_contents (sym_bfd, /* bfd */ + stabstrsect, /* bfd section */ + DBX_STRINGTAB (objfile), /* input buffer */ + 0, /* offset into section */ + DBX_STRINGTAB_SIZE (objfile)); /* amount to read */ + + if (!val) + perror_with_name (name); + + stabsread_new_init (); + buildsym_new_init (); free_header_files (); init_header_files (); + install_minimal_symbols (objfile); - /* In a PA file, we've already installed the minimal symbols that came - from the PA (non-stab) symbol table, so always act like an - incremental load here. */ + /* Now, do an incremental load */ - dbx_symfile_read (objfile, section_offsets, mainline); + processing_acc_compilation = 1; + dbx_symfile_read (objfile, section_offsets, 0); } /* Parse the user's idea of an offset for dynamic linking, into our idea @@ -2175,11 +2431,12 @@ dbx_symfile_offsets (objfile, addr) { struct section_offsets *section_offsets; int i; - + + objfile->num_sections = SECT_OFF_MAX; section_offsets = (struct section_offsets *) obstack_alloc (&objfile -> psymbol_obstack, - sizeof (struct section_offsets) + - sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1)); + sizeof (struct section_offsets) + + sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1)); for (i = 0; i < SECT_OFF_MAX; i++) ANOFFSET (section_offsets, i) = addr; @@ -2187,36 +2444,9 @@ dbx_symfile_offsets (objfile, addr) return section_offsets; } -/* Register our willingness to decode symbols for SunOS and a.out and - NetBSD and b.out files handled by BFD... */ -static struct sym_fns sunos_sym_fns = -{ - "sunOs", /* sym_name: name or name prefix of BFD target type */ - 6, /* sym_namelen: number of significant sym_name chars */ - dbx_new_init, /* sym_new_init: init anything gbl to entire symtab */ - dbx_symfile_init, /* sym_init: read initial info, setup for sym_read() */ - dbx_symfile_read, /* sym_read: read a symbol file into symtab */ - dbx_symfile_finish, /* sym_finish: finished with file, cleanup */ - dbx_symfile_offsets, /* sym_offsets: parse user's offsets to internal form */ - NULL /* next: pointer to next struct sym_fns */ -}; - static struct sym_fns aout_sym_fns = { - "a.out", /* sym_name: name or name prefix of BFD target type */ - 5, /* sym_namelen: number of significant sym_name chars */ - dbx_new_init, /* sym_new_init: init anything gbl to entire symtab */ - dbx_symfile_init, /* sym_init: read initial info, setup for sym_read() */ - dbx_symfile_read, /* sym_read: read a symbol file into symtab */ - dbx_symfile_finish, /* sym_finish: finished with file, cleanup */ - dbx_symfile_offsets, /* sym_offsets: parse user's offsets to internal form */ - NULL /* next: pointer to next struct sym_fns */ -}; - -static struct sym_fns bout_sym_fns = -{ - "b.out", /* sym_name: name or name prefix of BFD target type */ - 5, /* sym_namelen: number of significant sym_name chars */ + bfd_target_aout_flavour, dbx_new_init, /* sym_new_init: init anything gbl to entire symtab */ dbx_symfile_init, /* sym_init: read initial info, setup for sym_read() */ dbx_symfile_read, /* sym_read: read a symbol file into symtab */ @@ -2228,7 +2458,5 @@ static struct sym_fns bout_sym_fns = void _initialize_dbxread () { - add_symtab_fns(&sunos_sym_fns); add_symtab_fns(&aout_sym_fns); - add_symtab_fns(&bout_sym_fns); } diff --git a/gnu/usr.bin/gdb/gdb/defs.h b/gnu/usr.bin/gdb/gdb/defs.h index f65d56ac5878..37631ba1ed33 100644 --- a/gnu/usr.bin/gdb/gdb/defs.h +++ b/gnu/usr.bin/gdb/gdb/defs.h @@ -27,12 +27,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ansidecl.h" -/* An address in the program being debugged. Host byte order. */ -#ifndef CORE_ADDR_TYPE -typedef unsigned int CORE_ADDR; -#else -typedef CORE_ADDR_TYPE CORE_ADDR; -#endif +/* For BFD64 and bfd_vma. */ +#include "bfd.h" + +/* An address in the program being debugged. Host byte order. Rather + than duplicate all the logic in BFD which figures out what type + this is (long, long long, etc.) and whether it needs to be 64 + bits (the host/target interactions are subtle), we just use + bfd_vma. */ + +typedef bfd_vma CORE_ADDR; #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) @@ -88,7 +92,8 @@ enum language language_c, /* C */ language_cplus, /* C++ */ language_chill, /* Chill */ - language_m2 /* Modula-2 */ + language_m2, /* Modula-2 */ + language_asm /* Assembly language */ }; /* the cleanup list records things that have to be undone @@ -211,7 +216,11 @@ myread PARAMS ((int, char *, int)); extern int query (); + +/* Annotation stuff. */ +extern int annotation_level; /* in stack.c */ + extern void begin_line PARAMS ((void)); @@ -221,15 +230,39 @@ wrap_here PARAMS ((char *)); extern void reinitialize_more_filter PARAMS ((void)); +typedef FILE GDB_FILE; +#define gdb_stdout stdout +#define gdb_stderr stderr + extern int -print_insn PARAMS ((CORE_ADDR, FILE *)); +print_insn PARAMS ((CORE_ADDR, GDB_FILE *)); extern void -fputs_filtered PARAMS ((const char *, FILE *)); +gdb_flush PARAMS ((GDB_FILE *)); + +extern GDB_FILE * +gdb_fopen PARAMS ((char * name, char * mode)); + +extern void +fputs_filtered PARAMS ((const char *, GDB_FILE *)); + +extern void +fputs_unfiltered PARAMS ((const char *, GDB_FILE *)); + +extern void +fputc_unfiltered PARAMS ((int, GDB_FILE *)); + +extern void +putc_unfiltered PARAMS ((int)); + +#define putchar_unfiltered(C) putc_unfiltered(C) extern void puts_filtered PARAMS ((char *)); +extern void +puts_unfiltered PARAMS ((char *)); + extern void vprintf_filtered (); @@ -249,19 +282,34 @@ extern void printfi_filtered (); extern void -print_spaces PARAMS ((int, FILE *)); +vprintf_unfiltered (); extern void -print_spaces_filtered PARAMS ((int, FILE *)); +vfprintf_unfiltered (); + +extern void +fprintf_unfiltered (); + +extern void +printf_unfiltered (); + +extern void +print_spaces PARAMS ((int, GDB_FILE *)); + +extern void +print_spaces_filtered PARAMS ((int, GDB_FILE *)); extern char * n_spaces PARAMS ((int)); extern void -gdb_printchar PARAMS ((int, FILE *, int)); +gdb_printchar PARAMS ((int, GDB_FILE *, int)); + +/* Print a host address. */ +extern void gdb_print_address PARAMS ((void *, GDB_FILE *)); extern void -fprintf_symbol_filtered PARAMS ((FILE *, char *, enum language, int)); +fprintf_symbol_filtered PARAMS ((GDB_FILE *, char *, enum language, int)); extern void perror_with_name PARAMS ((char *)); @@ -290,14 +338,11 @@ extern char * gdb_readline PARAMS ((char *)); extern char * -command_line_input PARAMS ((char *, int)); +command_line_input PARAMS ((char *, int, char *)); extern void print_prompt PARAMS ((void)); -extern int -batch_mode PARAMS ((void)); - extern int input_from_terminal_p PARAMS ((void)); @@ -307,10 +352,13 @@ extern void set_next_address PARAMS ((CORE_ADDR)); extern void -print_address_symbolic PARAMS ((CORE_ADDR, FILE *, int, char *)); +print_address_symbolic PARAMS ((CORE_ADDR, GDB_FILE *, int, char *)); extern void -print_address PARAMS ((CORE_ADDR, FILE *)); +print_address_numeric PARAMS ((CORE_ADDR, int, GDB_FILE *)); + +extern void +print_address PARAMS ((CORE_ADDR, GDB_FILE *)); /* From source.c */ @@ -384,6 +432,10 @@ enum val_prettyprint #include "nm.h" +#ifdef KERNEL_DEBUG +extern int kernel_debugging; +#endif + /* If the xm.h file did not define the mode string used to open the files, assume that binary files are opened the same way as text files */ @@ -466,80 +518,32 @@ enum val_prettyprint #define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */ #endif -/* Number of bits in a char or unsigned char for the target machine. - Just like CHAR_BIT in but describes the target machine. */ -#if !defined (TARGET_CHAR_BIT) -#define TARGET_CHAR_BIT 8 -#endif +#ifdef BFD64 -/* Number of bits in a short or unsigned short for the target machine. */ -#if !defined (TARGET_SHORT_BIT) -#define TARGET_SHORT_BIT (2 * TARGET_CHAR_BIT) -#endif +/* This is to make sure that LONGEST is at least as big as CORE_ADDR. */ -/* Number of bits in an int or unsigned int for the target machine. */ -#if !defined (TARGET_INT_BIT) -#define TARGET_INT_BIT (4 * TARGET_CHAR_BIT) -#endif +#define LONGEST BFD_HOST_64_BIT -/* Number of bits in a long or unsigned long for the target machine. */ -#if !defined (TARGET_LONG_BIT) -#define TARGET_LONG_BIT (4 * TARGET_CHAR_BIT) -#endif +#else /* No BFD64 */ -/* Number of bits in a long long or unsigned long long for the target machine. */ -#if !defined (TARGET_LONG_LONG_BIT) -#define TARGET_LONG_LONG_BIT (2 * TARGET_LONG_BIT) -#endif +/* If all compilers for this host support "long long" and we want to + use it for LONGEST (the performance hit is about 10% on a testsuite + run based on one DECstation test), then the xm.h file can define + CC_HAS_LONG_LONG. -/* Number of bits in a float for the target machine. */ -#if !defined (TARGET_FLOAT_BIT) -#define TARGET_FLOAT_BIT (4 * TARGET_CHAR_BIT) -#endif - -/* Number of bits in a double for the target machine. */ -#if !defined (TARGET_DOUBLE_BIT) -#define TARGET_DOUBLE_BIT (8 * TARGET_CHAR_BIT) -#endif - -/* Number of bits in a long double for the target machine. */ -#if !defined (TARGET_LONG_DOUBLE_BIT) -#define TARGET_LONG_DOUBLE_BIT (2 * TARGET_DOUBLE_BIT) -#endif - -/* Number of bits in a "complex" for the target machine. */ -#if !defined (TARGET_COMPLEX_BIT) -#define TARGET_COMPLEX_BIT (2 * TARGET_FLOAT_BIT) -#endif - -/* Number of bits in a "double complex" for the target machine. */ -#if !defined (TARGET_DOUBLE_COMPLEX_BIT) -#define TARGET_DOUBLE_COMPLEX_BIT (2 * TARGET_DOUBLE_BIT) -#endif - -/* Number of bits in a pointer for the target machine */ -#if !defined (TARGET_PTR_BIT) -#define TARGET_PTR_BIT TARGET_INT_BIT -#endif - -/* Default to support for "long long" if the host compiler being used is gcc. - Config files must define CC_HAS_LONG_LONG to use other host compilers - that are capable of supporting "long long", and to cause gdb to use that - support. Not defining CC_HAS_LONG_LONG will suppress use of "long long" - regardless of what compiler is used. - - FIXME: For now, automatic selection of "long long" as the default when - gcc is used is disabled, pending further testing. Concerns include the - impact on gdb performance and the universality of bugfree long long - support on platforms that do have gcc. Compiling with FORCE_LONG_LONG - will select "long long" use for testing purposes. -fnf */ + Using GCC 1.39 on BSDI with long long causes about 700 new + testsuite failures. Using long long for LONGEST on the DECstation + causes 3 new FAILs in the testsuite and many heuristic fencepost + warnings. These are not investigated, but a first guess would be + that the BSDI problems are GCC bugs in long long support and the + latter are GDB bugs. */ #ifndef CC_HAS_LONG_LONG -# if defined (__GNUC__) && defined (FORCE_LONG_LONG) /* See FIXME above */ +# if defined (__GNUC__) && defined (FORCE_LONG_LONG) # define CC_HAS_LONG_LONG 1 # endif #endif - + /* LONGEST should not be a typedef, because "unsigned LONGEST" needs to work. CC_HAS_LONG_LONG is defined if the host compiler supports "long long" variables and we wish to make use of that support. */ @@ -552,30 +556,13 @@ enum val_prettyprint # endif #endif +#endif /* No BFD64 */ + /* Convert a LONGEST to an int. This is used in contexts (e.g. number of arguments to a function, number in a value history, register number, etc.) where the value must not be larger than can fit in an int. */ -#ifndef longest_to_int -# ifdef CC_HAS_LONG_LONG -# define longest_to_int(x) (((x) > INT_MAX || (x) < INT_MIN) \ - ? (error ("Value out of range."),0) : (int) (x)) -# else - /* Assume sizeof (int) == sizeof (long). */ -# define longest_to_int(x) ((int) (x)) -# endif -#endif - -/* If we picked up a copy of CHAR_BIT from a configuration file - (which may get it by including ) then use it to set - the number of bits in a host char. If not, use the same size - as the target. */ - -#if defined (CHAR_BIT) -#define HOST_CHAR_BIT CHAR_BIT -#else -#define HOST_CHAR_BIT TARGET_CHAR_BIT -#endif +extern int longest_to_int PARAMS ((LONGEST)); /* Assorted functions we can declare, now that const and volatile are defined. */ @@ -627,9 +614,19 @@ parse_escape PARAMS ((char **)); extern const char * const reg_names[]; +/* Message to be printed before the error message, when an error occurs. */ + +extern char *error_pre_print; + +/* Message to be printed before the warning message, when a warning occurs. */ + +extern char *warning_pre_print; + extern NORETURN void /* Does not return to the caller. */ error (); +extern void error_begin PARAMS ((void)); + extern NORETURN void /* Does not return to the caller. */ fatal (); @@ -723,7 +720,7 @@ psignal PARAMS ((unsigned, const char *)); #endif extern int -fclose PARAMS ((FILE *stream)); /* 4.9.5.1 */ +fclose PARAMS ((GDB_FILE *stream)); /* 4.9.5.1 */ extern void perror PARAMS ((const char *)); /* 4.9.10.4 */ @@ -750,7 +747,7 @@ free PARAMS ((void *)); /* 4.10.3.2 */ extern void qsort PARAMS ((void *base, size_t nmemb, /* 4.10.5.2 */ size_t size, - int (*comp)(const void *, const void *))); + int (*compar)(const void *, const void *))); #ifndef MEM_FNS_DECLARED /* Some non-ANSI use void *, not char *. */ extern PTR @@ -784,17 +781,21 @@ strerror PARAMS ((int)); /* 4.11.6.2 */ #ifndef alloca # ifdef __GNUC__ # define alloca __builtin_alloca -# else +# else /* Not GNU C */ # ifdef sparc # include /* NOTE: Doesn't declare alloca() */ # endif -# ifdef __STDC__ - extern void *alloca (size_t); -# else /* __STDC__ */ + +/* We need to be careful not to declare this in a way which conflicts with + bison. Bison never declares it as char *, but under various circumstances + (like __hpux) we need to use void *. */ +# if defined (__STDC__) || defined (__hpux) + extern void *alloca (); +# else /* Don't use void *. */ extern char *alloca (); -# endif -# endif -#endif +# endif /* Don't use void *. */ +# endif /* Not GNU C */ +#endif /* alloca not defined */ /* TARGET_BYTE_ORDER and HOST_BYTE_ORDER must be defined to one of these. */ @@ -813,6 +814,73 @@ strerror PARAMS ((int)); /* 4.11.6.2 */ #include "tm.h" +/* Number of bits in a char or unsigned char for the target machine. + Just like CHAR_BIT in but describes the target machine. */ +#if !defined (TARGET_CHAR_BIT) +#define TARGET_CHAR_BIT 8 +#endif + +/* Number of bits in a short or unsigned short for the target machine. */ +#if !defined (TARGET_SHORT_BIT) +#define TARGET_SHORT_BIT (2 * TARGET_CHAR_BIT) +#endif + +/* Number of bits in an int or unsigned int for the target machine. */ +#if !defined (TARGET_INT_BIT) +#define TARGET_INT_BIT (4 * TARGET_CHAR_BIT) +#endif + +/* Number of bits in a long or unsigned long for the target machine. */ +#if !defined (TARGET_LONG_BIT) +#define TARGET_LONG_BIT (4 * TARGET_CHAR_BIT) +#endif + +/* Number of bits in a long long or unsigned long long for the target machine. */ +#if !defined (TARGET_LONG_LONG_BIT) +#define TARGET_LONG_LONG_BIT (2 * TARGET_LONG_BIT) +#endif + +/* Number of bits in a float for the target machine. */ +#if !defined (TARGET_FLOAT_BIT) +#define TARGET_FLOAT_BIT (4 * TARGET_CHAR_BIT) +#endif + +/* Number of bits in a double for the target machine. */ +#if !defined (TARGET_DOUBLE_BIT) +#define TARGET_DOUBLE_BIT (8 * TARGET_CHAR_BIT) +#endif + +/* Number of bits in a long double for the target machine. */ +#if !defined (TARGET_LONG_DOUBLE_BIT) +#define TARGET_LONG_DOUBLE_BIT (2 * TARGET_DOUBLE_BIT) +#endif + +/* Number of bits in a "complex" for the target machine. */ +#if !defined (TARGET_COMPLEX_BIT) +#define TARGET_COMPLEX_BIT (2 * TARGET_FLOAT_BIT) +#endif + +/* Number of bits in a "double complex" for the target machine. */ +#if !defined (TARGET_DOUBLE_COMPLEX_BIT) +#define TARGET_DOUBLE_COMPLEX_BIT (2 * TARGET_DOUBLE_BIT) +#endif + +/* Number of bits in a pointer for the target machine */ +#if !defined (TARGET_PTR_BIT) +#define TARGET_PTR_BIT TARGET_INT_BIT +#endif + +/* If we picked up a copy of CHAR_BIT from a configuration file + (which may get it by including ) then use it to set + the number of bits in a host char. If not, use the same size + as the target. */ + +#if defined (CHAR_BIT) +#define HOST_CHAR_BIT CHAR_BIT +#else +#define HOST_CHAR_BIT TARGET_CHAR_BIT +#endif + /* The bit byte-order has to do just with numbering of bits in debugging symbols and such. Conceptually, it's quite separate from byte/word byte order. */ @@ -827,27 +895,6 @@ strerror PARAMS ((int)); /* 4.11.6.2 */ #endif /* Little endian. */ #endif /* BITS_BIG_ENDIAN not defined. */ -/* Swap LEN bytes at BUFFER between target and host byte-order. This is - the wrong way to do byte-swapping because it assumes that you have a way - to have a host variable of exactly the right size. - extract_* are the right way. */ -#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER -#define SWAP_TARGET_AND_HOST(buffer,len) -#else /* Target and host byte order differ. */ -#define SWAP_TARGET_AND_HOST(buffer,len) \ - { \ - char tmp; \ - char *p = (char *)(buffer); \ - char *q = ((char *)(buffer)) + len - 1; \ - for (; p < q; p++, q--) \ - { \ - tmp = *q; \ - *q = *p; \ - *p = tmp; \ - } \ - } -#endif /* Target and host byte order differ. */ - /* In findvar.c. */ LONGEST extract_signed_integer PARAMS ((void *, int)); unsigned LONGEST extract_unsigned_integer PARAMS ((void *, int)); @@ -856,6 +903,9 @@ CORE_ADDR extract_address PARAMS ((void *, int)); void store_signed_integer PARAMS ((void *, int, LONGEST)); void store_unsigned_integer PARAMS ((void *, int, unsigned LONGEST)); void store_address PARAMS ((void *, int, CORE_ADDR)); + +double extract_floating PARAMS ((void *, int)); +void store_floating PARAMS ((void *, int, double)); /* On some machines there are bits in addresses which are not really part of the address, but are used by the kernel, the hardware, etc. @@ -875,13 +925,8 @@ void store_address PARAMS ((void *, int, CORE_ADDR)); extern CORE_ADDR push_bytes PARAMS ((CORE_ADDR, char *, int)); -/* In some modules, we don't have a definition of REGISTER_TYPE yet, so we - must avoid prototyping this function for now. FIXME. Should be: extern CORE_ADDR -push_word PARAMS ((CORE_ADDR, REGISTER_TYPE)); - */ -extern CORE_ADDR -push_word (); +push_word PARAMS ((CORE_ADDR, unsigned LONGEST)); /* Some parts of gdb might be considered optional, in the sense that they are not essential for being able to build a working, usable debugger diff --git a/gnu/usr.bin/gdb/gdb/demangle.c b/gnu/usr.bin/gdb/gdb/demangle.c index a134bb70ad98..eecd3d3ed429 100644 --- a/gnu/usr.bin/gdb/gdb/demangle.c +++ b/gnu/usr.bin/gdb/gdb/demangle.c @@ -70,17 +70,6 @@ static const struct demangler {NULL, unknown_demangling, NULL} }; -/* show current demangling style. */ - -static void -show_demangling_command (ignore, from_tty) - char *ignore; - int from_tty; -{ - /* done automatically by show command. */ -} - - /* set current demangling style. called by the "set demangling" command after it has updated the current_demangling_style_string to match what the user has entered. @@ -98,9 +87,10 @@ show_demangling_command (ignore, from_tty) a malloc'd string, even if it is a null-string. */ static void -set_demangling_command (ignore, from_tty) - char *ignore; - int from_tty; +set_demangling_command (ignore, from_tty, c) + char *ignore; + int from_tty; + struct cmd_list_element *c; { const struct demangler *dem; @@ -127,19 +117,20 @@ set_demangling_command (ignore, from_tty) { if (*current_demangling_style_string != '\0') { - printf ("Unknown demangling style `%s'.\n", + printf_unfiltered ("Unknown demangling style `%s'.\n", current_demangling_style_string); } - printf ("The currently understood settings are:\n\n"); + printf_unfiltered ("The currently understood settings are:\n\n"); for (dem = demanglers; dem -> demangling_style_name != NULL; dem++) { - printf ("%-10s %s\n", dem -> demangling_style_name, + printf_unfiltered ("%-10s %s\n", dem -> demangling_style_name, dem -> demangling_style_doc); if (dem -> demangling_style == current_demangling_style) { free (current_demangling_style_string); current_demangling_style_string = - strdup (dem -> demangling_style_name); + savestring (dem -> demangling_style_name, + strlen (dem -> demangling_style_name)); } } if (current_demangling_style == unknown_demangling) @@ -149,7 +140,8 @@ set_demangling_command (ignore, from_tty) one as the default. */ current_demangling_style = demanglers[0].demangling_style; current_demangling_style_string = - strdup (demanglers[0].demangling_style_name); + savestring (demanglers[0].demangling_style_name, + strlen (demanglers[0].demangling_style_name)); warning ("`%s' style demangling chosen as the default.\n", current_demangling_style_string); } @@ -166,7 +158,7 @@ set_demangling_style (style) { free (current_demangling_style_string); } - current_demangling_style_string = strdup (style); + current_demangling_style_string = savestring (style, strlen (style)); set_demangling_command ((char *) NULL, 0); } @@ -181,8 +173,7 @@ _initialize_demangler () Use `set demangle-style' without arguments for a list of demangling styles.", &setlist); show = add_show_from_set (set, &showlist); - set -> function.cfunc = set_demangling_command; - show -> function.cfunc = show_demangling_command; + set -> function.sfunc = set_demangling_command; /* Set the default demangling style chosen at compilation time. */ set_demangling_style (DEFAULT_DEMANGLING_STYLE); diff --git a/gnu/usr.bin/gdb/gdb/demangle.h b/gnu/usr.bin/gdb/gdb/demangle.h index 4f191a2e1ade..a216799cda95 100644 --- a/gnu/usr.bin/gdb/gdb/demangle.h +++ b/gnu/usr.bin/gdb/gdb/demangle.h @@ -69,6 +69,9 @@ extern enum demangling_styles extern char * cplus_demangle PARAMS ((CONST char *mangled, int options)); +extern int +cplus_demangle_opname PARAMS ((char *opname, char *result, int options)); + /* Note: This sets global state. FIXME if you care about multi-threading. */ extern void diff --git a/gnu/usr.bin/gdb/gdb/dis-asm.h b/gnu/usr.bin/gdb/gdb/dis-asm.h index e7f106c318cb..50601d74095c 100644 --- a/gnu/usr.bin/gdb/gdb/dis-asm.h +++ b/gnu/usr.bin/gdb/gdb/dis-asm.h @@ -19,7 +19,7 @@ enum dis_insn_type { dis_jsr, /* Jump to subroutine */ dis_condjsr, /* Conditional jump to subroutine */ dis_dref, /* Data reference instruction */ - dis_dref2, /* Two data references in instruction */ + dis_dref2 /* Two data references in instruction */ }; /* This struct is passed into the instruction decoding routine, @@ -111,10 +111,13 @@ extern int print_insn_i960 PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_sh PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_hppa PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_m88k PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_ns32k PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_big_powerpc PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_little_powerpc PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_rs6000 PARAMS ((bfd_vma, disassemble_info*)); - - - +/* Fetch the disassembler for a given BFD, if that support is available. */ +extern disassembler_ftype disassembler PARAMS ((bfd *)); /* This block of definitions is for particular callers who read instructions diff --git a/gnu/usr.bin/gdb/gdb/dis-buf.c b/gnu/usr.bin/gdb/gdb/dis-buf.c index d07da6fcff31..d184b28405a8 100644 --- a/gnu/usr.bin/gdb/gdb/dis-buf.c +++ b/gnu/usr.bin/gdb/gdb/dis-buf.c @@ -1,5 +1,5 @@ /* Disassemble from a buffer, for GNU. - Copyright (C) 1993 Free Software Foundation, Inc. + Copyright (C) 1993, 1994 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,6 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "dis-asm.h" +#include "sysdep.h" #include /* Get LENGTH bytes from info's buffer, at target address memaddr. diff --git a/gnu/usr.bin/gdb/gdb/dwarfread.c b/gnu/usr.bin/gdb/gdb/dwarfread.c index 5d19bf8d0b07..96196f536e55 100644 --- a/gnu/usr.bin/gdb/gdb/dwarfread.c +++ b/gnu/usr.bin/gdb/gdb/dwarfread.c @@ -1,5 +1,5 @@ /* DWARF debugging format support for GDB. - Copyright (C) 1991, 1992 Free Software Foundation, Inc. + Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. Portions based on dbxread.c, mipsread.c, coffread.c, and dwarfread.c from a Data General SVR4 gdb port. @@ -44,9 +44,6 @@ other things to work on, if you get bored. :-) #include "gdbtypes.h" #include "symfile.h" #include "objfiles.h" -#include /* For time_t in libbfd.h. */ -#include /* For time_t, if not in time.h. */ -#include "libbfd.h" /* FIXME Secret Internal BFD stuff (bfd_read) */ #include "elf/dwarf.h" #include "buildsym.h" #include "demangle.h" @@ -56,7 +53,6 @@ other things to work on, if you get bored. :-) #include #include -#include #ifndef NO_SYS_FILE #include @@ -1989,10 +1985,21 @@ process_dies (thisdie, enddie, objfile) { nextdie = thisdie + di.die_length; } +#ifdef SMASH_TEXT_ADDRESS + /* I think that these are always text, not data, addresses. */ + SMASH_TEXT_ADDRESS (di.at_low_pc); + SMASH_TEXT_ADDRESS (di.at_high_pc); +#endif switch (di.die_tag) { case TAG_compile_unit: - read_file_scope (&di, thisdie, nextdie, objfile); + /* Skip Tag_compile_unit if we are already inside a compilation + unit, we are unable to handle nested compilation units + properly (FIXME). */ + if (current_subfile == NULL) + read_file_scope (&di, thisdie, nextdie, objfile); + else + nextdie = thisdie + di.die_length; break; case TAG_global_subroutine: case TAG_subroutine: @@ -2364,14 +2371,14 @@ psymtab_to_symtab_1 (pst) /* Inform about additional files that need to be read in. */ if (info_verbose) { - fputs_filtered (" ", stdout); + fputs_filtered (" ", gdb_stdout); wrap_here (""); - fputs_filtered ("and ", stdout); + fputs_filtered ("and ", gdb_stdout); wrap_here (""); printf_filtered ("%s...", pst -> dependencies[i] -> filename); wrap_here (""); - fflush (stdout); /* Flush output */ + gdb_flush (gdb_stdout); /* Flush output */ } psymtab_to_symtab_1 (pst -> dependencies[i]); } @@ -2385,7 +2392,7 @@ psymtab_to_symtab_1 (pst) { printf_filtered ("%d DIE's, sorting...", diecount); wrap_here (""); - fflush (stdout); + gdb_flush (gdb_stdout); } sort_symtab_syms (pst -> symtab); do_cleanups (old_chain); @@ -2435,7 +2442,7 @@ dwarf_psymtab_to_symtab (pst) { printf_filtered ("Reading in symbols for %s...", pst -> filename); - fflush (stdout); + gdb_flush (gdb_stdout); } psymtab_to_symtab_1 (pst); @@ -2453,7 +2460,7 @@ dwarf_psymtab_to_symtab (pst) if (info_verbose) { printf_filtered ("done.\n"); - fflush (stdout); + gdb_flush (gdb_stdout); } } } @@ -2613,6 +2620,9 @@ add_partial_symbol (dip, objfile) case TAG_structure_type: case TAG_union_type: case TAG_enumeration_type: + /* Do not add opaque aggregate definitions to the psymtab. */ + if (!dip -> has_at_byte_size) + break; ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name), STRUCT_NAMESPACE, LOC_TYPEDEF, objfile -> static_psymbols, diff --git a/gnu/usr.bin/gdb/gdb/elf/common.h b/gnu/usr.bin/gdb/gdb/elf/common.h index cd708f1489cf..d5d1bb0687ad 100644 --- a/gnu/usr.bin/gdb/gdb/elf/common.h +++ b/gnu/usr.bin/gdb/gdb/elf/common.h @@ -1,5 +1,5 @@ /* ELF support for BFD. - Copyright (C) 1991, 1992 Free Software Foundation, Inc. + Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published in "UNIX System V Release 4, Programmers Guide: ANSI C and @@ -69,16 +69,27 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Values for e_machine, which identifies the architecture */ -#define EM_NONE 0 /* No machine */ -#define EM_M32 1 /* AT&T WE 32100 */ -#define EM_SPARC 2 /* SUN SPARC */ -#define EM_386 3 /* Intel 80386 */ -#define EM_68K 4 /* Motorola m68k family */ -#define EM_88K 5 /* Motorola m88k family */ -#define EM_860 7 /* Intel 80860 */ -#define EM_MIPS 8 /* MIPS R3000 */ -#define EM_HPPA 9 /* HP PA-RISC */ +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ + +#define EM_SPARC64 11 /* SPARC v9 (not official) 64-bit */ + +#define EM_PARISC 15 /* HPPA */ + +/* If it is necessary to assign new unofficial EM_* values, please pick large + random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision + with official or non-GNU unofficial values. */ + +/* Cygnus PowerPC ELF backend. Written in the absence of an ABI. */ +#define EM_CYGNUS_POWERPC 0x9025 /* Values for e_version */ @@ -169,7 +180,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ other places. */ #define SHN_UNDEF 0 /* Undefined section reference */ -#define SHN_LORESERV 0xFF00 /* Begin range of reserved indices */ +#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ #define SHN_LOPROC 0xFF00 /* Begin range of appl-specific */ #define SHN_HIPROC 0xFF1F /* End range of appl-specific */ #define SHN_ABS 0xFFF1 /* Associated symbol is absolute */ @@ -178,13 +189,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* relocation info handling macros */ -#define ELF32_R_SYM(i) ((i)>>8) -#define ELF32_R_TYPE(i) ((unsigned char)(i)) -#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((i) & 0xff) +#define ELF32_R_INFO(s,t) (((s) << 8) + ((t) & 0xff)) -#define ELF64_R_SYM(i) ((i)>>32) -#define ELF64_R_TYPE(i) ((Elf64_Word)(i)) -#define ELF64_R_INFO(s,t) (((Elf64_Xword)(s)<<32)+(Elf64_Xword)(t)) +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(s,t) (((bfd_vma) (s) << 32) + (bfd_vma) (t)) /* Dynamic section tags */ diff --git a/gnu/usr.bin/gdb/gdb/elf/internal.h b/gnu/usr.bin/gdb/gdb/elf/internal.h index ae4bdada5ea9..717606771759 100644 --- a/gnu/usr.bin/gdb/gdb/elf/internal.h +++ b/gnu/usr.bin/gdb/gdb/elf/internal.h @@ -1,5 +1,5 @@ /* ELF support for BFD. - Copyright (C) 1991, 1992 Free Software Foundation, Inc. + Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published in "UNIX System V Release 4, Programmers Guide: ANSI C and @@ -28,24 +28,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ the elf-common.h file which contains the portions that are common to both the internal and external representations. */ -/* Types used by various structures, functions, etc. */ - -typedef unsigned long Elf32_Addr; /* Unsigned program address */ -typedef unsigned long Elf32_Off; /* Unsigned file offset */ -typedef long Elf32_Sword; /* Signed large integer */ -typedef unsigned long Elf32_Word; /* Unsigned large integer */ -typedef unsigned short Elf32_Half; /* Unsigned medium integer */ -typedef unsigned char Elf32_Char; /* Unsigned tiny integer */ - -#ifdef HOST_64_BIT -typedef unsigned HOST_64_BIT Elf64_Addr; -typedef unsigned HOST_64_BIT Elf64_Off; -typedef HOST_64_BIT Elf64_Sxword; -typedef unsigned HOST_64_BIT Elf64_Xword; -#endif -typedef long Elf64_Sword; -typedef unsigned long Elf64_Word; -typedef unsigned short Elf64_Half; /* NOTE that these structures are not kept in the same order as they appear in the object file. In some cases they've been reordered for more optimal @@ -111,8 +93,8 @@ typedef struct elf_internal_shdr { unsigned int sh_addralign; /* Section alignment */ /* The internal rep also has some cached info associated with it. */ - void *rawdata; /* null if unused... */ - void *contents; /* null if unused... */ + PTR rawdata; /* null if unused... */ + PTR contents; /* null if unused... */ bfd_vma size; /* size of contents (0 if unused) */ } Elf_Internal_Shdr; @@ -176,20 +158,17 @@ typedef struct elf_internal_rela { /* dynamic section structure */ -typedef struct { - Elf32_Sword d_tag; /* entry tag value */ +typedef struct elf_internal_dyn { + /* This needs to support 64-bit values in elf64. */ + bfd_vma d_tag; /* entry tag value */ union { - Elf32_Word d_val; - Elf32_Addr d_ptr; + /* This needs to support 64-bit values in elf64. */ + bfd_vma d_val; + bfd_vma d_ptr; } d_un; -} Elf32_Internal_Dyn; +} Elf_Internal_Dyn; -#ifdef HOST_64_BIT -typedef struct { - Elf64_Xword d_tag; /* entry tag value */ - union { - Elf64_Xword d_val; - Elf64_Addr d_ptr; - } d_un; -} Elf64_Internal_Dyn; -#endif +#define elf32_internal_dyn elf_internal_dyn +#define elf64_internal_dyn elf_internal_dyn +#define Elf32_Internal_Dyn Elf_Internal_Dyn +#define Elf64_Internal_Dyn Elf_Internal_Dyn diff --git a/gnu/usr.bin/gdb/gdb/elfread.c b/gnu/usr.bin/gdb/gdb/elfread.c index 230afecefb2e..93b11ef9571d 100644 --- a/gnu/usr.bin/gdb/gdb/elfread.c +++ b/gnu/usr.bin/gdb/gdb/elfread.c @@ -1,5 +1,5 @@ /* Read ELF (Executable and Linking Format) object files for GDB. - Copyright 1991, 1992 Free Software Foundation, Inc. + Copyright 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. This file is part of GDB. @@ -20,10 +20,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" #include "bfd.h" -#include /* For time_t in libbfd.h. */ -#include /* For time_t, if not in time.h. */ -#include "libbfd.h" /* For bfd_elf_find_section */ +#include #include "libelf.h" +/*#include "elf/mips.h"*/ #include "symtab.h" #include "symfile.h" #include "objfiles.h" @@ -31,7 +30,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "stabsread.h" #include "gdb-stabs.h" #include "complaints.h" -#include #include "demangle.h" /* The struct elfinfo is available only during ELF symbol table and @@ -45,6 +43,7 @@ struct elfinfo { unsigned int lnsize; /* Size of dwarf line number section */ asection *stabsect; /* Section pointer for .stab section */ asection *stabindexsect; /* Section pointer for .stab.index section */ + asection *mdebugsect; /* Section pointer for .mdebug section */ }; /* Various things we might complain about... */ @@ -74,7 +73,7 @@ static void elf_symfile_finish PARAMS ((struct objfile *)); static void -elf_symtab_read PARAMS ((bfd *, CORE_ADDR, struct objfile *)); +elf_symtab_read PARAMS ((bfd *, CORE_ADDR, struct objfile *, int)); static void free_elfinfo PARAMS ((void *)); @@ -136,6 +135,10 @@ elf_locate_sections (ignore_abfd, sectp, eip) { ei -> stabindexsect = sectp; } + else if (STREQ (sectp -> name, ".mdebug")) + { + ei -> mdebugsect = sectp; + } } #if 0 /* Currently unused */ @@ -185,6 +188,9 @@ record_minimal_symbol_and_info (name, address, ms_type, info, objfile) case mst_text: case mst_file_text: section = SECT_OFF_TEXT; +#ifdef SMASH_TEXT_ADDRESS + SMASH_TEXT_ADDRESS (address); +#endif break; case mst_data: case mst_file_data: @@ -200,7 +206,8 @@ record_minimal_symbol_and_info (name, address, ms_type, info, objfile) } name = obsavestring (name, strlen (name), &objfile -> symbol_obstack); - prim_record_minimal_symbol_and_info (name, address, ms_type, info, section); + prim_record_minimal_symbol_and_info (name, address, ms_type, info, section, + objfile); } /* @@ -230,16 +237,17 @@ DESCRIPTION */ static void -elf_symtab_read (abfd, addr, objfile) +elf_symtab_read (abfd, addr, objfile, dynamic) bfd *abfd; CORE_ADDR addr; struct objfile *objfile; + int dynamic; { - unsigned int storage_needed; + long storage_needed; asymbol *sym; asymbol **symbol_table; - unsigned int number_of_symbols; - unsigned int i; + long number_of_symbols; + long i; int index; struct cleanup *back_to; CORE_ADDR symaddr; @@ -253,13 +261,35 @@ elf_symtab_read (abfd, addr, objfile) struct dbx_symfile_info *dbx = (struct dbx_symfile_info *) objfile->sym_stab_info; unsigned long size; - - storage_needed = get_symtab_upper_bound (abfd); + int stripped = (bfd_get_symcount (abfd) == 0); + + if (dynamic) + { + storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd); + + /* Nothing to be done if there is no dynamic symtab. */ + if (storage_needed < 0) + return; + } + else + { + storage_needed = bfd_get_symtab_upper_bound (abfd); + if (storage_needed < 0) + error ("Can't read symbols from %s: %s", bfd_get_filename (abfd), + bfd_errmsg (bfd_get_error ())); + } if (storage_needed > 0) { symbol_table = (asymbol **) xmalloc (storage_needed); back_to = make_cleanup (free, symbol_table); - number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); + if (dynamic) + number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd, + symbol_table); + else + number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); + if (number_of_symbols < 0) + error ("Can't read symbols from %s: %s", bfd_get_filename (abfd), + bfd_errmsg (bfd_get_error ())); for (i = 0; i < number_of_symbols; i++) { sym = symbol_table[i]; @@ -269,6 +299,15 @@ elf_symtab_read (abfd, addr, objfile) that are null strings (may happen). */ continue; } + + /* If it is a nonstripped executable, do not enter dynamic + symbols, as the dynamic symbol table is usually a subset + of the main symbol table. + On Irix 5 however, the symbols for the procedure linkage + table entries have meaningful values only in the dynamic + symbol table, so we always examine undefined symbols. */ + if (dynamic && !stripped && sym -> section != &bfd_und_section) + continue; if (sym -> flags & BSF_FILE) { /* STT_FILE debugging symbol that helps stabs-in-elf debugging. @@ -296,9 +335,52 @@ elf_symtab_read (abfd, addr, objfile) /* For non-absolute symbols, use the type of the section they are relative to, to intuit text/data. Bfd provides no way of figuring this out for absolute symbols. */ - if (sym -> section == &bfd_abs_section) + if (sym -> section == &bfd_und_section + && (sym -> flags & BSF_GLOBAL) + && (sym -> flags & BSF_FUNCTION)) { - ms_type = mst_abs; + /* Symbol is a reference to a function defined in + a shared library. + If its value is non zero then it is usually the + absolute address of the corresponding entry in + the procedure linkage table. + If its value is zero then the dynamic linker has to + resolve the symbol. We are unable to find any + meaningful address for this symbol in the + executable file, so we skip it. + Irix 5 has a zero value for all shared library functions + in the main symbol table, but the dynamic symbol table + provides the right values. */ + ms_type = mst_solib_trampoline; + symaddr = sym -> value; + if (symaddr == 0) + continue; + symaddr += addr; + } + else if (sym -> section == &bfd_abs_section) + { + /* This is a hack to get the minimal symbol type + right for Irix 5, which has absolute adresses + with special section indices for dynamic symbols. */ + unsigned short shndx = + ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx; + + switch (shndx) + { +#if 0 + case SHN_MIPS_TEXT: + ms_type = mst_text; + break; + case SHN_MIPS_DATA: + ms_type = mst_data; + break; + case SHN_MIPS_ACOMMON: + ms_type = mst_bss; + break; +#endif + default: + ms_type = mst_abs; + } } else if (sym -> section -> flags & SEC_CODE) { @@ -306,7 +388,10 @@ elf_symtab_read (abfd, addr, objfile) { ms_type = mst_text; } - else if (sym->name[0] == '.' && sym->name[1] == 'L') + else if ((sym->name[0] == '.' && sym->name[1] == 'L') + || ((sym -> flags & BSF_LOCAL) + && sym->name[0] == 'L' + && sym->name[1] == 'L')) /* Looks like a compiler-generated label. Skip it. The assembler should be skipping these (to keep executables small), but apparently with gcc on the @@ -447,7 +532,8 @@ elf_symtab_read (abfd, addr, objfile) format to look for: FIXME!!! dwarf_build_psymtabs() builds psymtabs for DWARF symbols; - elfstab_build_psymtabs() handles STABS symbols. + elfstab_build_psymtabs() handles STABS symbols; + mdebug_build_psymtabs() handles ECOFF debugging information. Note that ELF files have a "minimal" symbol table, which looks a lot like a COFF symbol table, but has only the minimal information necessary @@ -483,7 +569,11 @@ elf_symfile_read (objfile, section_offsets, mainline) /* FIXME, should take a section_offsets param, not just an offset. */ offset = ANOFFSET (section_offsets, 0); - elf_symtab_read (abfd, offset, objfile); + elf_symtab_read (abfd, offset, objfile, 0); + + /* Add the dynamic symbols. */ + + elf_symtab_read (abfd, offset, objfile, 1); /* Now process debugging information, which is contained in special ELF sections. We first have to find them... */ @@ -499,32 +589,32 @@ elf_symfile_read (objfile, section_offsets, mainline) } if (ei.stabsect) { - /* STABS sections */ + asection *str_sect; - /* FIXME: Sun didn't really know how to implement this well. - They made .stab sections that don't point to the .stabstr - section with the sh_link field. BFD doesn't make string table - sections visible to the caller. So we have to search the - ELF section table, not the BFD section table, for the string - table. */ - struct elf32_internal_shdr *elf_sect; + /* Stab sections have an associated string table that looks like + a separate section. */ + str_sect = bfd_get_section_by_name (abfd, ".stabstr"); - elf_sect = bfd_elf_find_section (abfd, ".stabstr"); - if (elf_sect) + /* FIXME should probably warn about a stab section without a stabstr. */ + if (str_sect) elfstab_build_psymtabs (objfile, - section_offsets, - mainline, - ei.stabsect->filepos, /* .stab offset */ - bfd_get_section_size_before_reloc (ei.stabsect),/* .stab size */ - (file_ptr) elf_sect->sh_offset, /* .stabstr offset */ - elf_sect->sh_size); /* .stabstr size */ + section_offsets, + mainline, + ei.stabsect->filepos, + bfd_section_size (abfd, ei.stabsect), + str_sect->filepos, + bfd_section_size (abfd, str_sect)); } - - if (!have_partial_symbols ()) + if (ei.mdebugsect) { - wrap_here (""); - printf_filtered ("(no debugging symbols found)..."); - wrap_here (""); + const struct ecoff_debug_swap *swap; + + /* .mdebug section, presumably holding ECOFF debugging + information. */ + swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; + if (swap) + elfmdebug_build_psymtabs (objfile, swap, ei.mdebugsect, + section_offsets); } /* Install any minimal symbols that have been collected as the current @@ -615,15 +705,16 @@ elf_symfile_offsets (objfile, addr) { struct section_offsets *section_offsets; int i; - + + objfile->num_sections = SECT_OFF_MAX; section_offsets = (struct section_offsets *) obstack_alloc (&objfile -> psymbol_obstack, - sizeof (struct section_offsets) + - sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1)); + sizeof (struct section_offsets) + + sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1)); for (i = 0; i < SECT_OFF_MAX; i++) ANOFFSET (section_offsets, i) = addr; - + return section_offsets; } @@ -694,26 +785,11 @@ elfstab_offset_sections (objfile, pst) complain (&stab_info_mismatch_complaint, filename); } -/* Register that we are able to handle ELF object file formats and DWARF - debugging formats. - - Unlike other object file formats, where the debugging information format - is implied by the object file format, the ELF object file format and the - DWARF debugging information format are two distinct, and potentially - separate entities. I.E. it is perfectly possible to have ELF objects - with debugging formats other than DWARF. And it is conceivable that the - DWARF debugging format might be used with another object file format, - like COFF, by simply using COFF's custom section feature. - - GDB, and to a lesser extent BFD, should support the notion of separate - object file formats and debugging information formats. For now, we just - use "elf" in the same sense as "a.out" or "coff", to imply both the ELF - object file format and the DWARF debugging format. */ +/* Register that we are able to handle ELF object file formats. */ static struct sym_fns elf_sym_fns = { - "elf", /* sym_name: name or name prefix of BFD target type */ - 3, /* sym_namelen: number of significant sym_name chars */ + bfd_target_elf_flavour, elf_new_init, /* sym_new_init: init anything gbl to entire symtab */ elf_symfile_init, /* sym_init: read initial info, setup for sym_read() */ elf_symfile_read, /* sym_read: read a symbol file into symtab */ diff --git a/gnu/usr.bin/gdb/gdb/environ.c b/gnu/usr.bin/gdb/gdb/environ.c index 4089212e5add..5d7a640025b0 100644 --- a/gnu/usr.bin/gdb/gdb/environ.c +++ b/gnu/usr.bin/gdb/gdb/environ.c @@ -21,7 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" #include "environ.h" #include -#include "defs.h" /* For strsave(). */ +#include "gdbcore.h" /* Return a new environment object. */ @@ -64,6 +64,9 @@ init_environ (e) extern char **environ; register int i; + if (environ == NULL) + return; + for (i = 0; environ[i]; i++) /*EMPTY*/; if (e->allocated < i) @@ -149,23 +152,16 @@ set_in_environ (e, var, value) strcat (s, value); vector[i] = s; - /* Certain variables get exported back to the parent (e.g. our) - environment, too. FIXME: this is a hideous hack and should not be - allowed to live. What if we want to change the environment we pass to - the program without affecting GDB's behavior? */ - if (STREQ(var, "PATH")) /* Object file location */ - { - putenv (strsave (s)); - } + /* This used to handle setting the PATH and GNUTARGET variables + specially. The latter has been replaced by "set gnutarget" + (which has worked since GDB 4.11). The former affects searching + the PATH to find SHELL, and searching the PATH to find the + argument of "symbol-file" or "exec-file". Maybe we should have + some kind of "set exec-path" for that. But in any event, having + "set env" affect anything besides the inferior is a bad idea. + What if we want to change the environment we pass to the program + without afecting GDB's behavior? */ - /* This is a compatibility hack, since GDB 4.10 and older didn't have - `set gnutarget'. Eventually it should go away, so that (for example) - you can debug objdump's handling of GNUTARGET without affecting GDB's - behavior. */ - if (STREQ (var, "GNUTARGET")) - { - set_gnutarget (value); - } return; } diff --git a/gnu/usr.bin/gdb/gdb/eval.c b/gnu/usr.bin/gdb/gdb/eval.c index f641a65f95a4..46e95fba09b4 100644 --- a/gnu/usr.bin/gdb/gdb/eval.c +++ b/gnu/usr.bin/gdb/gdb/eval.c @@ -1,5 +1,6 @@ /* Evaluate expressions for GDB. - Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc. + Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -18,12 +19,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" +#include #include "symtab.h" #include "gdbtypes.h" #include "value.h" #include "expression.h" #include "target.h" #include "frame.h" +#include "demangle.h" #include "language.h" /* For CAST_IS_CONVERSION */ /* Values of NOSIDE argument to eval_subexp. */ @@ -43,18 +46,18 @@ enum noside /* Prototypes for local functions. */ -static value +static value_ptr evaluate_subexp_for_sizeof PARAMS ((struct expression *, int *)); -static value +static value_ptr evaluate_subexp_with_coercion PARAMS ((struct expression *, int *, enum noside)); -static value +static value_ptr evaluate_subexp_for_address PARAMS ((struct expression *, int *, enum noside)); -static value +static value_ptr evaluate_subexp PARAMS ((struct type *, struct expression *, int *, enum noside)); @@ -93,12 +96,12 @@ parse_and_eval_address_1 (expptr) return addr; } -value +value_ptr parse_and_eval (exp) char *exp; { struct expression *expr = parse_expression (exp); - register value val; + register value_ptr val; register struct cleanup *old_chain = make_cleanup (free_current_contents, &expr); @@ -111,12 +114,12 @@ parse_and_eval (exp) in the string EXPP as an expression, evaluate it, and return the value. EXPP is advanced to point to the comma. */ -value +value_ptr parse_to_comma_and_eval (expp) char **expp; { struct expression *expr = parse_exp_1 (expp, (struct block *) 0, 1); - register value val; + register value_ptr val; register struct cleanup *old_chain = make_cleanup (free_current_contents, &expr); @@ -130,12 +133,7 @@ parse_to_comma_and_eval (expp) See expression.h for info on the format of an expression. */ -static value evaluate_subexp (); -static value evaluate_subexp_for_address (); -static value evaluate_subexp_for_sizeof (); -static value evaluate_subexp_with_coercion (); - -value +value_ptr evaluate_expression (exp) struct expression *exp; { @@ -146,7 +144,7 @@ evaluate_expression (exp) /* Evaluate an expression, avoiding all memory references and getting a value whose type alone is correct. */ -value +value_ptr evaluate_type (exp) struct expression *exp; { @@ -154,7 +152,7 @@ evaluate_type (exp) return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_AVOID_SIDE_EFFECTS); } -static value +static value_ptr evaluate_subexp (expect_type, exp, pos, noside) struct type *expect_type; register struct expression *exp; @@ -164,10 +162,10 @@ evaluate_subexp (expect_type, exp, pos, noside) enum exp_opcode op; int tem, tem2, tem3; register int pc, pc2 = 0, oldpos; - register value arg1 = NULL, arg2 = NULL, arg3; + register value_ptr arg1 = NULL, arg2 = NULL, arg3; struct type *type; int nargs; - value *argvec; + value_ptr *argvec; pc = (*pos)++; op = exp->elts[pc].opcode; @@ -263,7 +261,7 @@ evaluate_subexp (expect_type, exp, pos, noside) tem2 = longest_to_int (exp->elts[pc + 1].longconst); tem3 = longest_to_int (exp->elts[pc + 2].longconst); nargs = tem3 - tem2 + 1; - argvec = (value *) alloca (sizeof (value) * nargs); + argvec = (value_ptr *) alloca (sizeof (value_ptr) * nargs); for (tem = 0; tem < nargs; tem++) { /* Ensure that array expressions are coerced into pointer objects. */ @@ -341,7 +339,7 @@ evaluate_subexp (expect_type, exp, pos, noside) for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j) if (TYPE_FN_FIELD_VOFFSET (f, j) == fnoffset) { - value temp = value_ind (arg2); + value_ptr temp = value_ind (arg2); arg1 = value_virtual_fn_field (&temp, f, j, domain_type, 0); arg2 = value_addr (temp); goto got_it; @@ -404,7 +402,7 @@ evaluate_subexp (expect_type, exp, pos, noside) } /* Allocate arg vector, including space for the function to be called in argvec[0] and a terminating NULL */ - argvec = (value *) alloca (sizeof (value) * (nargs + 2)); + argvec = (value_ptr *) alloca (sizeof (value_ptr) * (nargs + 2)); for (; tem <= nargs; tem++) /* Ensure that array expressions are coerced into pointer objects. */ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside); @@ -415,17 +413,25 @@ evaluate_subexp (expect_type, exp, pos, noside) if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR) { int static_memfuncp; - value temp = arg2; + value_ptr temp = arg2; + char tstr[64]; argvec[1] = arg2; - argvec[0] = - value_struct_elt (&temp, argvec+1, &exp->elts[pc2 + 2].string, + argvec[0] = 0; + strcpy(tstr, &exp->elts[pc2+2].string); + if (!argvec[0]) + { + temp = arg2; + argvec[0] = + value_struct_elt (&temp, argvec+1, tstr, &static_memfuncp, op == STRUCTOP_STRUCT ? "structure" : "structure pointer"); - arg2 = value_from_longest (lookup_pointer_type (VALUE_TYPE (temp)), - VALUE_ADDRESS (temp)+VALUE_OFFSET (temp)); + } + arg2 = value_from_longest (lookup_pointer_type(VALUE_TYPE (temp)), + VALUE_ADDRESS (temp)+VALUE_OFFSET (temp)); argvec[1] = arg2; + if (static_memfuncp) { argvec[1] = argvec[0]; @@ -473,9 +479,9 @@ evaluate_subexp (expect_type, exp, pos, noside) lval_memory); else { - value temp = arg1; - return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 2].string, - (int *) 0, "structure"); + value_ptr temp = arg1; + return value_struct_elt (&temp, NULL, &exp->elts[pc + 2].string, + NULL, "structure"); } case STRUCTOP_PTR: @@ -491,9 +497,9 @@ evaluate_subexp (expect_type, exp, pos, noside) lval_memory); else { - value temp = arg1; - return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 2].string, - (int *) 0, "structure pointer"); + value_ptr temp = arg1; + return value_struct_elt (&temp, NULL, &exp->elts[pc + 2].string, + NULL, "structure pointer"); } case STRUCTOP_MEMBER: @@ -623,6 +629,13 @@ evaluate_subexp (expect_type, exp, pos, noside) return value_x_binop (arg1, arg2, op, OP_NULL); else return value_subscript (arg1, arg2); + + case BINOP_IN: + arg1 = evaluate_subexp_with_coercion (exp, pos, noside); + arg2 = evaluate_subexp_with_coercion (exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + return value_in (arg1, arg2); case MULTI_SUBSCRIPT: (*pos) += 2; @@ -1028,7 +1041,7 @@ GDB does not (yet) know how to evaluated that kind of expression"); NOSIDE may be EVAL_AVOID_SIDE_EFFECTS; then only the type of the result need be correct. */ -static value +static value_ptr evaluate_subexp_for_address (exp, pos, noside) register struct expression *exp; register int *pos; @@ -1086,7 +1099,7 @@ evaluate_subexp_for_address (exp, pos, noside) default_case: if (noside == EVAL_AVOID_SIDE_EFFECTS) { - value x = evaluate_subexp (NULL_TYPE, exp, pos, noside); + value_ptr x = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (VALUE_LVAL (x) == lval_memory) return value_zero (lookup_pointer_type (VALUE_TYPE (x)), not_lval); @@ -1110,7 +1123,7 @@ evaluate_subexp_for_address (exp, pos, noside) */ -static value +static value_ptr evaluate_subexp_with_coercion (exp, pos, noside) register struct expression *exp; register int *pos; @@ -1118,7 +1131,7 @@ evaluate_subexp_with_coercion (exp, pos, noside) { register enum exp_opcode op; register int pc; - register value val; + register value_ptr val; struct symbol *var; pc = (*pos); @@ -1149,14 +1162,14 @@ evaluate_subexp_with_coercion (exp, pos, noside) and return a value for the size of that subexpression. Advance *POS over the subexpression. */ -static value +static value_ptr evaluate_subexp_for_sizeof (exp, pos) register struct expression *exp; register int *pos; { enum exp_opcode op; register int pc; - value val; + value_ptr val; pc = (*pos); op = exp->elts[pc].opcode; diff --git a/gnu/usr.bin/gdb/gdb/exec.c b/gnu/usr.bin/gdb/gdb/exec.c index f66a33c2cdc5..8bc872b71bb2 100644 --- a/gnu/usr.bin/gdb/gdb/exec.c +++ b/gnu/usr.bin/gdb/gdb/exec.c @@ -1,5 +1,5 @@ /* Work with executable files, for GDB. - Copyright 1988, 1989, 1991, 1992 Free Software Foundation, Inc. + Copyright 1988, 1989, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "inferior.h" #include "target.h" #include "gdbcmd.h" +#include "language.h" #ifdef USG #include @@ -148,15 +149,25 @@ exec_file_command (args, from_tty) exec_bfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan); if (!exec_bfd) error ("Could not open `%s' as an executable file: %s", - scratch_pathname, bfd_errmsg (bfd_error)); + scratch_pathname, bfd_errmsg (bfd_get_error ())); if (!bfd_check_format (exec_bfd, bfd_object)) - error ("\"%s\": not in executable format: %s.", - scratch_pathname, bfd_errmsg (bfd_error)); + { + /* Make sure to close exec_bfd, or else "run" might try to use + it. */ + exec_close (0); + error ("\"%s\": not in executable format: %s.", + scratch_pathname, bfd_errmsg (bfd_get_error ())); + } if (build_section_table (exec_bfd, &exec_ops.to_sections, &exec_ops.to_sections_end)) - error ("Can't find the file sections in `%s': %s", - exec_bfd->filename, bfd_errmsg (bfd_error)); + { + /* Make sure to close exec_bfd, or else "run" might try to use + it. */ + exec_close (0); + error ("Can't find the file sections in `%s': %s", + exec_bfd->filename, bfd_errmsg (bfd_get_error ())); + } #ifdef NEED_TEXT_START_END @@ -173,7 +184,7 @@ exec_file_command (args, from_tty) text_start = ~(CORE_ADDR)0; text_end = (CORE_ADDR)0; for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++) - if (bfd_get_section_flags (p->bfd, p->sec_ptr) + if (bfd_get_section_flags (p->bfd, p->the_bfd_section) & (SEC_CODE | SEC_READONLY)) { if (text_start > p->addr) @@ -193,7 +204,7 @@ exec_file_command (args, from_tty) (*exec_file_display_hook) (filename); } else if (from_tty) - printf ("No exec file now.\n"); + printf_unfiltered ("No exec file now.\n"); } /* Set both the exec file and the symbol file, in one command. @@ -226,13 +237,12 @@ add_to_section_table (abfd, asect, table_pp_char) flagword aflag; aflag = bfd_get_section_flags (abfd, asect); - /* FIXME, we need to handle BSS segment here...it alloc's but doesn't load */ - if (!(aflag & SEC_LOAD)) + if (!(aflag & SEC_ALLOC)) return; if (0 == bfd_section_size (abfd, asect)) return; (*table_pp)->bfd = abfd; - (*table_pp)->sec_ptr = asect; + (*table_pp)->the_bfd_section = asect; (*table_pp)->addr = bfd_section_vma (abfd, asect); (*table_pp)->endaddr = (*table_pp)->addr + bfd_section_size (abfd, asect); (*table_pp)++; @@ -304,8 +314,8 @@ xfer_memory (memaddr, myaddr, len, write, target) if (p->endaddr >= memend) { /* Entire transfer is within this section. */ - res = xfer_fn (p->bfd, p->sec_ptr, myaddr, memaddr - p->addr, len); - return (res != false)? len: 0; + res = xfer_fn (p->bfd, p->the_bfd_section, myaddr, memaddr - p->addr, len); + return (res != 0) ? len : 0; } else if (p->endaddr <= memaddr) { @@ -316,8 +326,8 @@ xfer_memory (memaddr, myaddr, len, write, target) { /* This section overlaps the transfer. Just do half. */ len = p->endaddr - memaddr; - res = xfer_fn (p->bfd, p->sec_ptr, myaddr, memaddr - p->addr, len); - return (res != false)? len: 0; + res = xfer_fn (p->bfd, p->the_bfd_section, myaddr, memaddr - p->addr, len); + return (res != 0) ? len : 0; } else if (p->addr < nextsectaddr) nextsectaddr = p->addr; @@ -354,20 +364,27 @@ print_section_info (t, abfd) printf_filtered ("\t`%s', ", bfd_get_filename(abfd)); wrap_here (" "); printf_filtered ("file type %s.\n", bfd_get_target(abfd)); - printf_filtered ("\tEntry point: %s\n", - local_hex_string ((unsigned long) bfd_get_start_address (exec_bfd))); - for (p = t->to_sections; p < t->to_sections_end; p++) { - printf_filtered ("\t%s", local_hex_string_custom ((unsigned long) p->addr, "08l")); - printf_filtered (" - %s", local_hex_string_custom ((unsigned long) p->endaddr, "08l")); - if (info_verbose) - printf_filtered (" @ %s", - local_hex_string_custom ((unsigned long) p->sec_ptr->filepos, "08l")); - printf_filtered (" is %s", bfd_section_name (p->bfd, p->sec_ptr)); - if (p->bfd != abfd) { - printf_filtered (" in %s", bfd_get_filename (p->bfd)); + if (abfd == exec_bfd) + { + printf_filtered ("\tEntry point: "); + print_address_numeric (bfd_get_start_address (abfd), 1, gdb_stdout); + printf_filtered ("\n"); + } + for (p = t->to_sections; p < t->to_sections_end; p++) + { + /* FIXME-32x64 need a print_address_numeric with field width */ + printf_filtered ("\t%s", local_hex_string_custom ((unsigned long) p->addr, "08l")); + printf_filtered (" - %s", local_hex_string_custom ((unsigned long) p->endaddr, "08l")); + if (info_verbose) + printf_filtered (" @ %s", + local_hex_string_custom ((unsigned long) p->the_bfd_section->filepos, "08l")); + printf_filtered (" is %s", bfd_section_name (p->bfd, p->the_bfd_section)); + if (p->bfd != abfd) + { + printf_filtered (" in %s", bfd_get_filename (p->bfd)); + } + printf_filtered ("\n"); } - printf_filtered ("\n"); - } } static void @@ -400,8 +417,8 @@ set_section_command (args, from_tty) secaddr = parse_and_eval_address (args); for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++) { - if (!strncmp (secname, bfd_section_name (exec_bfd, p->sec_ptr), seclen) - && bfd_section_name (exec_bfd, p->sec_ptr)[seclen] == '\0') { + if (!strncmp (secname, bfd_section_name (exec_bfd, p->the_bfd_section), seclen) + && bfd_section_name (exec_bfd, p->the_bfd_section)[seclen] == '\0') { offset = secaddr - p->addr; p->addr += offset; p->endaddr += offset; diff --git a/gnu/usr.bin/gdb/gdb/expprint.c b/gnu/usr.bin/gdb/gdb/expprint.c index 607b3df7037a..4948f4ad4f9a 100644 --- a/gnu/usr.bin/gdb/gdb/expprint.c +++ b/gnu/usr.bin/gdb/gdb/expprint.c @@ -28,15 +28,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Prototypes for local functions */ static void -print_subexp PARAMS ((struct expression *, int *, FILE *, enum precedence)); +print_subexp PARAMS ((struct expression *, int *, GDB_FILE *, enum precedence)); static void -print_simple_m2_func PARAMS ((char *, struct expression *, int *, FILE *)); +print_simple_m2_func PARAMS ((char *, struct expression *, int *, GDB_FILE *)); void print_expression (exp, stream) struct expression *exp; - FILE *stream; + GDB_FILE *stream; { int pc = 0; print_subexp (exp, &pc, stream, PREC_NULL); @@ -51,7 +51,7 @@ static void print_subexp (exp, pos, stream, prec) register struct expression *exp; register int *pos; - FILE *stream; + GDB_FILE *stream; enum precedence prec; { register unsigned tem; @@ -64,7 +64,7 @@ print_subexp (exp, pos, stream, prec) enum precedence myprec = PREC_NULL; /* Set to 1 for a right-associative operator. */ int assoc = 0; - value val; + value_ptr val; char *tempstr = NULL; op_print_tab = exp->language_defn->la_op_print_tab; @@ -340,23 +340,23 @@ print_subexp (exp, pos, stream, prec) (*pos) += 2; nargs = longest_to_int (exp->elts[pc + 1].longconst); print_subexp (exp, pos, stream, PREC_SUFFIX); - fprintf (stream, " ["); + fprintf_unfiltered (stream, " ["); for (tem = 0; tem < nargs; tem++) { if (tem != 0) - fprintf (stream, ", "); + fprintf_unfiltered (stream, ", "); print_subexp (exp, pos, stream, PREC_ABOVE_COMMA); } - fprintf (stream, "]"); + fprintf_unfiltered (stream, "]"); return; case BINOP_VAL: (*pos)+=2; - fprintf(stream,"VAL("); + fprintf_unfiltered(stream,"VAL("); type_print(exp->elts[pc+1].type,"",stream,0); - fprintf(stream,","); + fprintf_unfiltered(stream,","); print_subexp(exp,pos,stream,PREC_PREFIX); - fprintf(stream,")"); + fprintf_unfiltered(stream,")"); return; case UNOP_CAP: @@ -466,11 +466,11 @@ print_simple_m2_func(s,exp,pos,stream) char *s; register struct expression *exp; register int *pos; - FILE *stream; + GDB_FILE *stream; { - fprintf(stream,"%s(",s); + fprintf_unfiltered(stream,"%s(",s); print_subexp(exp,pos,stream,PREC_PREFIX); - fprintf(stream,")"); + fprintf_unfiltered(stream,")"); } /* Return the operator corresponding to opcode OP as @@ -498,7 +498,7 @@ op_string(op) void dump_expression (exp, stream, note) struct expression *exp; - FILE *stream; + GDB_FILE *stream; char *note; { int elt; @@ -506,8 +506,9 @@ dump_expression (exp, stream, note) char *eltscan; int eltsize; - fprintf_filtered (stream, "Dump of expression @ 0x%lx, %s:\n", - (unsigned long) exp, note); + fprintf_filtered (stream, "Dump of expression @ "); + gdb_print_address (exp, stream); + fprintf_filtered (stream, ", %s:\n", note); fprintf_filtered (stream, "\tLanguage %s, %d elements, %d bytes each.\n", exp->language_defn->la_name, exp -> nelts, sizeof (union exp_element)); diff --git a/gnu/usr.bin/gdb/gdb/expression.h b/gnu/usr.bin/gdb/gdb/expression.h index 521c25cb45a4..1f85a3f80706 100644 --- a/gnu/usr.bin/gdb/gdb/expression.h +++ b/gnu/usr.bin/gdb/gdb/expression.h @@ -104,6 +104,9 @@ enum exp_opcode the second operand with itself that many times. */ BINOP_CONCAT, + /* For Chill and Pascal. */ + BINOP_IN, /* Returns 1 iff ARG1 IN ARG2. */ + /* This must be the highest BINOP_ value, for expprint.c. */ BINOP_END, @@ -292,7 +295,7 @@ extern struct block *innermost_block; /* From expprint.c */ extern void -print_expression PARAMS ((struct expression *, FILE *)); +print_expression PARAMS ((struct expression *, GDB_FILE *)); extern char * op_string PARAMS ((enum exp_opcode)); @@ -304,7 +307,7 @@ op_string PARAMS ((enum exp_opcode)); #ifdef DEBUG_EXPRESSIONS extern void -dump_expression PARAMS ((struct expression *, FILE *, char *)); +dump_expression PARAMS ((struct expression *, GDB_FILE *, char *)); #define DUMP_EXPRESSION(exp,file,note) dump_expression ((exp), (file), (note)) #else #define DUMP_EXPRESSION(exp,file,note) /* Null expansion */ diff --git a/gnu/usr.bin/gdb/gdb/findvar.c b/gnu/usr.bin/gdb/gdb/findvar.c index bf50e1f04541..98be44937055 100644 --- a/gnu/usr.bin/gdb/gdb/findvar.c +++ b/gnu/usr.bin/gdb/gdb/findvar.c @@ -168,6 +168,90 @@ store_address (addr, len, val) store_unsigned_integer (addr, len, (LONGEST)val); } +/* Swap LEN bytes at BUFFER between target and host byte-order. This is + the wrong way to do byte-swapping because it assumes that you have a way + to have a host variable of exactly the right size. Once extract_floating + and store_floating have been fixed, this can go away. */ +#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER +#define SWAP_TARGET_AND_HOST(buffer,len) +#else /* Target and host byte order differ. */ +#define SWAP_TARGET_AND_HOST(buffer,len) \ + { \ + char tmp; \ + char *p = (char *)(buffer); \ + char *q = ((char *)(buffer)) + len - 1; \ + for (; p < q; p++, q--) \ + { \ + tmp = *q; \ + *q = *p; \ + *p = tmp; \ + } \ + } +#endif /* Target and host byte order differ. */ + +/* There are many problems with floating point cross-debugging. + + 1. These routines only handle byte-swapping, not conversion of + formats. So if host is IEEE floating and target is VAX floating, + or vice-versa, it loses. This means that we can't (yet) use these + routines for extendeds. Extendeds are handled by + REGISTER_CONVERTIBLE. What we want is to use floatformat.h, but that + doesn't yet handle VAX floating at all. + + 2. We can't deal with it if there is more than one floating point + format in use. This has to be fixed at the unpack_double level. + + 3. We probably should have a LONGEST_DOUBLE or DOUBLEST or whatever + we want to call it which is long double where available. */ + +double +extract_floating (addr, len) + PTR addr; + int len; +{ + if (len == sizeof (float)) + { + float retval; + memcpy (&retval, addr, sizeof (retval)); + SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); + return retval; + } + else if (len == sizeof (double)) + { + double retval; + memcpy (&retval, addr, sizeof (retval)); + SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); + return retval; + } + else + { + error ("Can't deal with a floating point number of %d bytes.", len); + } +} + +void +store_floating (addr, len, val) + PTR addr; + int len; + double val; +{ + if (len == sizeof (float)) + { + float floatval = val; + SWAP_TARGET_AND_HOST (&floatval, sizeof (floatval)); + memcpy (addr, &floatval, sizeof (floatval)); + } + else if (len == sizeof (double)) + { + SWAP_TARGET_AND_HOST (&val, sizeof (val)); + memcpy (addr, &val, sizeof (val)); + } + else + { + error ("Can't deal with a floating point number of %d bytes.", len); + } +} + #if !defined (GET_SAVED_REGISTER) /* Return the address in which frame FRAME's value of register REGNUM @@ -332,29 +416,38 @@ read_relative_register_raw_bytes (regnum, myaddr) in its virtual format, with the type specified by REGISTER_VIRTUAL_TYPE. */ -value +value_ptr value_of_register (regnum) int regnum; { CORE_ADDR addr; int optim; - register value val; + register value_ptr reg_val; char raw_buffer[MAX_REGISTER_RAW_SIZE]; - char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; enum lval_type lval; get_saved_register (raw_buffer, &optim, &addr, selected_frame, regnum, &lval); - REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer); - val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum)); - memcpy (VALUE_CONTENTS_RAW (val), virtual_buffer, - REGISTER_VIRTUAL_SIZE (regnum)); - VALUE_LVAL (val) = lval; - VALUE_ADDRESS (val) = addr; - VALUE_REGNO (val) = regnum; - VALUE_OPTIMIZED_OUT (val) = optim; - return val; + reg_val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum)); + + /* Convert raw data to virtual format if necessary. */ + +#ifdef REGISTER_CONVERTIBLE + if (REGISTER_CONVERTIBLE (regnum)) + { + REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum), + raw_buffer, VALUE_CONTENTS_RAW (reg_val)); + } + else +#endif + memcpy (VALUE_CONTENTS_RAW (reg_val), raw_buffer, + REGISTER_RAW_SIZE (regnum)); + VALUE_LVAL (reg_val) = lval; + VALUE_ADDRESS (reg_val) = addr; + VALUE_REGNO (reg_val) = regnum; + VALUE_OPTIMIZED_OUT (reg_val) = optim; + return reg_val; } /* Low level examining and depositing of registers. @@ -372,12 +465,21 @@ char registers[REGISTER_BYTES + /* SLOP */ 256]; /* Nonzero if that register has been fetched. */ char register_valid[NUM_REGS]; +/* The thread/process associated with the current set of registers. For now, + -1 is special, and means `no current process'. */ +int registers_pid = -1; + /* Indicate that registers may have changed, so invalidate the cache. */ + void registers_changed () { int i; - for (i = 0; i < NUM_REGS; i++) + int numregs = ARCH_NUM_REGS; + + registers_pid = -1; + + for (i = 0; i < numregs; i++) register_valid[i] = 0; } @@ -386,7 +488,8 @@ void registers_fetched () { int i; - for (i = 0; i < NUM_REGS; i++) + int numregs = ARCH_NUM_REGS; + for (i = 0; i < numregs; i++) register_valid[i] = 1; } @@ -401,8 +504,16 @@ read_register_bytes (regbyte, myaddr, len) int len; { /* Fetch all registers. */ - int i; - for (i = 0; i < NUM_REGS; i++) + int i, numregs; + + if (registers_pid != inferior_pid) + { + registers_changed (); + registers_pid = inferior_pid; + } + + numregs = ARCH_NUM_REGS; + for (i = 0; i < numregs; i++) if (!register_valid[i]) { target_fetch_registers (-1); @@ -421,6 +532,12 @@ read_register_gen (regno, myaddr) int regno; char *myaddr; { + if (registers_pid != inferior_pid) + { + registers_changed (); + registers_pid = inferior_pid; + } + if (!register_valid[regno]) target_fetch_registers (regno); memcpy (myaddr, ®isters[REGISTER_BYTE (regno)], @@ -436,6 +553,12 @@ write_register_bytes (regbyte, myaddr, len) char *myaddr; int len; { + if (registers_pid != inferior_pid) + { + registers_changed (); + registers_pid = inferior_pid; + } + /* Make sure the entire registers array is valid. */ read_register_bytes (0, (char *)NULL, REGISTER_BYTES); memcpy (®isters[regbyte], myaddr, len); @@ -449,6 +572,12 @@ CORE_ADDR read_register (regno) int regno; { + if (registers_pid != inferior_pid) + { + registers_changed (); + registers_pid = inferior_pid; + } + if (!register_valid[regno]) target_fetch_registers (regno); @@ -456,6 +585,27 @@ read_register (regno) REGISTER_RAW_SIZE(regno)); } +CORE_ADDR +read_register_pid (regno, pid) + int regno, pid; +{ + int save_pid; + CORE_ADDR retval; + + if (pid == inferior_pid) + return read_register (regno); + + save_pid = inferior_pid; + + inferior_pid = pid; + + retval = read_register (regno); + + inferior_pid = save_pid; + + return retval; +} + /* Registers we shouldn't try to store. */ #if !defined (CANNOT_STORE_REGISTER) #define CANNOT_STORE_REGISTER(regno) 0 @@ -477,6 +627,12 @@ write_register (regno, val) if (CANNOT_STORE_REGISTER (regno)) return; + if (registers_pid != inferior_pid) + { + registers_changed (); + registers_pid = inferior_pid; + } + size = REGISTER_RAW_SIZE(regno); buf = alloca (size); store_signed_integer (buf, size, (LONGEST) val); @@ -484,11 +640,9 @@ write_register (regno, val) /* If we have a valid copy of the register, and new value == old value, then don't bother doing the actual store. */ - if (register_valid [regno]) - { - if (memcmp (®isters[REGISTER_BYTE (regno)], buf, size) == 0) - return; - } + if (register_valid [regno] + && memcmp (®isters[REGISTER_BYTE (regno)], buf, size) == 0) + return; target_prepare_to_store (); @@ -499,6 +653,29 @@ write_register (regno, val) target_store_registers (regno); } +void +write_register_pid (regno, val, pid) + int regno; + LONGEST val; + int pid; +{ + int save_pid; + + if (pid == inferior_pid) + { + write_register (regno, val); + return; + } + + save_pid = inferior_pid; + + inferior_pid = pid; + + write_register (regno, val); + + inferior_pid = save_pid; +} + /* Record that register REGNO contains VAL. This is used when the value is obtained from the inferior or core dump, so there is no need to store the value there. */ @@ -508,6 +685,12 @@ supply_register (regno, val) int regno; char *val; { + if (registers_pid != inferior_pid) + { + registers_changed (); + registers_pid = inferior_pid; + } + register_valid[regno] = 1; memcpy (®isters[REGISTER_BYTE (regno)], val, REGISTER_RAW_SIZE (regno)); @@ -517,6 +700,111 @@ supply_register (regno, val) CLEAN_UP_REGISTER_VALUE(regno, ®isters[REGISTER_BYTE(regno)]); #endif } + + +/* This routine is getting awfully cluttered with #if's. It's probably + time to turn this into READ_PC and define it in the tm.h file. + Ditto for write_pc. */ + +CORE_ADDR +read_pc () +{ +#ifdef TARGET_READ_PC + return TARGET_READ_PC (inferior_pid); +#else + return ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, inferior_pid)); +#endif +} + +CORE_ADDR +read_pc_pid (pid) + int pid; +{ +#ifdef TARGET_READ_PC + return TARGET_READ_PC (pid); +#else + return ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, pid)); +#endif +} + +void +write_pc (val) + CORE_ADDR val; +{ +#ifdef TARGET_WRITE_PC + TARGET_WRITE_PC (val, inferior_pid); +#else + write_register_pid (PC_REGNUM, (long) val, inferior_pid); +#ifdef NPC_REGNUM + write_register_pid (NPC_REGNUM, (long) val + 4, inferior_pid); +#ifdef NNPC_REGNUM + write_register_pid (NNPC_REGNUM, (long) val + 8, inferior_pid); +#endif +#endif +#endif +} + +void +write_pc_pid (val, pid) + CORE_ADDR val; + int pid; +{ +#ifdef TARGET_WRITE_PC + TARGET_WRITE_PC (val, pid); +#else + write_register_pid (PC_REGNUM, (long) val, pid); +#ifdef NPC_REGNUM + write_register_pid (NPC_REGNUM, (long) val + 4, pid); +#ifdef NNPC_REGNUM + write_register_pid (NNPC_REGNUM, (long) val + 8, pid); +#endif +#endif +#endif +} + +/* Cope with strage ways of getting to the stack and frame pointers */ + +CORE_ADDR +read_sp () +{ +#ifdef TARGET_READ_SP + return TARGET_READ_SP (); +#else + return read_register (SP_REGNUM); +#endif +} + +void +write_sp (val) + CORE_ADDR val; +{ +#ifdef TARGET_WRITE_SP + TARGET_WRITE_SP (val); +#else + write_register (SP_REGNUM, val); +#endif +} + +CORE_ADDR +read_fp () +{ +#ifdef TARGET_READ_FP + return TARGET_READ_FP (); +#else + return read_register (FP_REGNUM); +#endif +} + +void +write_fp (val) + CORE_ADDR val; +{ +#ifdef TARGET_WRITE_FP + TARGET_WRITE_FP (val); +#else + write_register (FP_REGNUM, val); +#endif +} /* Will calling read_var_value or locate_var_value on SYM end up caring what frame it is being evaluated relative to? SYM must @@ -555,6 +843,7 @@ symbol_read_needs_frame (sym) case LOC_OPTIMIZED_OUT: return 0; } + return 1; } /* Given a struct symbol for a variable, @@ -563,12 +852,12 @@ symbol_read_needs_frame (sym) If the variable cannot be found, return a zero pointer. If FRAME is NULL, use the selected_frame. */ -value +value_ptr read_var_value (var, frame) register struct symbol *var; FRAME frame; { - register value v; + register value_ptr v; struct frame_info *fi; struct type *type = SYMBOL_TYPE (var); CORE_ADDR addr; @@ -672,15 +961,17 @@ read_var_value (var, frame) return 0; b = get_frame_block (frame); - v = value_from_register (type, SYMBOL_VALUE (var), frame); if (SYMBOL_CLASS (var) == LOC_REGPARM_ADDR) { - addr = *(CORE_ADDR *)VALUE_CONTENTS (v); + addr = + value_as_pointer (value_from_register (lookup_pointer_type (type), + SYMBOL_VALUE (var), + frame)); VALUE_LVAL (v) = lval_memory; } else - return v; + return value_from_register (type, SYMBOL_VALUE (var), frame); } break; @@ -702,17 +993,16 @@ read_var_value (var, frame) /* Return a value of type TYPE, stored in register REGNUM, in frame FRAME. */ -value +value_ptr value_from_register (type, regnum, frame) struct type *type; int regnum; FRAME frame; { char raw_buffer [MAX_REGISTER_RAW_SIZE]; - char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; CORE_ADDR addr; int optim; - value v = allocate_value (type); + value_ptr v = allocate_value (type); int len = TYPE_LENGTH (type); char *value_bytes = 0; int value_bytes_copied = 0; @@ -878,36 +1168,17 @@ value_from_register (type, regnum, frame) VALUE_OPTIMIZED_OUT (v) = optim; VALUE_LVAL (v) = lval; VALUE_ADDRESS (v) = addr; + + /* Convert raw data to virtual format if necessary. */ - /* Convert the raw contents to virtual contents. - (Just copy them if the formats are the same.) */ - - REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer); - +#ifdef REGISTER_CONVERTIBLE if (REGISTER_CONVERTIBLE (regnum)) { - /* When the raw and virtual formats differ, the virtual format - corresponds to a specific data type. If we want that type, - copy the data into the value. - Otherwise, do a type-conversion. */ - - if (type != REGISTER_VIRTUAL_TYPE (regnum)) - { - /* eg a variable of type `float' in a 68881 register - with raw type `extended' and virtual type `double'. - Fetch it as a `double' and then convert to `float'. */ - /* FIXME: This value will be not_lval, which means we can't assign - to it. Probably the right fix is to do the cast on a temporary - value, and just copy the VALUE_CONTENTS over. */ - v = allocate_value (REGISTER_VIRTUAL_TYPE (regnum)); - memcpy (VALUE_CONTENTS_RAW (v), virtual_buffer, - REGISTER_VIRTUAL_SIZE (regnum)); - v = value_cast (type, v); - } - else - memcpy (VALUE_CONTENTS_RAW (v), virtual_buffer, len); + REGISTER_CONVERT_TO_VIRTUAL (regnum, type, + raw_buffer, VALUE_CONTENTS_RAW (v)); } else +#endif { /* Raw and virtual formats are the same for this register. */ @@ -919,7 +1190,7 @@ value_from_register (type, regnum, frame) } #endif - memcpy (VALUE_CONTENTS_RAW (v), virtual_buffer + VALUE_OFFSET (v), len); + memcpy (VALUE_CONTENTS_RAW (v), raw_buffer + VALUE_OFFSET (v), len); } return v; @@ -930,14 +1201,14 @@ value_from_register (type, regnum, frame) return a (pointer to a) struct value containing the properly typed address. */ -value +value_ptr locate_var_value (var, frame) register struct symbol *var; FRAME frame; { CORE_ADDR addr = 0; struct type *type = SYMBOL_TYPE (var); - value lazy_value; + value_ptr lazy_value; /* Evaluate it first; if the result is a memory address, we're fine. Lazy evaluation pays off here. */ diff --git a/gnu/usr.bin/gdb/gdb/fork-child.c b/gnu/usr.bin/gdb/gdb/fork-child.c index 3c01b6021eb5..26b74cf41654 100644 --- a/gnu/usr.bin/gdb/gdb/fork-child.c +++ b/gnu/usr.bin/gdb/gdb/fork-child.c @@ -1,5 +1,5 @@ /* Fork a Unix child process, and set up to debug it, for GDB. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Contributed by Cygnus Support. This file is part of GDB. @@ -19,48 +19,43 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" +#include #include "frame.h" /* required by inferior.h */ #include "inferior.h" #include "target.h" #include "wait.h" #include "gdbcore.h" #include "terminal.h" +#include "thread.h" #include -#ifdef SET_STACK_LIMIT_HUGE -#include -#include - -extern int original_stack_limit; -#endif /* SET_STACK_LIMIT_HUGE */ - extern char **environ; -/* Start an inferior Unix child process and sets inferior_pid to its pid. - EXEC_FILE is the file to run. - ALLARGS is a string containing the arguments to the program. - ENV is the environment vector to pass. Errors reported with error(). */ - #ifndef SHELL_FILE #define SHELL_FILE "/bin/sh" #endif +/* Start an inferior Unix child process and sets inferior_pid to its pid. + EXEC_FILE is the file to run. + ALLARGS is a string containing the arguments to the program. + ENV is the environment vector to pass. SHELL_FILE is the shell file, + or NULL if we should pick one. Errors reported with error(). */ + void -fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun) +fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun, + shell_file) char *exec_file; char *allargs; char **env; void (*traceme_fun) PARAMS ((void)); void (*init_trace_fun) PARAMS ((int)); + char *shell_file; { int pid; char *shell_command; - char *shell_file; static char default_shell_file[] = SHELL_FILE; int len; - int pending_execs; - int terminal_initted; /* Set debug_fork then attach to the child while it sleeps, to debug. */ static int debug_fork = 0; /* This is set to the result of setpgrp, which if vforked, will be visible @@ -76,9 +71,11 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun) /* The user might want tilde-expansion, and in general probably wants the program to behave the same way as if run from his/her favorite shell. So we let the shell run it for us. - FIXME, this should probably search the local environment (as - modified by the setenv command), not the env gdb inherited. */ - shell_file = getenv ("SHELL"); + FIXME-maybe, we might want a "set shell" command so the user can change + the shell from within GDB (if so, change callers which pass in a non-NULL + shell_file too). */ + if (shell_file == NULL) + shell_file = getenv ("SHELL"); if (shell_file == NULL) shell_file = default_shell_file; @@ -171,8 +168,8 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun) output prior to doing a fork, to avoid the possibility of both the parent and child flushing the same data after the fork. */ - fflush (stdout); - fflush (stderr); + gdb_flush (gdb_stdout); + gdb_flush (gdb_stderr); #if defined(USG) && !defined(HAVE_VFORK) pid = fork (); @@ -196,17 +193,6 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun) if (debug_setpgrp == -1) perror("setpgrp failed in child"); -#ifdef SET_STACK_LIMIT_HUGE - /* Reset the stack limit back to what it was. */ - { - struct rlimit rlim; - - getrlimit (RLIMIT_STACK, &rlim); - rlim.rlim_cur = original_stack_limit; - setrlimit (RLIMIT_STACK, &rlim); - } -#endif /* SET_STACK_LIMIT_HUGE */ - /* Ask the tty subsystem to switch to the one we specified earlier (or to share the current terminal, if none was specified). */ @@ -229,9 +215,9 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun) environ = env; execlp (shell_file, shell_file, "-c", shell_command, (char *)0); - fprintf (stderr, "Cannot exec %s: %s.\n", shell_file, + fprintf_unfiltered (gdb_stderr, "Cannot exec %s: %s.\n", shell_file, safe_strerror (errno)); - fflush (stderr); + gdb_flush (gdb_stderr); _exit (0177); } @@ -240,37 +226,47 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun) init_thread_list(); + inferior_pid = pid; /* Needed for wait_for_inferior stuff below */ + /* Now that we have a child process, make it our target, and initialize anything target-vector-specific that needs initializing. */ (*init_trace_fun)(pid); + /* We are now in the child process of interest, having exec'd the + correct program, and are poised at the first instruction of the + new program. */ +#ifdef SOLIB_CREATE_INFERIOR_HOOK + SOLIB_CREATE_INFERIOR_HOOK (pid); +#endif +} + +/* Accept NTRAPS traps from the inferior. */ + +void +startup_inferior (ntraps) + int ntraps; +{ + int pending_execs = ntraps; + int terminal_initted; + /* The process was started by the fork that created it, but it will have stopped one instruction after execing the shell. Here we must get it up to actual execution of the real program. */ - inferior_pid = pid; /* Needed for wait_for_inferior stuff below */ - clear_proceed_status (); - /* We will get a trace trap after one instruction. - Continue it automatically. Eventually (after shell does an exec) - it will get another trace trap. Then insert breakpoints and continue. */ - -#ifdef START_INFERIOR_TRAPS_EXPECTED - pending_execs = START_INFERIOR_TRAPS_EXPECTED; -#else - pending_execs = 2; -#endif - init_wait_for_inferior (); terminal_initted = 0; +#ifdef STARTUP_INFERIOR + STARTUP_INFERIOR (pending_execs); +#else while (1) { stop_soon_quietly = 1; /* Make wait_for_inferior be quiet */ wait_for_inferior (); - if (stop_signal != SIGTRAP) + if (stop_signal != TARGET_SIGNAL_TRAP) { /* Let shell child handle its own signals in its own way */ /* FIXME, what if child has exit()ed? Must exit loop somehow */ @@ -296,15 +292,9 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun) } if (0 == --pending_execs) break; - resume (0, 0); /* Just make it go on */ + resume (0, TARGET_SIGNAL_0); /* Just make it go on */ } } +#endif /* STARTUP_INFERIOR */ stop_soon_quietly = 0; - - /* We are now in the child process of interest, having exec'd the - correct program, and are poised at the first instruction of the - new program. */ -#ifdef SOLIB_CREATE_INFERIOR_HOOK - SOLIB_CREATE_INFERIOR_HOOK (pid); -#endif } diff --git a/gnu/usr.bin/gdb/gdb/frame.h b/gnu/usr.bin/gdb/gdb/frame.h index 1fe6fb6a49b3..92b8d2a3878b 100644 --- a/gnu/usr.bin/gdb/gdb/frame.h +++ b/gnu/usr.bin/gdb/gdb/frame.h @@ -217,7 +217,7 @@ extern struct block * block_for_pc PARAMS ((CORE_ADDR)); extern int frameless_look_for_prologue PARAMS ((FRAME)); extern void print_frame_args PARAMS ((struct symbol *, struct frame_info *, - int, FILE *)); + int, GDB_FILE *)); extern FRAME find_relative_frame PARAMS ((FRAME, int*)); @@ -233,6 +233,8 @@ extern CORE_ADDR find_saved_register PARAMS ((FRAME, int)); extern FRAME block_innermost_frame PARAMS ((struct block *)); +extern FRAME find_frame_addr_in_frame_chain PARAMS ((FRAME_ADDR)); + extern CORE_ADDR sigtramp_saved_pc PARAMS ((FRAME)); #endif /* !defined (FRAME_H) */ diff --git a/gnu/usr.bin/gdb/gdb/freebsd-nat.c b/gnu/usr.bin/gdb/gdb/freebsd-nat.c index deb68ebb9453..ba742a359c7e 100644 --- a/gnu/usr.bin/gdb/gdb/freebsd-nat.c +++ b/gnu/usr.bin/gdb/gdb/freebsd-nat.c @@ -15,10 +15,20 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: freebsd-nat.c,v 1.3 1994/05/18 12:43:13 pk Exp $ +*/ + +#include +#include +#include +#include +#include +#include +#include #include "defs.h" -#include /* this table must line up with REGISTER_NAMES in tm-i386.h */ /* symbols like 'tEAX' come from */ @@ -28,14 +38,7 @@ static int tregmap[] = tESP, tEBP, tESI, tEDI, tEIP, tEFLAGS, tCS, tSS }; -#ifdef sEAX -static int sregmap[] = -{ - sEAX, sECX, sEDX, sEBX, - sESP, sEBP, sESI, sEDI, - sEIP, sEFLAGS, sCS, sSS -}; -#endif + /* blockend is the value of u.u_ar0, and points to the place where ES is stored. */ @@ -44,45 +47,14 @@ i386_register_u_addr (blockend, regnum) int blockend; int regnum; { - /* The following condition is a kludge to get at the proper register map - depending upon the state of pcb_flag. - The proper condition would be - if (u.u_pcb.pcb_flag & FM_TRAP) - but that would require a ptrace call here and wouldn't work - for corefiles. */ - -#ifdef sEAX - if (blockend < 0x1fcc) return (blockend + 4 * tregmap[regnum]); - else - return (blockend + 4 * sregmap[regnum]); -#else - return (blockend + 4 * tregmap[regnum]); -#endif } -#ifdef FLOAT_INFO -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#define curpcb Xcurpcb /* XXX avoid leaking declaration from pcb.h */ -#include -#undef curpcb -#include -#include -#include #define fpstate save87 #define U_FPSTATE(u) u.u_pcb.pcb_savefpu +static void i387_to_double (from, to) char *from; char *to; @@ -113,6 +85,7 @@ i387_to_double (from, to) asm ("popl %eax"); /* flush saved copy */ } +static void double_to_i387 (from, to) char *from; char *to; @@ -209,7 +182,7 @@ print_387_status_word (status) printf ("top %d\n", (status >> 11) & 7); } -static +static void print_387_status (status, ep) unsigned short status; struct env387 *ep; @@ -271,6 +244,7 @@ print_387_status (status, ep) } } +void i386_float_info () { struct user u; /* just for address computations */ @@ -320,4 +294,319 @@ i386_float_info () print_387_status (0, (struct env387 *)buf); } +void +clear_regs() +{ + return; +} + +#ifdef KERNEL_DEBUG +#include +#include +#include +#include + +#include +#include + +#include +#include + +#define KERNOFF ((unsigned)KERNBASE) +#define INKERNEL(x) ((x) >= KERNOFF) + +static CORE_ADDR sbr; +static CORE_ADDR curpcb; +static CORE_ADDR kstack; +static int found_pcb; +static int devmem; +static int kfd; +static struct pcb pcb; +int read_pcb (int, CORE_ADDR); +static CORE_ADDR kvtophys (int, CORE_ADDR); +static physrd(int, u_int, char*, int); + +extern CORE_ADDR ksym_lookup(const char *); + +/* substitutes for the stuff in libkvm which doesn't work */ +/* most of this was taken from the old kgdb */ + +/* we don't need all this stuff, but the call should look the same */ +kvm_open (efile, cfile, sfile, perm, errout) +char *efile; +char *cfile; +void *sfile; +int perm; +int errout; +{ + struct stat stb; + CORE_ADDR addr; + int cfd; + + if ((cfd = open(cfile, perm, 0)) < 0) + return (cfd); + + fstat(cfd, &stb); + if ((stb.st_mode & S_IFMT) == S_IFCHR && stb.st_rdev == makedev(2, 0)) { + devmem = 1; + kfd = open ("/dev/kmem", perm, 0); + } + + physrd(cfd, ksym_lookup("IdlePTD") - KERNOFF, (char*)&sbr, sizeof sbr); + printf("IdlePTD %x\n", sbr); + curpcb = ksym_lookup("curpcb") - KERNOFF; + physrd(cfd, curpcb, (char*)&curpcb, sizeof curpcb); + kstack = ksym_lookup("kstack"); + + found_pcb = 1; /* for vtophys */ + if (!devmem) + read_pcb(cfd, ksym_lookup("dumppcb") - KERNOFF); + else + read_pcb(cfd, kvtophys(cfd, kstack)); + + return (cfd); +} + +kvm_close (fd) +{ + return (close (fd)); +} + +kvm_write(core_kd, memaddr, myaddr, len) +CORE_ADDR memaddr; +char *myaddr; +{ + int cc; + + if (devmem) { + if (kfd > 0) { + /* + * Just like kvm_read, only we write. + */ + errno = 0; + if (lseek(kfd, (off_t)memaddr, 0) < 0 && errno != 0) { + error("kvm_write:invalid address (%x)", memaddr); + return (0); + } + cc = write(kfd, myaddr, len); + if (cc < 0) { + error("kvm_write:write failed"); + return (0); + } else if (cc < len) + error("kvm_write:short write"); + return (cc); + } else + return (0); + } else { + printf("kvm_write not implemented for dead kernels\n"); + return (0); + } + /* NOTREACHED */ +} + +kvm_read(core_kd, memaddr, myaddr, len) +CORE_ADDR memaddr; +char *myaddr; +{ + return (kernel_core_file_hook (core_kd, memaddr, myaddr, len)); +} + +kvm_uread(core_kd, p, memaddr, myaddr, len) +register struct proc *p; +CORE_ADDR memaddr; +char *myaddr; +{ + register char *cp; + char procfile[MAXPATHLEN]; + ssize_t amount; + int fd; + + if (devmem) { + cp = myaddr; + + sprintf(procfile, "/proc/%d/mem", p->p_pid); + fd = open(procfile, O_RDONLY, 0); + + if (fd < 0) { + error("cannot open %s", procfile); + close(fd); + return (0); + } + + while (len > 0) { + if (lseek(fd, memaddr, 0) == -1 && errno != 0) { + error("invalid address (%x) in %s", + memaddr, procfile); + break; + } + amount = read(fd, cp, len); + if (amount < 0) { + error("error reading %s", procfile); + break; + } + cp += amount; + memaddr += amount; + len -= amount; + } + + close(fd); + return (ssize_t)(cp - myaddr); + } else { + return (kernel_core_file_hook (core_kd, memaddr, myaddr, len)); + } +} + +static +physrd(cfd, addr, dat, len) +u_int addr; +char *dat; +{ + if (lseek(cfd, (off_t)addr, L_SET) == -1) + return (-1); + return (read(cfd, dat, len)); +} + +static CORE_ADDR +kvtophys (fd, addr) +CORE_ADDR addr; +{ + CORE_ADDR v; + struct pte pte; + static CORE_ADDR PTD = -1; + CORE_ADDR current_ptd; + + /*if (devmem && kfd > 0) + return (addr); + /* + * If we're looking at the kernel stack, + * munge the address to refer to the user space mapping instead; + * that way we get the requested process's kstack, not the running one. + */ + if (addr >= kstack && addr < kstack + ctob(UPAGES)) + addr = (addr - kstack) + curpcb; + + /* + * We may no longer have a linear system page table... + * + * Here's the scoop. IdlePTD contains the physical address + * of a page table directory that always maps the kernel. + * IdlePTD is in memory that is mapped 1-to-1, so we can + * find it easily given its 'virtual' address from ksym_lookup(). + * For hysterical reasons, the value of IdlePTD is stored in sbr. + * + * To look up a kernel address, we first convert it to a 1st-level + * address and look it up in IdlePTD. This gives us the physical + * address of a page table page; we extract the 2nd-level part of + * VA and read the 2nd-level pte. Finally, we add the offset part + * of the VA into the physical address from the pte and return it. + * + * User addresses are a little more complicated. If we don't have + * a current PCB from read_pcb(), we use PTD, which is the (fixed) + * virtual address of the current ptd. Since it's NOT in 1-to-1 + * kernel space, we must look it up using IdlePTD. If we do have + * a pcb, we get the ptd from pcb_ptd. + */ + + if (INKERNEL(addr)) + current_ptd = sbr; + else if (found_pcb == 0) { + if (PTD == -1) + PTD = kvtophys(fd, ksym_lookup("PTD")); + current_ptd = PTD; + } else + current_ptd = pcb.pcb_ptd; + + /* + * Read the first-level page table (ptd). + */ + v = current_ptd + ((unsigned)addr >> PD_SHIFT) * sizeof pte; + if (physrd(fd, v, (char *)&pte, sizeof pte) < 0 || pte.pg_v == 0) + return (~0); + + /* + * Read the second-level page table. + */ + v = i386_ptob(pte.pg_pfnum) + ((addr&PT_MASK) >> PG_SHIFT) * sizeof pte; + if (physrd(fd, v, (char *) &pte, sizeof(pte)) < 0 || pte.pg_v == 0) + return (~0); + + addr = i386_ptob(pte.pg_pfnum) + (addr & PGOFSET); +#if 0 + printf("vtophys(%x) -> %x\n", oldaddr, addr); #endif + return (addr); +} + +read_pcb (fd, uaddr) +CORE_ADDR uaddr; +{ + int i; + int *pcb_regs = (int *)&pcb; + int eip; + + if (physrd(fd, uaddr, (char *)&pcb, sizeof pcb) < 0) { + error("cannot read pcb at %x\n", uaddr); + return (-1); + } + printf("current pcb at %x\n", uaddr); + + /* + * get the register values out of the sys pcb and + * store them where `read_register' will find them. + */ + for (i = 0; i < 8; ++i) + supply_register(i, &pcb_regs[i+10]); + supply_register(8, &pcb_regs[8]); /* eip */ + supply_register(9, &pcb_regs[9]); /* eflags */ + for (i = 10; i < 13; ++i) /* cs, ss, ds */ + supply_register(i, &pcb_regs[i+9]); + supply_register(13, &pcb_regs[18]); /* es */ + for (i = 14; i < 16; ++i) /* fs, gs */ + supply_register(i, &pcb_regs[i+8]); + +#if 0 /* doesn't work ??? */ + /* Hmm... */ + if (target_read_memory(pcb_regs[5+10]+4, &eip, sizeof eip, 0)) + error("Cannot read PC."); + supply_register(8, &eip); /* eip */ +#endif + + /* XXX 80387 registers? */ +} + +/* + * read len bytes from kernel virtual address 'addr' into local + * buffer 'buf'. Return numbert of bytes if read ok, 0 otherwise. On read + * errors, portion of buffer not read is zeroed. + */ +kernel_core_file_hook(fd, addr, buf, len) + CORE_ADDR addr; + char *buf; + int len; +{ + int i; + CORE_ADDR paddr; + register char *cp; + int cc; + + cp = buf; + + while (len > 0) { + paddr = kvtophys(fd, addr); + if (paddr == ~0) { + bzero(buf, len); + break; + } + /* we can't read across a page boundary */ + i = min(len, NBPG - (addr & PGOFSET)); + if ((cc = physrd(fd, paddr, cp, i)) <= 0) { + bzero(cp, len); + return (cp - buf); + } + cp += cc; + addr += cc; + len -= cc; + } + return (cp - buf); +} +#endif /* KERNEL_DEBUG */ diff --git a/gnu/usr.bin/gdb/gdb/gdb.1 b/gnu/usr.bin/gdb/gdb/gdb.1 index ccb216ee88f7..ee14f7073451 100644 --- a/gnu/usr.bin/gdb/gdb/gdb.1 +++ b/gnu/usr.bin/gdb/gdb/gdb.1 @@ -1,6 +1,6 @@ .\" Copyright (c) 1991 Free Software Foundation .\" See section COPYING for conditions for redistribution -.\" $Id: gdb.1,v 1.1.1.1 1993/10/30 21:59:13 jkh Exp $ +.\" $Id: gdb.1,v 1.1 1994/01/28 12:39:43 pk Exp $ .TH gdb 1 "4nov1991" "GNU Tools" "GNU Tools" .SH NAME gdb \- The GNU Debugger diff --git a/gnu/usr.bin/gdb/gdb/gdbcore.h b/gnu/usr.bin/gdb/gdb/gdbcore.h index ec0f1b5a950a..54570a6e763e 100644 --- a/gnu/usr.bin/gdb/gdb/gdbcore.h +++ b/gnu/usr.bin/gdb/gdb/gdbcore.h @@ -64,11 +64,18 @@ read_memory_integer PARAMS ((CORE_ADDR memaddr, int len)); extern unsigned LONGEST read_memory_unsigned_integer PARAMS ((CORE_ADDR memaddr, int len)); -/* If this is prototyped, need to deal with void* vs. char*. */ +/* This takes a char *, not void *. This is probably right, because + passing in an int * or whatever is wrong with respect to + byteswapping, alignment, different sizes for host vs. target types, + etc. */ -extern void -write_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len)); +extern void write_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len)); +extern void generic_search PARAMS ((int len, char *data, char *mask, + CORE_ADDR startaddr, int increment, + CORE_ADDR lorange, CORE_ADDR hirange, + CORE_ADDR *addr_found, char *data_found)); + /* Hook for `exec_file_command' command to call. */ extern void (*exec_file_display_hook) PARAMS ((char *filename)); @@ -113,6 +120,9 @@ extern CORE_ADDR kernel_u_addr; /* The target vector for core files */ extern struct target_ops core_ops; +#ifdef KERNEL_DEBUG +extern struct target_ops kcore_ops; +#endif /* target vector functions called directly from elsewhere */ void diff --git a/gnu/usr.bin/gdb/gdb/gdbtypes.c b/gnu/usr.bin/gdb/gdb/gdbtypes.c index f34646935aa5..b89123738fb8 100644 --- a/gnu/usr.bin/gdb/gdb/gdbtypes.c +++ b/gnu/usr.bin/gdb/gdb/gdbtypes.c @@ -348,6 +348,53 @@ create_range_type (result_type, index_type, low_bound, high_bound) return (result_type); } +/* A lot of code assumes that the "index type" of an array/string/ + set/bitstring is specifically a range type, though in some languages + it can be any discrete type. */ + +struct type * +force_to_range_type (type) + struct type *type; +{ + switch (TYPE_CODE (type)) + { + case TYPE_CODE_RANGE: + return type; + + case TYPE_CODE_ENUM: + { + int low_bound = TYPE_FIELD_BITPOS (type, 0); + int high_bound = TYPE_FIELD_BITPOS (type, TYPE_NFIELDS (type) - 1); + struct type *range_type = + create_range_type (NULL, type, low_bound, high_bound); + TYPE_NAME (range_type) = TYPE_NAME (range_type); + TYPE_DUMMY_RANGE (range_type) = 1; + return range_type; + } + case TYPE_CODE_BOOL: + { + struct type *range_type = create_range_type (NULL, type, 0, 1); + TYPE_NAME (range_type) = TYPE_NAME (range_type); + TYPE_DUMMY_RANGE (range_type) = 1; + return range_type; + } + case TYPE_CODE_CHAR: + { + struct type *range_type = create_range_type (NULL, type, 0, 255); + TYPE_NAME (range_type) = TYPE_NAME (range_type); + TYPE_DUMMY_RANGE (range_type) = 1; + return range_type; + } + default: + { + static struct complaint msg = + { "array index type must be a discrete type", 0, 0}; + complain (&msg); + + return create_range_type (NULL, builtin_type_int, 0, 0); + } + } +} /* Create an array type using either a blank type supplied in RESULT_TYPE, or creating a new type, inheriting the objfile from RANGE_TYPE. @@ -367,23 +414,15 @@ create_array_type (result_type, element_type, range_type) int low_bound; int high_bound; - if (TYPE_CODE (range_type) != TYPE_CODE_RANGE) - { - /* FIXME: We only handle range types at the moment. Complain and - create a dummy range type to use. */ - warning ("internal error: array index type must be a range type"); - range_type = lookup_fundamental_type (TYPE_OBJFILE (range_type), - FT_INTEGER); - range_type = create_range_type ((struct type *) NULL, range_type, 0, 0); - } + range_type = force_to_range_type (range_type); if (result_type == NULL) { result_type = alloc_type (TYPE_OBJFILE (range_type)); } TYPE_CODE (result_type) = TYPE_CODE_ARRAY; TYPE_TARGET_TYPE (result_type) = element_type; - low_bound = TYPE_FIELD_BITPOS (range_type, 0); - high_bound = TYPE_FIELD_BITPOS (range_type, 1); + low_bound = TYPE_LOW_BOUND (range_type); + high_bound = TYPE_HIGH_BOUND (range_type); TYPE_LENGTH (result_type) = TYPE_LENGTH (element_type) * (high_bound - low_bound + 1); TYPE_NFIELDS (result_type) = 1; @@ -417,6 +456,37 @@ create_string_type (result_type, range_type) return (result_type); } +struct type * +create_set_type (result_type, domain_type) + struct type *result_type; + struct type *domain_type; +{ + int low_bound, high_bound, bit_length; + if (result_type == NULL) + { + result_type = alloc_type (TYPE_OBJFILE (domain_type)); + } + domain_type = force_to_range_type (domain_type); + TYPE_CODE (result_type) = TYPE_CODE_SET; + TYPE_NFIELDS (result_type) = 1; + TYPE_FIELDS (result_type) = (struct field *) + TYPE_ALLOC (result_type, 1 * sizeof (struct field)); + memset (TYPE_FIELDS (result_type), 0, sizeof (struct field)); + TYPE_FIELD_TYPE (result_type, 0) = domain_type; + low_bound = TYPE_LOW_BOUND (domain_type); + high_bound = TYPE_HIGH_BOUND (domain_type); + bit_length = high_bound - low_bound + 1; + if (bit_length <= TARGET_CHAR_BIT) + TYPE_LENGTH (result_type) = 1; + else if (bit_length <= TARGET_SHORT_BIT) + TYPE_LENGTH (result_type) = TARGET_SHORT_BIT / TARGET_CHAR_BIT; + else + TYPE_LENGTH (result_type) + = ((bit_length + TARGET_INT_BIT - 1) / TARGET_INT_BIT) + * TARGET_CHAR_BIT; + return (result_type); +} + /* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE. A MEMBER is a wierd thing -- it amounts to a typed offset into a struct, e.g. "an int at offset 8". A MEMBER TYPE doesn't @@ -685,7 +755,7 @@ lookup_struct_elt_type (type, name, noerr) { int i; - if (TYPE_CODE (type) == TYPE_CODE_PTR || + while (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_CODE (type) == TYPE_CODE_REF) type = TYPE_TARGET_TYPE (type); @@ -693,9 +763,9 @@ lookup_struct_elt_type (type, name, noerr) TYPE_CODE (type) != TYPE_CODE_UNION) { target_terminal_ours (); - fflush (stdout); - fprintf (stderr, "Type "); - type_print (type, "", stderr, -1); + gdb_flush (gdb_stdout); + fprintf_unfiltered (gdb_stderr, "Type "); + type_print (type, "", gdb_stderr, -1); error (" is not a structure or union type."); } @@ -743,11 +813,11 @@ lookup_struct_elt_type (type, name, noerr) } target_terminal_ours (); - fflush (stdout); - fprintf (stderr, "Type "); - type_print (type, "", stderr, -1); - fprintf (stderr, " has no component named "); - fputs_filtered (name, stderr); + gdb_flush (gdb_stdout); + fprintf_unfiltered (gdb_stderr, "Type "); + type_print (type, "", gdb_stderr, -1); + fprintf_unfiltered (gdb_stderr, " has no component named "); + fputs_filtered (name, gdb_stderr); error ("."); return (struct type *)-1; /* For lint */ } @@ -790,13 +860,14 @@ fill_in_vptr_fieldno (type) If this is a stubbed struct (i.e. declared as struct foo *), see if we can find a full definition in some other file. If so, copy this - definition, so we can use it in future. If not, set a flag so we - don't waste too much time in future. (FIXME, this doesn't seem - to be happening...) + definition, so we can use it in future. There used to be a comment (but + not any code) that if we don't find a full definition, we'd set a flag + so we don't spend time in the future checking the same type. That would + be a mistake, though--we might load in more symbols which contain a + full definition for the type. This used to be coded as a macro, but I don't think it is called - often enough to merit such treatment. -*/ + often enough to merit such treatment. */ struct complaint stub_noname_complaint = {"stub type has NULL name", 0, 0}; @@ -822,7 +893,31 @@ check_stub_type (type) (struct symtab **) NULL); if (sym) { - memcpy ((char *)type, (char *)SYMBOL_TYPE(sym), sizeof (struct type)); + memcpy ((char *)type, + (char *)SYMBOL_TYPE(sym), + sizeof (struct type)); + } + } + + if (TYPE_FLAGS (type) & TYPE_FLAG_TARGET_STUB) + { + struct type *range_type; + + check_stub_type (TYPE_TARGET_TYPE (type)); + if (!(TYPE_FLAGS (TYPE_TARGET_TYPE (type)) & TYPE_FLAG_STUB) + && TYPE_CODE (type) == TYPE_CODE_ARRAY + && TYPE_NFIELDS (type) == 1 + && (TYPE_CODE (range_type = TYPE_FIELD_TYPE (type, 0)) + == TYPE_CODE_RANGE)) + { + /* Now recompute the length of the array type, based on its + number of elements and the target type's length. */ + TYPE_LENGTH (type) = + ((TYPE_FIELD_BITPOS (range_type, 1) + - TYPE_FIELD_BITPOS (range_type, 0) + + 1) + * TYPE_LENGTH (TYPE_TARGET_TYPE (type))); + TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB; } } } @@ -884,6 +979,7 @@ check_stub_method (type, i, j) argtypes = (struct type **) TYPE_ALLOC (type, (argcount + 2) * sizeof (struct type *)); p = argtypetext; + /* FIXME: This is wrong for static member functions. */ argtypes[0] = lookup_pointer_type (type); argcount = 1; @@ -894,9 +990,13 @@ check_stub_method (type, i, j) { if (depth <= 0 && (*p == ',' || *p == ')')) { - argtypes[argcount] = - parse_and_eval_type (argtypetext, p - argtypetext); - argcount += 1; + /* Avoid parsing of ellipsis, they will be handled below. */ + if (strncmp (argtypetext, "...", p - argtypetext) != 0) + { + argtypes[argcount] = + parse_and_eval_type (argtypetext, p - argtypetext); + argcount += 1; + } argtypetext = p + 1; } @@ -1046,6 +1146,17 @@ lookup_fundamental_type (objfile, typeid) return (*typep); } +int +can_dereference (t) + struct type *t; +{ + /* FIXME: Should we return true for references as well as pointers? */ + return + (t != NULL + && TYPE_CODE (t) == TYPE_CODE_PTR + && TYPE_CODE (TYPE_TARGET_TYPE (t)) != TYPE_CODE_VOID); +} + #if MAINTENANCE_CMDS static void @@ -1105,33 +1216,46 @@ dump_fn_fieldlists (type, spaces) int overload_idx; struct fn_field *f; - printfi_filtered (spaces, "fn_fieldlists 0x%lx\n", - (unsigned long) TYPE_FN_FIELDLISTS (type)); + printfi_filtered (spaces, "fn_fieldlists "); + gdb_print_address (TYPE_FN_FIELDLISTS (type), gdb_stdout); + printf_filtered ("\n"); for (method_idx = 0; method_idx < TYPE_NFN_FIELDS (type); method_idx++) { f = TYPE_FN_FIELDLIST1 (type, method_idx); - printfi_filtered (spaces + 2, "[%d] name '%s' (0x%lx) length %d\n", + printfi_filtered (spaces + 2, "[%d] name '%s' (", method_idx, - TYPE_FN_FIELDLIST_NAME (type, method_idx), - (unsigned long) TYPE_FN_FIELDLIST_NAME (type, method_idx), - TYPE_FN_FIELDLIST_LENGTH (type, method_idx)); + TYPE_FN_FIELDLIST_NAME (type, method_idx)); + gdb_print_address (TYPE_FN_FIELDLIST_NAME (type, method_idx), + gdb_stdout); + printf_filtered (") length %d\n", + TYPE_FN_FIELDLIST_LENGTH (type, method_idx)); for (overload_idx = 0; overload_idx < TYPE_FN_FIELDLIST_LENGTH (type, method_idx); overload_idx++) { - printfi_filtered (spaces + 4, "[%d] physname '%s' (0x%lx)\n", + printfi_filtered (spaces + 4, "[%d] physname '%s' (", overload_idx, - TYPE_FN_FIELD_PHYSNAME (f, overload_idx), - (unsigned long) TYPE_FN_FIELD_PHYSNAME (f, overload_idx)); - printfi_filtered (spaces + 8, "type 0x%lx\n", - (unsigned long) TYPE_FN_FIELD_TYPE (f, overload_idx)); + TYPE_FN_FIELD_PHYSNAME (f, overload_idx)); + gdb_print_address (TYPE_FN_FIELD_PHYSNAME (f, overload_idx), + gdb_stdout); + printf_filtered (")\n"); + printfi_filtered (spaces + 8, "type "); + gdb_print_address (TYPE_FN_FIELD_TYPE (f, overload_idx), gdb_stdout); + printf_filtered ("\n"); + recursive_dump_type (TYPE_FN_FIELD_TYPE (f, overload_idx), spaces + 8 + 2); - printfi_filtered (spaces + 8, "args 0x%lx\n", - (unsigned long) TYPE_FN_FIELD_ARGS (f, overload_idx)); + + printfi_filtered (spaces + 8, "args "); + gdb_print_address (TYPE_FN_FIELD_ARGS (f, overload_idx), gdb_stdout); + printf_filtered ("\n"); + print_arg_types (TYPE_FN_FIELD_ARGS (f, overload_idx), spaces); - printfi_filtered (spaces + 8, "fcontext 0x%lx\n", - (unsigned long) TYPE_FN_FIELD_FCONTEXT (f, overload_idx)); + printfi_filtered (spaces + 8, "fcontext "); + gdb_print_address (TYPE_FN_FIELD_FCONTEXT (f, overload_idx), + gdb_stdout); + printf_filtered ("\n"); + printfi_filtered (spaces + 8, "is_const %d\n", TYPE_FN_FIELD_CONST (f, overload_idx)); printfi_filtered (spaces + 8, "is_volatile %d\n", @@ -1161,9 +1285,11 @@ print_cplus_stuff (type, spaces) TYPE_NFN_FIELDS_TOTAL (type)); if (TYPE_N_BASECLASSES (type) > 0) { - printfi_filtered (spaces, "virtual_field_bits (%d bits at *0x%lx)", - TYPE_N_BASECLASSES (type), - (unsigned long) TYPE_FIELD_VIRTUAL_BITS (type)); + printfi_filtered (spaces, "virtual_field_bits (%d bits at *", + TYPE_N_BASECLASSES (type)); + gdb_print_address (TYPE_FIELD_VIRTUAL_BITS (type), gdb_stdout); + printf_filtered (")"); + print_bit_vector (TYPE_FIELD_VIRTUAL_BITS (type), TYPE_N_BASECLASSES (type)); puts_filtered ("\n"); @@ -1172,18 +1298,20 @@ print_cplus_stuff (type, spaces) { if (TYPE_FIELD_PRIVATE_BITS (type) != NULL) { - printfi_filtered (spaces, "private_field_bits (%d bits at *0x%lx)", - TYPE_NFIELDS (type), - (unsigned long) TYPE_FIELD_PRIVATE_BITS (type)); + printfi_filtered (spaces, "private_field_bits (%d bits at *", + TYPE_NFIELDS (type)); + gdb_print_address (TYPE_FIELD_PRIVATE_BITS (type), gdb_stdout); + printf_filtered (")"); print_bit_vector (TYPE_FIELD_PRIVATE_BITS (type), TYPE_NFIELDS (type)); puts_filtered ("\n"); } if (TYPE_FIELD_PROTECTED_BITS (type) != NULL) { - printfi_filtered (spaces, "protected_field_bits (%d bits at *0x%lx)", - TYPE_NFIELDS (type), - (unsigned long) TYPE_FIELD_PROTECTED_BITS (type)); + printfi_filtered (spaces, "protected_field_bits (%d bits at *", + TYPE_NFIELDS (type)); + gdb_print_address (TYPE_FIELD_PROTECTED_BITS (type), gdb_stdout); + printf_filtered (")"); print_bit_vector (TYPE_FIELD_PROTECTED_BITS (type), TYPE_NFIELDS (type)); puts_filtered ("\n"); @@ -1202,14 +1330,20 @@ recursive_dump_type (type, spaces) { int idx; - printfi_filtered (spaces, "type node 0x%lx\n", (unsigned long)type); - printfi_filtered (spaces, "name '%s' (0x%lx)\n", - TYPE_NAME (type) ? TYPE_NAME (type) : "", - (unsigned long)TYPE_NAME (type)); + printfi_filtered (spaces, "type node "); + gdb_print_address (type, gdb_stdout); + printf_filtered ("\n"); + printfi_filtered (spaces, "name '%s' (", + TYPE_NAME (type) ? TYPE_NAME (type) : ""); + gdb_print_address (TYPE_NAME (type), gdb_stdout); + printf_filtered (")\n"); if (TYPE_TAG_NAME (type) != NULL) - printfi_filtered (spaces, "tagname '%s' (0x%lx)\n", - TYPE_TAG_NAME (type), - (unsigned long)TYPE_TAG_NAME (type)); + { + printfi_filtered (spaces, "tagname '%s' (", + TYPE_TAG_NAME (type)); + gdb_print_address (TYPE_TAG_NAME (type), gdb_stdout); + printf_filtered (")\n"); + } printfi_filtered (spaces, "code 0x%x ", TYPE_CODE (type)); switch (TYPE_CODE (type)) { @@ -1276,54 +1410,59 @@ recursive_dump_type (type, spaces) } puts_filtered ("\n"); printfi_filtered (spaces, "length %d\n", TYPE_LENGTH (type)); - printfi_filtered (spaces, "objfile 0x%lx\n", - (unsigned long) TYPE_OBJFILE (type)); - printfi_filtered (spaces, "target_type 0x%lx\n", - (unsigned long) TYPE_TARGET_TYPE (type)); + printfi_filtered (spaces, "objfile "); + gdb_print_address (TYPE_OBJFILE (type), gdb_stdout); + printf_filtered ("\n"); + printfi_filtered (spaces, "target_type "); + gdb_print_address (TYPE_TARGET_TYPE (type), gdb_stdout); + printf_filtered ("\n"); if (TYPE_TARGET_TYPE (type) != NULL) { recursive_dump_type (TYPE_TARGET_TYPE (type), spaces + 2); } - printfi_filtered (spaces, "pointer_type 0x%lx\n", - (unsigned long) TYPE_POINTER_TYPE (type)); - printfi_filtered (spaces, "reference_type 0x%lx\n", - (unsigned long) TYPE_REFERENCE_TYPE (type)); - printfi_filtered (spaces, "function_type 0x%lx\n", - (unsigned long) TYPE_FUNCTION_TYPE (type)); + printfi_filtered (spaces, "pointer_type "); + gdb_print_address (TYPE_POINTER_TYPE (type), gdb_stdout); + printf_filtered ("\n"); + printfi_filtered (spaces, "reference_type "); + gdb_print_address (TYPE_REFERENCE_TYPE (type), gdb_stdout); + printf_filtered ("\n"); + printfi_filtered (spaces, "function_type "); + gdb_print_address (TYPE_FUNCTION_TYPE (type), gdb_stdout); + printf_filtered ("\n"); printfi_filtered (spaces, "flags 0x%x", TYPE_FLAGS (type)); if (TYPE_FLAGS (type) & TYPE_FLAG_UNSIGNED) { puts_filtered (" TYPE_FLAG_UNSIGNED"); } - if (TYPE_FLAGS (type) & TYPE_FLAG_SIGNED) - { - puts_filtered (" TYPE_FLAG_SIGNED"); - } if (TYPE_FLAGS (type) & TYPE_FLAG_STUB) { puts_filtered (" TYPE_FLAG_STUB"); } puts_filtered ("\n"); - printfi_filtered (spaces, "nfields %d 0x%lx\n", TYPE_NFIELDS (type), - (unsigned long) TYPE_FIELDS (type)); + printfi_filtered (spaces, "nfields %d ", TYPE_NFIELDS (type)); + gdb_print_address (TYPE_FIELDS (type), gdb_stdout); + puts_filtered ("\n"); for (idx = 0; idx < TYPE_NFIELDS (type); idx++) { printfi_filtered (spaces + 2, - "[%d] bitpos %d bitsize %d type 0x%lx name '%s' (0x%lx)\n", + "[%d] bitpos %d bitsize %d type ", idx, TYPE_FIELD_BITPOS (type, idx), - TYPE_FIELD_BITSIZE (type, idx), - (unsigned long) TYPE_FIELD_TYPE (type, idx), - TYPE_FIELD_NAME (type, idx) != NULL - ? TYPE_FIELD_NAME (type, idx) - : "", - (unsigned long) TYPE_FIELD_NAME (type, idx)); + TYPE_FIELD_BITSIZE (type, idx)); + gdb_print_address (TYPE_FIELD_TYPE (type, idx), gdb_stdout); + printf_filtered (" name '%s' (", + TYPE_FIELD_NAME (type, idx) != NULL + ? TYPE_FIELD_NAME (type, idx) + : ""); + gdb_print_address (TYPE_FIELD_NAME (type, idx), gdb_stdout); + printf_filtered (")\n"); if (TYPE_FIELD_TYPE (type, idx) != NULL) { recursive_dump_type (TYPE_FIELD_TYPE (type, idx), spaces + 4); } } - printfi_filtered (spaces, "vptr_basetype 0x%lx\n", - (unsigned long) TYPE_VPTR_BASETYPE (type)); + printfi_filtered (spaces, "vptr_basetype "); + gdb_print_address (TYPE_VPTR_BASETYPE (type), gdb_stdout); + puts_filtered ("\n"); if (TYPE_VPTR_BASETYPE (type) != NULL) { recursive_dump_type (TYPE_VPTR_BASETYPE (type), spaces + 2); @@ -1333,14 +1472,16 @@ recursive_dump_type (type, spaces) { case TYPE_CODE_METHOD: case TYPE_CODE_FUNC: - printfi_filtered (spaces, "arg_types 0x%lx\n", - (unsigned long) TYPE_ARG_TYPES (type)); + printfi_filtered (spaces, "arg_types "); + gdb_print_address (TYPE_ARG_TYPES (type), gdb_stdout); + puts_filtered ("\n"); print_arg_types (TYPE_ARG_TYPES (type), spaces); break; case TYPE_CODE_STRUCT: - printfi_filtered (spaces, "cplus_stuff 0x%lx\n", - (unsigned long) TYPE_CPLUS_SPECIFIC (type)); + printfi_filtered (spaces, "cplus_stuff "); + gdb_print_address (TYPE_CPLUS_SPECIFIC (type), gdb_stdout); + puts_filtered ("\n"); print_cplus_stuff (type, spaces); break; @@ -1348,8 +1489,8 @@ recursive_dump_type (type, spaces) /* We have to pick one of the union types to be able print and test the value. Pick cplus_struct_type, even though we know it isn't any particular one. */ - printfi_filtered (spaces, "type_specific 0x%lx", - (unsigned long) TYPE_CPLUS_SPECIFIC (type)); + printfi_filtered (spaces, "type_specific "); + gdb_print_address (TYPE_CPLUS_SPECIFIC (type), gdb_stdout); if (TYPE_CPLUS_SPECIFIC (type) != NULL) { printf_filtered (" (unknown data form)"); @@ -1375,7 +1516,7 @@ _initialize_gdbtypes () "char", (struct objfile *) NULL); builtin_type_signed_char = init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_SIGNED, + 0, "signed char", (struct objfile *) NULL); builtin_type_unsigned_char = init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, diff --git a/gnu/usr.bin/gdb/gdb/gdbtypes.h b/gnu/usr.bin/gdb/gdb/gdbtypes.h index 89cad6cbbe5d..62fe1ab262ab 100644 --- a/gnu/usr.bin/gdb/gdb/gdbtypes.h +++ b/gnu/usr.bin/gdb/gdb/gdbtypes.h @@ -21,9 +21,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #if !defined (GDBTYPES_H) #define GDBTYPES_H 1 -/* When gdb creates fundamental types, it uses one of the following - type identifiers. The identifiers are used to index a vector of - pointers to any types that are created. */ +/* Codes for `fundamental types'. This is a monstrosity based on the + bogus notion that there are certain compiler-independent + `fundamental types'. None of these is well-defined (how big is + FT_SHORT? Does it depend on the language? How does the + language-specific code know which type to correlate to FT_SHORT?) */ #define FT_VOID 0 #define FT_BOOLEAN 1 @@ -84,13 +86,25 @@ enum type_code of GDB which bogusly assume that TYPE_CODE_FLT can mean complex. */ TYPE_CODE_FLT, - /* Void type (values zero length; the length field is ignored). */ + /* Void type. The length field specifies the length (probably always + one) which is used in pointer arithmetic involving pointers to + this type, but actually dereferencing such a pointer is invalid; + a void type has no length and no actual representation in memory + or registers. A pointer to a void type is a generic pointer. */ TYPE_CODE_VOID, TYPE_CODE_SET, /* Pascal sets */ TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */ - TYPE_CODE_STRING, /* String types, distinct from array of char */ - TYPE_CODE_BITSTRING, /* String of bits, distinct from bool array */ + + /* A string type which is like an array of character but prints + differently (at least for CHILL). It does not contain a length + field as Pascal strings (for many Pascals, anyway) do; if we want + to deal with such strings, we should use a new type code. */ + TYPE_CODE_STRING, + + /* String of bits; like TYPE_CODE_SET but prints differently (at least + for CHILL). */ + TYPE_CODE_BITSTRING, /* Unknown type. The length field is valid if we were able to deduce that much about the type, or 0 if we don't even know that. */ @@ -101,33 +115,40 @@ enum type_code TYPE_CODE_METHOD, /* Method type */ TYPE_CODE_REF, /* C++ Reference types */ - /* Modula-2 */ TYPE_CODE_CHAR, /* *real* character type */ - TYPE_CODE_BOOL /* BOOLEAN type */ + + /* Boolean type. 0 is false, 1 is true, and other values are non-boolean + (e.g. FORTRAN "logical" used as unsigned int). */ + TYPE_CODE_BOOL }; /* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an - alias for TYPE_CODE_STRUCT. Eventually these should probably be - officially distinct types within gdb. */ + alias for TYPE_CODE_STRUCT. This is for DWARF, which has a distinct + "class" attribute. Perhaps we should actually have a separate TYPE_CODE + so that we can print "class" or "struct" depending on what the debug + info said. It's not clear we should bother. */ #define TYPE_CODE_CLASS TYPE_CODE_STRUCT /* Some bits for the type's flags word. */ -/* Explicitly unsigned integer type */ +/* Unsigned integer type. If this is not set for a TYPE_CODE_INT, the + type is signed. */ #define TYPE_FLAG_UNSIGNED (1 << 0) -/* Explicitly signed integer type */ - -#define TYPE_FLAG_SIGNED (1 << 1) - /* This appears in a type's flags word if it is a stub type (e.g., if someone referenced a type that wasn't defined in a source file via (struct sir_not_appearing_in_this_film *)). */ #define TYPE_FLAG_STUB (1 << 2) +/* The target type of this type is a stub type, and this type needs to + be updated if it gets un-stubbed in check_stub_type. Currently only + used for arrays, in which TYPE_LENGTH of the array gets set based + on the TYPE_LENGTH of the target type. */ + +#define TYPE_FLAG_TARGET_STUB (1 << 3) struct type { @@ -347,6 +368,11 @@ struct cplus_struct_type B_TYPE *protected_field_bits; + /* for classes with fields to be ignored, either this is optimized out + or this field has length 0 */ + + B_TYPE *ignore_field_bits; + /* For classes, structures, and unions, a description of each field, which consists of an overloaded name, followed by the types of arguments that the method expects, and then the name after it @@ -389,7 +415,8 @@ struct cplus_struct_type /* The argument list. Only valid if is_stub is clear. Contains the type of each argument, including `this', and ending with - a NULL pointer after the last argument. */ + a NULL pointer after the last argument. Should not contain + a `this' pointer for static member functions. */ struct type **args; @@ -453,6 +480,12 @@ allocate_cplus_struct_type PARAMS ((struct type *)); #define TYPE_NFIELDS(thistype) (thistype)->nfields #define TYPE_FIELDS(thistype) (thistype)->fields +#define TYPE_LOW_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 0) +#define TYPE_HIGH_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 1) +/* If TYPE_DUMMY_RANGE is true for a range type, it was allocated + by force_to_range_type. */ +#define TYPE_DUMMY_RANGE(type) ((type)->vptr_fieldno) + /* C++ */ #define TYPE_VPTR_BASETYPE(thistype) (thistype)->vptr_basetype @@ -484,12 +517,16 @@ allocate_cplus_struct_type PARAMS ((struct type *)); TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits #define TYPE_FIELD_PROTECTED_BITS(thistype) \ TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits +#define TYPE_FIELD_IGNORE_BITS(thistype) \ + TYPE_CPLUS_SPECIFIC(thistype)->ignore_field_bits #define TYPE_FIELD_VIRTUAL_BITS(thistype) \ TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits #define SET_TYPE_FIELD_PRIVATE(thistype, n) \ B_SET (TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits, (n)) #define SET_TYPE_FIELD_PROTECTED(thistype, n) \ B_SET (TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits, (n)) +#define SET_TYPE_FIELD_IGNORE(thistype, n) \ + B_SET (TYPE_CPLUS_SPECIFIC(thistype)->ignore_field_bits, (n)) #define SET_TYPE_FIELD_VIRTUAL(thistype, n) \ B_SET (TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (n)) #define TYPE_FIELD_PRIVATE(thistype, n) \ @@ -498,6 +535,9 @@ allocate_cplus_struct_type PARAMS ((struct type *)); #define TYPE_FIELD_PROTECTED(thistype, n) \ (TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits == NULL ? 0 \ : B_TST(TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits, (n))) +#define TYPE_FIELD_IGNORE(thistype, n) \ + (TYPE_CPLUS_SPECIFIC(thistype)->ignore_field_bits == NULL ? 0 \ + : B_TST(TYPE_CPLUS_SPECIFIC(thistype)->ignore_field_bits, (n))) #define TYPE_FIELD_VIRTUAL(thistype, n) \ B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (n)) @@ -565,20 +605,6 @@ extern struct type *builtin_type_chill_long; extern struct type *builtin_type_chill_ulong; extern struct type *builtin_type_chill_real; -/* CC_HAS_LONG_LONG is defined if the host has "long long". */ - -#ifdef CC_HAS_LONG_LONG - -#define BUILTIN_TYPE_LONGEST builtin_type_long_long -#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long_long - -#else /* not CC_HAS_LONG_LONG. */ - -#define BUILTIN_TYPE_LONGEST builtin_type_long -#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long - -#endif /* not CC_HAS_LONG_LONG. */ - /* Maximum and minimum values of built-in types */ #define MAX_OF_TYPE(t) \ @@ -655,6 +681,9 @@ create_array_type PARAMS ((struct type *, struct type *, struct type *)); extern struct type * create_string_type PARAMS ((struct type *, struct type *)); +extern struct type * +create_set_type PARAMS ((struct type *, struct type *)); + extern struct type * lookup_unsigned_typename PARAMS ((char *)); @@ -695,7 +724,9 @@ extern void recursive_dump_type PARAMS ((struct type *, int)); /* printcmd.c */ extern void -print_scalar_formatted PARAMS ((char *, struct type *, int, int, FILE *)); +print_scalar_formatted PARAMS ((char *, struct type *, int, int, GDB_FILE *)); + +extern int can_dereference PARAMS ((struct type *)); #if MAINTENANCE_CMDS extern void maintenance_print_type PARAMS ((char *, int)); diff --git a/gnu/usr.bin/gdb/gdb/i386-dis.c b/gnu/usr.bin/gdb/gdb/i386-dis.c index 3e4bbb225e63..7f9641dc156d 100644 --- a/gnu/usr.bin/gdb/gdb/i386-dis.c +++ b/gnu/usr.bin/gdb/gdb/i386-dis.c @@ -1,5 +1,5 @@ /* Print i386 instructions for GDB, the GNU debugger. - Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1991, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -33,12 +33,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ */ #include "dis-asm.h" +#include "sysdep.h" #define MAXLEN 20 #include -struct private +struct dis_private { /* Points to first byte not fetched. */ bfd_byte *max_fetched; @@ -51,7 +52,7 @@ struct private to ADDR (exclusive) are valid. Returns 1 for success, longjmps on error. */ #define FETCH_DATA(info, addr) \ - ((addr) <= ((struct private *)(info->private_data))->max_fetched \ + ((addr) <= ((struct dis_private *)(info->private_data))->max_fetched \ ? 1 : fetch_data ((info), (addr))) static int @@ -60,7 +61,7 @@ fetch_data (info, addr) bfd_byte *addr; { int status; - struct private *priv = (struct private *)info->private_data; + struct dis_private *priv = (struct dis_private *)info->private_data; bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); status = (*info->read_memory_func) (start, @@ -415,8 +416,8 @@ struct dis386 dis386[] = { { "stosS", Yv, eAX }, { "lodsb", AL, Xb }, { "lodsS", eAX, Xv }, - { "scasb", AL, Xb }, - { "scasS", eAX, Xv }, + { "scasb", AL, Yb }, + { "scasS", eAX, Yv }, /* b0 */ { "movb", AL, Ib }, { "movb", CL, Ib }, @@ -977,7 +978,7 @@ print_insn_i386 (pc, info) char *first, *second, *third; int needcomma; - struct private priv; + struct dis_private priv; bfd_byte *inbuf = priv.the_buffer; info->private_data = (PTR) &priv; @@ -1045,11 +1046,17 @@ print_insn_i386 (pc, info) else dp = &dis386[*codep]; codep++; + + /* Fetch the mod/reg/rm byte. FIXME: We should be only fetching + this if we need it. As it is, this code loses if there is a + one-byte instruction (without a mod/reg/rm byte) at the end of + the address space. */ + FETCH_DATA (info, codep + 1); mod = (*codep >> 6) & 3; reg = (*codep >> 3) & 7; rm = *codep & 7; - + if (dp->name == NULL && dp->bytemode1 == FLOATCODE) { dofloat (); diff --git a/gnu/usr.bin/gdb/gdb/i386-pinsn.c b/gnu/usr.bin/gdb/gdb/i386-pinsn.c index b6d7fe91e39f..c11ee49a740d 100644 --- a/gnu/usr.bin/gdb/gdb/i386-pinsn.c +++ b/gnu/usr.bin/gdb/gdb/i386-pinsn.c @@ -27,7 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ int print_insn (memaddr, stream) CORE_ADDR memaddr; - FILE *stream; + GDB_FILE *stream; { disassemble_info info; diff --git a/gnu/usr.bin/gdb/gdb/i386-tdep.c b/gnu/usr.bin/gdb/gdb/i386-tdep.c index 3c64d7224cf0..511b432c8969 100644 --- a/gnu/usr.bin/gdb/gdb/i386-tdep.c +++ b/gnu/usr.bin/gdb/gdb/i386-tdep.c @@ -1,5 +1,5 @@ /* Intel 386 target-dependent stuff. - Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1991, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -22,6 +22,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "inferior.h" #include "gdbcore.h" #include "target.h" +#include "floatformat.h" +#include "symtab.h" static long i386_get_frame_setup PARAMS ((int)); @@ -430,7 +432,12 @@ i386_frame_find_saved_regs (fip, fsrp) op = codestream_get (); if (op < 0x50 || op > 0x57) break; +#ifdef I386_REGNO_TO_SYMMETRY + /* Dynix uses different internal numbering. Ick. */ + fsrp->regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = adr; +#else fsrp->regs[op - 0x50] = adr; +#endif adr -= 4; } } @@ -447,6 +454,10 @@ i386_skip_prologue (pc) { unsigned char op; int i; + static unsigned char pic_pat[6] = { 0xe8, 0, 0, 0, 0, /* call 0x0 */ + 0x5b, /* popl %ebx */ + }; + CORE_ADDR pos; if (i386_get_frame_setup (pc) < 0) return (pc); @@ -464,6 +475,54 @@ i386_skip_prologue (pc) break; codestream_get (); } + + /* The native cc on SVR4 in -K PIC mode inserts the following code to get + the address of the global offset table (GOT) into register %ebx. + call 0x0 + popl %ebx + movl %ebx,x(%ebp) (optional) + addl y,%ebx + This code is with the rest of the prologue (at the end of the + function), so we have to skip it to get to the first real + instruction at the start of the function. */ + + pos = codestream_tell (); + for (i = 0; i < 6; i++) + { + op = codestream_get (); + if (pic_pat [i] != op) + break; + } + if (i == 6) + { + unsigned char buf[4]; + long delta = 6; + + op = codestream_get (); + if (op == 0x89) /* movl %ebx, x(%ebp) */ + { + op = codestream_get (); + if (op == 0x5d) /* one byte offset from %ebp */ + { + delta += 3; + codestream_read (buf, 1); + } + else if (op == 0x9d) /* four byte offset from %ebp */ + { + delta += 6; + codestream_read (buf, 4); + } + else /* unexpected instruction */ + delta = -1; + op = codestream_get (); + } + /* addl y,%ebx */ + if (delta > 0 && op == 0x81 && codestream_get () == 0xc3) + { + pos += delta + 6; + } + } + codestream_seek (pos); i386_follow_jump (); @@ -565,27 +624,12 @@ i386_extract_return_value(type, regbuf, valbuf) { if (TYPE_CODE_FLT == TYPE_CODE(type)) { - extern struct ext_format ext_format_i387; double d; /* 387 %st(0), gcc uses this */ - ieee_extended_to_double (&ext_format_i387, - ®buf[REGISTER_BYTE(FP0_REGNUM)], - &d); - switch (TYPE_LENGTH(type)) - { - case 4: /* float */ - { - float f = (float) d; - memcpy (valbuf, &f, 4); - break; - } - case 8: /* double */ - memcpy (valbuf, &d, 8); - break; - default: - error("Unknown floating point size"); - break; - } + floatformat_to_double (&floatformat_i387_ext, + ®buf[REGISTER_BYTE(FP0_REGNUM)], + &d); + store_floating (valbuf, TYPE_LENGTH (type), d); } else { @@ -593,3 +637,32 @@ i386_extract_return_value(type, regbuf, valbuf) } } #endif /* I386_AIX_TARGET */ + +#ifdef I386V4_SIGTRAMP_SAVED_PC +/* Get saved user PC for sigtramp from the pushed ucontext on the stack + for all three variants of SVR4 sigtramps. */ + +CORE_ADDR +i386v4_sigtramp_saved_pc (frame) + FRAME frame; +{ + CORE_ADDR saved_pc_offset = 4; + char *name = NULL; + + find_pc_partial_function (frame->pc, &name, + (CORE_ADDR *)NULL,(CORE_ADDR *)NULL); + if (name) + { + if (STREQ (name, "_sigreturn")) + saved_pc_offset = 132 + 14 * 4; + else if (STREQ (name, "_sigacthandler")) + saved_pc_offset = 80 + 14 * 4; + else if (STREQ (name, "sigvechandler")) + saved_pc_offset = 120 + 14 * 4; + } + + if (frame->next) + return read_memory_integer (frame->next->frame + saved_pc_offset, 4); + return read_memory_integer (read_register (SP_REGNUM) + saved_pc_offset, 4); +} +#endif /* I386V4_SIGTRAMP_SAVED_PC */ diff --git a/gnu/usr.bin/gdb/gdb/infcmd.c b/gnu/usr.bin/gdb/gdb/infcmd.c index 5859ed269f85..c89a159d6e2e 100644 --- a/gnu/usr.bin/gdb/gdb/infcmd.c +++ b/gnu/usr.bin/gdb/gdb/infcmd.c @@ -30,6 +30,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gdbcmd.h" #include "gdbcore.h" #include "target.h" +#include "language.h" static void continue_command PARAMS ((char *, int)); @@ -127,7 +128,7 @@ int inferior_pid; /* Last signal that the inferior received (why it stopped). */ -int stop_signal; +enum target_signal stop_signal; /* Address at which inferior stopped. */ @@ -221,12 +222,22 @@ Start it from the beginning? ")) target_kill (); } + clear_breakpoint_hit_counts (); + exec_file = (char *) get_exec_file (0); /* The exec file is re-read every time we do a generic_mourn_inferior, so we just have to worry about the symbol file. */ reread_symbols (); + /* We keep symbols from add-symbol-file, on the grounds that the + user might want to add some symbols before running the program + (right?). But sometimes (dynamic loading where the user manually + introduces the new symbols with add-symbol-file), the code which + the symbols describe does not persist between runs. Currently + the user has to manually nuke all symbols between runs if they + want them to go away (PR 2207). This is probably reasonable. */ + if (args) { char *cmd; @@ -243,7 +254,7 @@ Start it from the beginning? ")) puts_filtered(" "); puts_filtered(inferior_args); puts_filtered("\n"); - fflush (stdout); + gdb_flush (gdb_stdout); } target_create_inferior (exec_file, inferior_args, @@ -286,7 +297,7 @@ continue_command (proc_count_exp, from_tty) clear_proceed_status (); - proceed ((CORE_ADDR) -1, -1, 0); + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); } /* Step until outside of current statement. */ @@ -373,7 +384,7 @@ step_1 (skip_subroutines, single_inst, count_string) printf_filtered ("\ Single stepping until exit from function %s, \n\ which has no line number information.\n", name); - fflush (stdout); + gdb_flush (gdb_stdout); } } else @@ -391,7 +402,7 @@ which has no line number information.\n", name); step_over_calls = 1; step_multi = (count > 1); - proceed ((CORE_ADDR) -1, -1, 1); + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); if (! stop_step) break; @@ -455,11 +466,14 @@ jump_command (arg, from_tty) addr = sal.pc; if (from_tty) - printf_filtered ("Continuing at %s.\n", - local_hex_string((unsigned long) addr)); + { + printf_filtered ("Continuing at "); + print_address_numeric (addr, 1, gdb_stdout); + printf_filtered (".\n"); + } clear_proceed_status (); - proceed (addr, 0, 0); + proceed (addr, TARGET_SIGNAL_0, 0); } /* Continue program giving it specified signal. */ @@ -469,7 +483,7 @@ signal_command (signum_exp, from_tty) char *signum_exp; int from_tty; { - register int signum; + enum target_signal oursig; dont_repeat (); /* Too dangerous. */ ERROR_NO_INFERIOR; @@ -480,25 +494,36 @@ signal_command (signum_exp, from_tty) /* It would be even slicker to make signal names be valid expressions, (the type could be "enum $signal" or some such), then the user could assign them to convenience variables. */ - signum = strtosigno (signum_exp); + oursig = target_signal_from_name (signum_exp); - if (signum == 0) - /* Not found as a name, try it as an expression. */ - signum = parse_and_eval_address (signum_exp); + if (oursig == TARGET_SIGNAL_UNKNOWN) + { + /* Not found as a name, try it as an expression. */ + /* The numeric signal refers to our own internal signal numbering + from target.h, not to host/target signal number. This is a + feature; users really should be using symbolic names anyway, + and the common ones like SIGHUP, SIGINT, SIGALRM, etc. will + work right anyway. */ + int signum = parse_and_eval_address (signum_exp); + if (signum < 0 + || signum >= (int)TARGET_SIGNAL_LAST + || signum == (int)TARGET_SIGNAL_UNKNOWN + || signum == (int)TARGET_SIGNAL_DEFAULT) + error ("Invalid signal number %d.", signum); + oursig = signum; + } if (from_tty) { - char *signame = strsigno (signum); - printf_filtered ("Continuing with signal "); - if (signame == NULL || signum == 0) - printf_filtered ("%d.\n", signum); + if (oursig == TARGET_SIGNAL_0) + printf_filtered ("Continuing with no signal.\n"); else - /* Do we need to print the number as well as the name? */ - printf_filtered ("%s (%d).\n", signame, signum); + printf_filtered ("Continuing with signal %s.\n", + target_signal_to_name (oursig)); } clear_proceed_status (); - proceed (stop_pc, signum, 0); + proceed (stop_pc, oursig, 0); } /* Call breakpoint_auto_delete on the current contents of the bpstat @@ -552,7 +577,7 @@ run_stack_dummy (addr, buffer) #if CALL_DUMMY_LOCATION != AT_ENTRY_POINT sal.pc = addr - CALL_DUMMY_START_OFFSET + CALL_DUMMY_BREAKPOINT_OFFSET; #else - sal.pc = entry_point_address (); + sal.pc = CALL_DUMMY_ADDRESS (); #endif sal.symtab = NULL; sal.line = 0; @@ -583,7 +608,7 @@ run_stack_dummy (addr, buffer) #endif /* CALL_DUMMY_BREAKPOINT_OFFSET. */ proceed_to_finish = 1; /* We want stop_registers, please... */ - proceed (addr, 0, 0); + proceed (addr, TARGET_SIGNAL_0, 0); discard_cleanups (old_cleanups); @@ -601,8 +626,8 @@ run_stack_dummy (addr, buffer) Note that eventually this command should probably be changed so that only source lines are printed out when we hit the breakpoint - we set. I'm going to postpone this until after a hopeful rewrite - of wait_for_inferior and the proceed status code. -- randy */ + we set. This may involve changes to wait_for_inferior and the + proceed status code. */ /* ARGSUSED */ static void @@ -648,7 +673,7 @@ until_next_command (from_tty) step_multi = 0; /* Only one call to proceed */ - proceed ((CORE_ADDR) -1, -1, 1); + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); } static void @@ -714,14 +739,14 @@ finish_command (arg, from_tty) } proceed_to_finish = 1; /* We want stop_registers, please... */ - proceed ((CORE_ADDR) -1, -1, 0); + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); /* Did we stop at our breakpoint? */ if (bpstat_find_breakpoint(stop_bpstat, breakpoint) != NULL && function != 0) { struct type *value_type; - register value val; + register value_ptr val; CORE_ADDR funcaddr; value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function)); @@ -740,7 +765,7 @@ finish_command (arg, from_tty) BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function)))); printf_filtered ("Value returned is $%d = ", record_latest_value (val)); - value_print (val, stdout, 0, Val_no_prettyprint); + value_print (val, gdb_stdout, 0, Val_no_prettyprint); printf_filtered ("\n"); } do_cleanups(old_chain); @@ -779,21 +804,12 @@ program_info (args, from_tty) num = bpstat_num (&bs); } } - else if (stop_signal) + else if (stop_signal != TARGET_SIGNAL_0) { -#ifdef PRINT_RANDOM_SIGNAL - PRINT_RANDOM_SIGNAL (stop_signal); -#else - char *signame = strsigno (stop_signal); - printf_filtered ("It stopped with signal "); - if (signame == NULL) - printf_filtered ("%d", stop_signal); - else - /* Do we need to print the number as well as the name? */ - printf_filtered ("%s (%d)", signame, stop_signal); - printf_filtered (", %s.\n", safe_strsignal (stop_signal)); -#endif - } + printf_filtered ("It stopped with signal %s, %s.\n", + target_signal_to_name (stop_signal), + target_signal_to_string (stop_signal)); + } if (!from_tty) printf_filtered ("Type \"info stack\" or \"info registers\" for more information.\n"); @@ -946,82 +962,6 @@ path_command (dirname, from_tty) path_info ((char *)NULL, from_tty); } -/* This routine is getting awfully cluttered with #if's. It's probably - time to turn this into READ_PC and define it in the tm.h file. - Ditto for write_pc. */ - -CORE_ADDR -read_pc () -{ -#ifdef TARGET_READ_PC - return TARGET_READ_PC (); -#else - return ADDR_BITS_REMOVE ((CORE_ADDR) read_register (PC_REGNUM)); -#endif -} - -void -write_pc (val) - CORE_ADDR val; -{ -#ifdef TARGET_WRITE_PC - TARGET_WRITE_PC (val); -#else - write_register (PC_REGNUM, (long) val); -#ifdef NPC_REGNUM - write_register (NPC_REGNUM, (long) val + 4); -#ifdef NNPC_REGNUM - write_register (NNPC_REGNUM, (long) val + 8); -#endif -#endif -#endif -} - -/* Cope with strage ways of getting to the stack and frame pointers */ - -CORE_ADDR -read_sp () -{ -#ifdef TARGET_READ_SP - return TARGET_READ_SP (); -#else - return read_register (SP_REGNUM); -#endif -} - -void -write_sp (val) - CORE_ADDR val; -{ -#ifdef TARGET_WRITE_SP - TARGET_WRITE_SP (val); -#else - write_register (SP_REGNUM, val); -#endif -} - - -CORE_ADDR -read_fp () -{ -#ifdef TARGET_READ_FP - return TARGET_READ_FP (); -#else - return read_register (FP_REGNUM); -#endif -} - -void -write_fp (val) - CORE_ADDR val; -{ -#ifdef TARGET_WRITE_FP - TARGET_WRITE_FP (val); -#else - write_register (FP_REGNUM, val); -#endif -} - const char * const reg_names[] = REGISTER_NAMES; /* Print out the machine register regnum. If regnum is -1, @@ -1036,15 +976,18 @@ const char * const reg_names[] = REGISTER_NAMES; to provide that format. */ #if !defined (DO_REGISTERS_INFO) + #define DO_REGISTERS_INFO(regnum, fp) do_registers_info(regnum, fp) + static void do_registers_info (regnum, fpregs) int regnum; int fpregs; { register int i; + int numregs = ARCH_NUM_REGS; - for (i = 0; i < NUM_REGS; i++) + for (i = 0; i < numregs; i++) { char raw_buffer[MAX_REGISTER_RAW_SIZE]; char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; @@ -1058,17 +1001,27 @@ do_registers_info (regnum, fpregs) continue; } - fputs_filtered (reg_names[i], stdout); - print_spaces_filtered (15 - strlen (reg_names[i]), stdout); + fputs_filtered (reg_names[i], gdb_stdout); + print_spaces_filtered (15 - strlen (reg_names[i]), gdb_stdout); - /* Get the data in raw format, then convert also to virtual format. */ + /* Get the data in raw format. */ if (read_relative_register_raw_bytes (i, raw_buffer)) { printf_filtered ("Invalid register contents\n"); continue; } - - REGISTER_CONVERT_TO_VIRTUAL (i, raw_buffer, virtual_buffer); + + /* Convert raw data to virtual format if necessary. */ +#ifdef REGISTER_CONVERTIBLE + if (REGISTER_CONVERTIBLE (i)) + { + REGISTER_CONVERT_TO_VIRTUAL (i, REGISTER_VIRTUAL_TYPE (i), + raw_buffer, virtual_buffer); + } + else +#endif + memcpy (virtual_buffer, raw_buffer, + REGISTER_VIRTUAL_SIZE (i)); /* If virtual format is floating, print it that way, and in raw hex. */ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT @@ -1077,7 +1030,7 @@ do_registers_info (regnum, fpregs) register int j; val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, - stdout, 0, 1, 0, Val_pretty_default); + gdb_stdout, 0, 1, 0, Val_pretty_default); printf_filtered ("\t(raw 0x"); for (j = 0; j < REGISTER_RAW_SIZE (i); j++) @@ -1100,10 +1053,10 @@ do_registers_info (regnum, fpregs) else { val_print (REGISTER_VIRTUAL_TYPE (i), raw_buffer, 0, - stdout, 'x', 1, 0, Val_pretty_default); + gdb_stdout, 'x', 1, 0, Val_pretty_default); printf_filtered ("\t"); val_print (REGISTER_VIRTUAL_TYPE (i), raw_buffer, 0, - stdout, 0, 1, 0, Val_pretty_default); + gdb_stdout, 0, 1, 0, Val_pretty_default); } /* The SPARC wants to print even-numbered float regs as doubles @@ -1122,7 +1075,7 @@ registers_info (addr_exp, fpregs) char *addr_exp; int fpregs; { - int regnum; + int regnum, numregs; register char *end; if (!target_has_registers) @@ -1141,13 +1094,14 @@ registers_info (addr_exp, fpregs) end = addr_exp; while (*end != '\0' && *end != ' ' && *end != '\t') ++end; - for (regnum = 0; regnum < NUM_REGS; regnum++) + numregs = ARCH_NUM_REGS; + for (regnum = 0; regnum < numregs; regnum++) if (!strncmp (addr_exp, reg_names[regnum], end - addr_exp) && strlen (reg_names[regnum]) == end - addr_exp) goto found; if (*addr_exp >= '0' && *addr_exp <= '9') regnum = atoi (addr_exp); /* Take a number */ - if (regnum >= NUM_REGS) /* Bad name, or bad number */ + if (regnum >= numregs) /* Bad name, or bad number */ error ("%.*s: invalid register", end - addr_exp, addr_exp); found: @@ -1221,7 +1175,12 @@ attach_command (args, from_tty) clear_proceed_status (); stop_soon_quietly = 1; +#ifndef MACH + /* Mach 3 does not generate any traps when attaching to inferior, + and to set up frames we can do this. */ + wait_for_inferior (); +#endif #ifdef SOLIB_ADD /* Add shared library symbols from the newly attached process, if any. */ @@ -1248,6 +1207,8 @@ detach_command (args, from_tty) int from_tty; { dont_repeat (); /* Not for the faint of heart */ + if (remove_breakpoints ()) + printf("detach_command: couldn't remove all breakpoints!\n"); target_detach (args, from_tty); } @@ -1271,7 +1232,7 @@ unset_command (args, from_tty) int from_tty; { printf_filtered ("\"unset\" must be followed by the name of an unset subcommand.\n"); - help_list (unsetlist, "unset ", -1, stdout); + help_list (unsetlist, "unset ", -1, gdb_stdout); } void diff --git a/gnu/usr.bin/gdb/gdb/inferior.h b/gnu/usr.bin/gdb/gdb/inferior.h index 0f5499a3c6ba..9754bb4a52dd 100644 --- a/gnu/usr.bin/gdb/gdb/inferior.h +++ b/gnu/usr.bin/gdb/gdb/inferior.h @@ -27,6 +27,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* For FRAME_ADDR. */ #include "frame.h" +/* For enum target_signal. */ +#include "target.h" + /* * Structure in which to save the status of the inferior. Save * through "save_inferior_status", restore through @@ -36,7 +39,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ * control variables. */ struct inferior_status { - int stop_signal; + enum target_signal stop_signal; CORE_ADDR stop_pc; FRAME_ADDR stop_frame_address; bpstat stop_bpstat; @@ -65,12 +68,26 @@ struct inferior_status { int proceed_to_finish; }; +/* This macro gives the number of registers actually in use by the + inferior. This may be less than the total number of registers, + perhaps depending on the actual CPU in use or program being run. */ + +#ifndef ARCH_NUM_REGS +#define ARCH_NUM_REGS NUM_REGS +#endif + extern void save_inferior_status PARAMS ((struct inferior_status *, int)); extern void restore_inferior_status PARAMS ((struct inferior_status *)); +extern void set_sigint_trap PARAMS ((void)); +extern void clear_sigint_trap PARAMS ((void)); + +extern void set_sigio_trap PARAMS ((void)); +extern void clear_sigio_trap PARAMS ((void)); + /* File name for default use for standard in/out in the inferior. */ extern char *inferior_io_terminal; @@ -92,7 +109,7 @@ extern void clear_proceed_status PARAMS ((void)); extern void -proceed PARAMS ((CORE_ADDR, int, int)); +proceed PARAMS ((CORE_ADDR, enum target_signal, int)); extern void kill_inferior PARAMS ((void)); @@ -108,6 +125,9 @@ extern int run_stack_dummy PARAMS ((CORE_ADDR, char [REGISTER_BYTES])); extern CORE_ADDR read_pc PARAMS ((void)); +extern CORE_ADDR +read_pc_pid PARAMS ((int)); + extern void write_pc PARAMS ((CORE_ADDR)); @@ -138,7 +158,7 @@ reopen_exec_file PARAMS ((void)); /* The `resume' routine should only be called in special circumstances. Normally, use `proceed', which handles a lot of bookkeeping. */ extern void -resume PARAMS ((int, int)); +resume PARAMS ((int, enum target_signal)); /* From misc files */ @@ -175,7 +195,7 @@ void detach PARAMS ((int)); extern void -child_resume PARAMS ((int, int, int)); +child_resume PARAMS ((int, int, enum target_signal)); #ifndef PTRACE_ARG3_TYPE #define PTRACE_ARG3_TYPE int /* Correct definition for most systems. */ @@ -191,10 +211,11 @@ proc_iterate_over_mappings PARAMS ((int (*) (int, CORE_ADDR))); /* From fork-child.c */ -extern void -fork_inferior PARAMS ((char *, char *, char **, - void (*) (void), - void (*) (int))); +extern void fork_inferior PARAMS ((char *, char *, char **, + void (*) (void), + void (*) (int), char *)); + +extern void startup_inferior PARAMS ((int)); /* From inflow.c */ @@ -230,7 +251,7 @@ attach_command PARAMS ((char *, int)); /* Last signal that the inferior received (why it stopped). */ -extern int stop_signal; +extern enum target_signal stop_signal; /* Address at which inferior stopped. */ @@ -390,11 +411,9 @@ extern CORE_ADDR text_end; #endif /* On stack. */ #if CALL_DUMMY_LOCATION == AT_ENTRY_POINT -extern CORE_ADDR -entry_point_address PARAMS ((void)); #define PC_IN_CALL_DUMMY(pc, sp, frame_address) \ - ((pc) >= entry_point_address () \ - && (pc) <= (entry_point_address () + DECR_PC_AFTER_BREAK)) + ((pc) >= CALL_DUMMY_ADDRESS () \ + && (pc) <= (CALL_DUMMY_ADDRESS () + DECR_PC_AFTER_BREAK)) #endif /* At entry point. */ #endif /* No PC_IN_CALL_DUMMY. */ diff --git a/gnu/usr.bin/gdb/gdb/inflow.c b/gnu/usr.bin/gdb/gdb/inflow.c index be0b43ba672e..18006abf9cc8 100644 --- a/gnu/usr.bin/gdb/gdb/inflow.c +++ b/gnu/usr.bin/gdb/gdb/inflow.c @@ -25,6 +25,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "serial.h" #include "terminal.h" #include "target.h" +#include "thread.h" #include #include @@ -56,12 +57,6 @@ kill_command PARAMS ((char *, int)); static void terminal_ours_1 PARAMS ((int)); - -/* Nonzero if we are debugging an attached outside process - rather than an inferior. */ - -int attach_flag; - /* Record terminal status separately for debugger and inferior. */ @@ -146,6 +141,9 @@ gdb_has_a_terminal () } return gdb_has_a_terminal_flag == yes; + default: + /* "Can't happen". */ + return 0; } } @@ -153,7 +151,7 @@ gdb_has_a_terminal () #define OOPSY(what) \ if (result == -1) \ - fprintf(stderr, "[%s failed in terminal_inferior: %s]\n", \ + fprintf_unfiltered(gdb_stderr, "[%s failed in terminal_inferior: %s]\n", \ what, strerror (errno)) static void terminal_ours_1 PARAMS ((int)); @@ -172,7 +170,17 @@ terminal_init_inferior () free (inferior_ttystate); inferior_ttystate = SERIAL_GET_TTY_STATE (stdin_serial); #ifdef PROCESS_GROUP_TYPE +#ifdef PIDGET + /* This is for Lynx, and should be cleaned up by having Lynx be + a separate debugging target with a version of + target_terminal_init_inferior which passes in the process + group to a generic routine which does all the work (and the + non-threaded child_terminal_init_inferior can just pass in + inferior_pid to the same routine). */ + inferior_process_group = PIDGET (inferior_pid); +#else inferior_process_group = inferior_pid; +#endif #endif /* Make sure that next time we call terminal_inferior (which will be @@ -310,7 +318,10 @@ terminal_ours_1 (output_only) /* Here we used to set ICANON in our ttystate, but I believe this was an artifact from before when we used readline. Readline sets - the tty state when it needs to. */ + the tty state when it needs to. + FIXME-maybe: However, query() expects non-raw mode and doesn't + use readline. Maybe query should use readline (on the other hand, + this only matters for HAVE_SGTTY, not termio or termios, I think). */ /* Set tty state to our_ttystate. We don't change in our out of raw mode, to avoid flushing input. We need to do the same thing @@ -318,6 +329,7 @@ terminal_ours_1 (output_only) terminal_is_ours and terminal_is_ours_for_output flags. It's OK, though, since readline will deal with raw mode when/if it needs to. */ + SERIAL_NOFLUSH_SET_TTY_STATE (stdin_serial, our_ttystate, inferior_ttystate); @@ -331,7 +343,7 @@ terminal_ours_1 (output_only) used to check for an error here, so perhaps there are other such situations as well. */ if (result == -1) - fprintf (stderr, "[tcsetpgrp failed in terminal_ours: %s]\n", + fprintf_unfiltered (gdb_stderr, "[tcsetpgrp failed in terminal_ours: %s]\n", strerror (errno)); #endif #endif /* termios */ @@ -535,34 +547,11 @@ kill_command (arg, from_tty) if (target_has_stack) { printf_filtered ("In %s,\n", current_target->to_longname); if (selected_frame == NULL) - fputs_filtered ("No selected stack frame.\n", stdout); + fputs_filtered ("No selected stack frame.\n", gdb_stdout); else print_stack_frame (selected_frame, selected_frame_level, 1); } } - -/* The inferior process has died. Long live the inferior! */ - -void -generic_mourn_inferior () -{ - inferior_pid = 0; - attach_flag = 0; - breakpoint_init_inferior (); - registers_changed (); - -#ifdef CLEAR_DEFERRED_STORES - /* Delete any pending stores to the inferior... */ - CLEAR_DEFERRED_STORES; -#endif - - reopen_exec_file (); - reinit_frame_cache (); - - /* It is confusing to the user for ignore counts to stick around - from previous runs of the inferior. So clear them. */ - breakpoint_clear_ignore_counts (); -} /* Call set_sigint_trap when you need to pass a signal on to an attached process when handling SIGINT */ @@ -589,8 +578,67 @@ clear_sigint_trap() signal (SIGINT, osig); } +#if defined (SIGIO) && defined (FASYNC) && defined (FD_SET) && defined (F_SETOWN) +static void (*old_sigio) (); -int job_control; +static void +handle_sigio (signo) + int signo; +{ + int numfds; + fd_set readfds; + + signal (SIGIO, handle_sigio); + + FD_ZERO (&readfds); + FD_SET (target_activity_fd, &readfds); + numfds = select (target_activity_fd + 1, &readfds, NULL, NULL, NULL); + if (numfds >= 0 && FD_ISSET (target_activity_fd, &readfds)) + { + if ((*target_activity_function) ()) + kill (inferior_pid, SIGINT); + } +} + +static int old_fcntl_flags; + +void +set_sigio_trap () +{ + if (target_activity_function) + { + old_sigio = (void (*) ()) signal (SIGIO, handle_sigio); + fcntl (target_activity_fd, F_SETOWN, getpid()); + old_fcntl_flags = fcntl (target_activity_fd, F_GETFL, 0); + fcntl (target_activity_fd, F_SETFL, old_fcntl_flags | FASYNC); + } +} + +void +clear_sigio_trap () +{ + if (target_activity_function) + { + signal (SIGIO, old_sigio); + fcntl (target_activity_fd, F_SETFL, old_fcntl_flags); + } +} +#else /* No SIGIO. */ +void +set_sigio_trap () +{ + if (target_activity_function) + abort (); +} + +void +clear_sigio_trap () +{ + if (target_activity_function) + abort (); +} +#endif /* No SIGIO. */ + /* This is here because this is where we figure out whether we (probably) have job control. Just using job_control only does part of it because @@ -605,6 +653,7 @@ int gdb_setpgid () { int retval = 0; + if (job_control) { #if defined (NEED_POSIX_SETPGID) || defined (HAVE_TERMIOS) diff --git a/gnu/usr.bin/gdb/gdb/infptrace.c b/gnu/usr.bin/gdb/gdb/infptrace.c index a152d673a5df..d648e0a89975 100644 --- a/gnu/usr.bin/gdb/gdb/infptrace.c +++ b/gnu/usr.bin/gdb/gdb/infptrace.c @@ -1,5 +1,6 @@ /* Low level Unix child interface to ptrace, for GDB when running under Unix. - Copyright 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -110,13 +111,18 @@ kill_inferior () if (inferior_pid == 0) return; /* ptrace PT_KILL only works if process is stopped!!! So stop it with - a real signal first, if we can. */ + a real signal first, if we can. FIXME: This is bogus. When the inferior + is not stopped, GDB should just be waiting for it. Either the following + line is unecessary, or there is some problem elsewhere in GDB which + causes us to get here when the inferior is not stopped. */ kill (inferior_pid, SIGKILL); ptrace (PT_KILL, inferior_pid, (PTRACE_ARG3_TYPE) 0, 0); wait ((int *)0); target_mourn_inferior (); } +#ifndef CHILD_RESUME + /* Resume execution of the inferior process. If STEP is nonzero, single-step it. If SIGNAL is nonzero, give it that signal. */ @@ -125,11 +131,14 @@ void child_resume (pid, step, signal) int pid; int step; - int signal; + enum target_signal signal; { errno = 0; if (pid == -1) + /* Resume all threads. */ + /* I think this only gets used in the non-threaded case, where "resume + all threads" and "resume inferior_pid" are the same. */ pid = inferior_pid; /* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where @@ -142,24 +151,55 @@ child_resume (pid, step, signal) instructions), so we don't have to worry about that here. */ if (step) - ptrace (PT_STEP, pid, (PTRACE_ARG3_TYPE) 1, signal); + ptrace (PT_STEP, pid, (PTRACE_ARG3_TYPE) 1, + target_signal_to_host (signal)); else - ptrace (PT_CONTINUE, pid, (PTRACE_ARG3_TYPE) 1, signal); + ptrace (PT_CONTINUE, pid, (PTRACE_ARG3_TYPE) 1, + target_signal_to_host (signal)); if (errno) perror_with_name ("ptrace"); } +#endif /* CHILD_RESUME */ + #ifdef ATTACH_DETACH +#include /* Start debugging the process whose number is PID. */ int attach (pid) int pid; { +#if defined(BSD4_4) && BSD >= 199306 + char procfile[MAXPATHLEN]; + int fd; + + sprintf(procfile, "/proc/%d/ctl", pid); + fd = open(procfile, O_RDWR, 0); + + if (fd < 0) { + perror_with_name ("open"); + } + + /* send attach message to the process */ + if (write (fd, "attach", 7) < 0) { + close(fd); + perror_with_name ("write:attach"); + } + /* wait for the process to stop */ +#if 0 + if (write (fd, "wait", 5) < 0) { + close(fd); + perror_with_name ("write:wait"); + } +#endif + close (fd); +#else errno = 0; ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 0); if (errno) perror_with_name ("ptrace"); +#endif attach_flag = 1; return pid; } @@ -172,10 +212,29 @@ void detach (signal) int signal; { +#if defined(BSD4_4) && BSD >= 199306 + char procfile[MAXPATHLEN]; + int fd; + + sprintf(procfile, "/proc/%d/ctl", inferior_pid); + fd = open(procfile, O_RDWR, 0); + + if (fd < 0) { + perror_with_name ("open"); + } + /* send detach message to the process */ + if (write (fd, "detach", 7) < 0) { + close(fd); + perror_with_name ("write:detach"); + } + /* TODO signals */ + close (fd); +#else errno = 0; ptrace (PT_DETACH, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal); if (errno) perror_with_name ("ptrace"); +#endif attach_flag = 0; } #endif /* ATTACH_DETACH */ @@ -185,17 +244,17 @@ detach (signal) #define PTRACE_XFER_TYPE int #endif -#if !defined (FETCH_INFERIOR_REGISTERS) - /* KERNEL_U_ADDR is the amount to subtract from u.u_ar0 to get the offset in the core file of the register values. */ -#if defined (KERNEL_U_ADDR_BSD) +#if defined (KERNEL_U_ADDR_BSD) && !defined (FETCH_INFERIOR_REGISTERS) /* Get kernel_u_addr using BSD-style nlist(). */ CORE_ADDR kernel_u_addr; +#endif /* KERNEL_U_ADDR_BSD. */ void _initialize_kernel_u_addr () { +#if defined (KERNEL_U_ADDR_BSD) && !defined (FETCH_INFERIOR_REGISTERS) struct nlist names[2]; names[0].n_un.n_name = "_u"; @@ -204,8 +263,10 @@ _initialize_kernel_u_addr () kernel_u_addr = names[0].n_value; else fatal ("Unable to get kernel u area address."); -} #endif /* KERNEL_U_ADDR_BSD. */ +} + +#if !defined (FETCH_INFERIOR_REGISTERS) #if !defined (offsetof) #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER) @@ -230,7 +291,8 @@ static void fetch_register (regno) int regno; { - register unsigned int regaddr; + /* This isn't really an address. But ptrace thinks of it as one. */ + CORE_ADDR regaddr; char buf[MAX_REGISTER_RAW_SIZE]; char mess[128]; /* For messages */ register int i; @@ -270,9 +332,14 @@ void fetch_inferior_registers (regno) int regno; { + int numregs; + if (regno == -1) - for (regno = 0; regno < NUM_REGS; regno++) - fetch_register (regno); + { + numregs = ARCH_NUM_REGS; + for (regno = 0; regno < numregs; regno++) + fetch_register (regno); + } else fetch_register (regno); } @@ -290,9 +357,10 @@ void store_inferior_registers (regno) int regno; { - register unsigned int regaddr; + /* This isn't really an address. But ptrace thinks of it as one. */ + CORE_ADDR regaddr; char buf[80]; - register int i; + register int i, numregs; unsigned int offset = U_REGS_OFFSET; @@ -314,7 +382,8 @@ store_inferior_registers (regno) } else { - for (regno = 0; regno < NUM_REGS; regno++) + numregs = ARCH_NUM_REGS; + for (regno = 0; regno < numregs; regno++) { if (CANNOT_STORE_REGISTER (regno)) continue; @@ -336,6 +405,8 @@ store_inferior_registers (regno) } #endif /* !defined (FETCH_INFERIOR_REGISTERS). */ + +#if !defined (CHILD_XFER_MEMORY) /* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory in the NEW_SUN_PTRACE case. It ought to be straightforward. But it appears that writing did @@ -434,3 +505,4 @@ child_xfer_memory (memaddr, myaddr, len, write, target) } return len; } +#endif /* !defined (CHILD_XFER_MEMORY). */ diff --git a/gnu/usr.bin/gdb/gdb/infrun.c b/gnu/usr.bin/gdb/gdb/infrun.c index 9266c31caf15..4fc8b1f96139 100644 --- a/gnu/usr.bin/gdb/gdb/infrun.c +++ b/gnu/usr.bin/gdb/gdb/infrun.c @@ -1,5 +1,5 @@ /* Target-struct-independent code to start (run) and stop an inferior process. - Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993 + Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -29,6 +29,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gdbcore.h" #include "gdbcmd.h" #include "target.h" +#include "thread.h" +#include "annotate.h" #include @@ -47,8 +49,7 @@ signals_info PARAMS ((char *, int)); static void handle_command PARAMS ((char *, int)); -static void -sig_print_info PARAMS ((int)); +static void sig_print_info PARAMS ((enum target_signal)); static void sig_print_header PARAMS ((void)); @@ -75,7 +76,7 @@ hook_stop_stub PARAMS ((char *)); #endif /* For SVR4 shared libraries, each call goes through a small piece of - trampoline code in the ".init" section. IN_SOLIB_TRAMPOLINE evaluates + trampoline code in the ".plt" section. IN_SOLIB_TRAMPOLINE evaluates to nonzero if we are current stopped in one of these. */ #ifndef IN_SOLIB_TRAMPOLINE #define IN_SOLIB_TRAMPOLINE(pc,name) 0 @@ -194,7 +195,7 @@ resume_cleanups (arg) void resume (step, sig) int step; - int sig; + enum target_signal sig; { struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0); QUIT; @@ -262,7 +263,7 @@ clear_proceed_status () void proceed (addr, siggnal, step) CORE_ADDR addr; - int siggnal; + enum target_signal siggnal; int step; { int oneproc = 0; @@ -280,10 +281,37 @@ proceed (addr, siggnal, step) if (breakpoint_here_p (read_pc ())) oneproc = 1; + +#ifdef STEP_SKIPS_DELAY + /* Check breakpoint_here_p first, because breakpoint_here_p is fast + (it just checks internal GDB data structures) and STEP_SKIPS_DELAY + is slow (it needs to read memory from the target). */ + if (breakpoint_here_p (read_pc () + 4) + && STEP_SKIPS_DELAY (read_pc ())) + oneproc = 1; +#endif /* STEP_SKIPS_DELAY */ } else write_pc (addr); +#ifdef PREPARE_TO_PROCEED + /* In a multi-threaded task we may select another thread and then continue. + + In this case the thread that stopped at a breakpoint will immediately + cause another stop, if it is not stepped over first. On the other hand, + if (ADDR != -1) we only want to single step over the breakpoint if we did + switch to another thread. + + If we are single stepping, don't do any of the above. + (Note that in the current implementation single stepping another + thread after a breakpoint and then continuing will cause the original + breakpoint to be hit again, but you can always continue, so it's not + a big deal.) */ + + if (! step && PREPARE_TO_PROCEED (1) && breakpoint_here_p (read_pc ())) + oneproc = 1; +#endif /* PREPARE_TO_PROCEED */ + if (trap_expected_after_continue) { /* If (step == 0), a trap will be automatically generated after @@ -310,12 +338,14 @@ The same program may be running in another process."); breakpoints_inserted = 1; } - if (siggnal >= 0) + if (siggnal != TARGET_SIGNAL_DEFAULT) stop_signal = siggnal; /* If this signal should not be seen by program, give it zero. Used for debugging signals. */ - else if (stop_signal < NSIG && !signal_program[stop_signal]) - stop_signal= 0; + else if (!signal_program[stop_signal]) + stop_signal = TARGET_SIGNAL_0; + + annotate_starting (); /* Resume inferior. */ resume (oneproc || step || bpstat_should_step (), stop_signal); @@ -335,6 +365,7 @@ static CORE_ADDR prev_pc; static CORE_ADDR prev_sp; static CORE_ADDR prev_func_start; static char *prev_func_name; +static CORE_ADDR prev_frame_address; /* Start remote-debugging of a machine over a serial link. */ @@ -360,11 +391,14 @@ init_wait_for_inferior () prev_sp = 0; prev_func_start = 0; prev_func_name = NULL; + prev_frame_address = 0; trap_expected_after_continue = 0; breakpoints_inserted = 0; breakpoint_init_inferior (); - stop_signal = 0; /* Don't confuse first call to proceed(). */ + + /* Don't confuse first call to proceed(). */ + stop_signal = TARGET_SIGNAL_0; } static void @@ -386,211 +420,243 @@ void wait_for_inferior () { struct cleanup *old_cleanups; - WAITTYPE w; + struct target_waitstatus w; int another_trap; int random_signal; CORE_ADDR stop_sp = 0; CORE_ADDR stop_func_start; + CORE_ADDR stop_func_end; char *stop_func_name; CORE_ADDR prologue_pc = 0, tmp; struct symtab_and_line sal; int remove_breakpoints_on_following_step = 0; int current_line; + struct symtab *current_symtab; int handling_longjmp = 0; /* FIXME */ struct breakpoint *step_resume_breakpoint = NULL; + struct breakpoint *through_sigtramp_breakpoint = NULL; int pid; old_cleanups = make_cleanup (delete_breakpoint_current_contents, &step_resume_breakpoint); + make_cleanup (delete_breakpoint_current_contents, + &through_sigtramp_breakpoint); sal = find_pc_line(prev_pc, 0); current_line = sal.line; + current_symtab = sal.symtab; /* Are we stepping? */ -#define CURRENTLY_STEPPING() ((step_resume_breakpoint == NULL \ - && !handling_longjmp \ - && (step_range_end \ - || trap_expected)) \ - || bpstat_should_step ()) +#define CURRENTLY_STEPPING() \ + ((through_sigtramp_breakpoint == NULL \ + && !handling_longjmp \ + && ((step_range_end && step_resume_breakpoint == NULL) \ + || trap_expected)) \ + || bpstat_should_step ()) while (1) { - /* Clean up saved state that will become invalid. */ - flush_cached_frames (); + /* We have to invalidate the registers BEFORE calling target_wait because + they can be loaded from the target while in target_wait. This makes + remote debugging a bit more efficient for those targets that provide + critical registers as part of their normal status mechanism. */ + registers_changed (); pid = target_wait (-1, &w); -#ifdef SIGTRAP_STOP_AFTER_LOAD + flush_cached_frames (); - /* Somebody called load(2), and it gave us a "trap signal after load". - Ignore it gracefully. */ + /* If it's a new process, add it to the thread database */ - SIGTRAP_STOP_AFTER_LOAD (w); -#endif - - /* See if the process still exists; clean up if it doesn't. */ - if (WIFEXITED (w)) + if (pid != inferior_pid + && !in_thread_list (pid)) { + fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid)); + add_thread (pid); + + /* We may want to consider not doing a resume here in order to give + the user a chance to play with the new thread. It might be good + to make that a user-settable option. */ + + /* At this point, all threads are stopped (happens automatically in + either the OS or the native code). Therefore we need to continue + all threads in order to make progress. */ + + target_resume (-1, 0, TARGET_SIGNAL_0); + continue; + } + + switch (w.kind) + { + case TARGET_WAITKIND_LOADED: + /* Ignore it gracefully. */ + if (breakpoints_inserted) + { + mark_breakpoints_out (); + insert_breakpoints (); + } + resume (0, TARGET_SIGNAL_0); + continue; + + case TARGET_WAITKIND_SPURIOUS: + resume (0, TARGET_SIGNAL_0); + continue; + + case TARGET_WAITKIND_EXITED: target_terminal_ours (); /* Must do this before mourn anyway */ - if (WEXITSTATUS (w)) + annotate_exited (w.value.integer); + if (w.value.integer) printf_filtered ("\nProgram exited with code 0%o.\n", - (unsigned int)WEXITSTATUS (w)); + (unsigned int)w.value.integer); else - if (!batch_mode()) - printf_filtered ("\nProgram exited normally.\n"); - fflush (stdout); + printf_filtered ("\nProgram exited normally.\n"); + gdb_flush (gdb_stdout); target_mourn_inferior (); #ifdef NO_SINGLE_STEP one_stepped = 0; #endif stop_print_frame = 0; - break; - } - else if (!WIFSTOPPED (w)) - { - char *signame; - + goto stop_stepping; + + case TARGET_WAITKIND_SIGNALLED: stop_print_frame = 0; - stop_signal = WTERMSIG (w); + stop_signal = w.value.sig; target_terminal_ours (); /* Must do this before mourn anyway */ + annotate_signalled (); target_kill (); /* kill mourns as well */ -#ifdef PRINT_RANDOM_SIGNAL - printf_filtered ("\nProgram terminated: "); - PRINT_RANDOM_SIGNAL (stop_signal); -#else printf_filtered ("\nProgram terminated with signal "); - signame = strsigno (stop_signal); - if (signame == NULL) - printf_filtered ("%d", stop_signal); - else - /* Do we need to print the number in addition to the name? */ - printf_filtered ("%s (%d)", signame, stop_signal); - printf_filtered (", %s\n", safe_strsignal (stop_signal)); -#endif + annotate_signal_name (); + printf_filtered ("%s", target_signal_to_name (stop_signal)); + annotate_signal_name_end (); + printf_filtered (", "); + annotate_signal_string (); + printf_filtered ("%s", target_signal_to_string (stop_signal)); + annotate_signal_string_end (); + printf_filtered (".\n"); + printf_filtered ("The program no longer exists.\n"); - fflush (stdout); + gdb_flush (gdb_stdout); #ifdef NO_SINGLE_STEP one_stepped = 0; #endif + goto stop_stepping; + + case TARGET_WAITKIND_STOPPED: + /* This is the only case in which we keep going; the above cases + end in a continue or goto. */ break; } - stop_signal = WSTOPSIG (w); + stop_signal = w.value.sig; - if (pid != inferior_pid) + stop_pc = read_pc_pid (pid); + + /* See if a thread hit a thread-specific breakpoint that was meant for + another thread. If so, then step that thread past the breakpoint, + and continue it. */ + + if (stop_signal == TARGET_SIGNAL_TRAP + && breakpoints_inserted + && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK)) { - int save_pid = inferior_pid; + random_signal = 0; + if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid)) + { + /* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */ + write_pc (stop_pc - DECR_PC_AFTER_BREAK); - inferior_pid = pid; /* Setup for target memory/regs */ - registers_changed (); - stop_pc = read_pc (); - inferior_pid = save_pid; - registers_changed (); + remove_breakpoints (); + target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */ + /* FIXME: What if a signal arrives instead of the single-step + happening? */ + target_wait (pid, &w); + insert_breakpoints (); + target_resume (pid, 0, TARGET_SIGNAL_0); + continue; + } } else - stop_pc = read_pc (); + random_signal = 1; - if (stop_signal == SIGTRAP - && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK)) - if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid)) - { - /* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */ - if (breakpoints_inserted) - { - remove_breakpoints (); - target_resume (pid, 1, 0); /* Single step */ - /* FIXME: What if a signal arrives instead of the single-step - happening? */ - target_wait (pid, NULL); - insert_breakpoints (); - } - target_resume (-1, 0, 0); - continue; - } - else - if (pid != inferior_pid) - goto switch_thread; + /* See if something interesting happened to the non-current thread. If + so, then switch to that thread, and eventually give control back to + the user. */ if (pid != inferior_pid) { int printed = 0; - if (!in_thread_list (pid)) - { - fprintf (stderr, "[New %s]\n", target_pid_to_str (pid)); - add_thread (pid); + /* If it's a random signal for a non-current thread, notify user + if he's expressed an interest. */ - target_resume (-1, 0, 0); + if (random_signal + && signal_print[stop_signal]) + { + printed = 1; + target_terminal_ours_for_output (); + printf_filtered ("\nProgram received signal %s, %s.\n", + target_signal_to_name (stop_signal), + target_signal_to_string (stop_signal)); + gdb_flush (gdb_stdout); + } + + /* If it's not SIGTRAP and not a signal we want to stop for, then + continue the thread. */ + + if (stop_signal != TARGET_SIGNAL_TRAP + && !signal_stop[stop_signal]) + { + if (printed) + target_terminal_inferior (); + + /* Clear the signal if it should not be passed. */ + if (signal_program[stop_signal] == 0) + stop_signal = TARGET_SIGNAL_0; + + target_resume (pid, 0, stop_signal); continue; } - else + + /* It's a SIGTRAP or a signal we're interested in. Switch threads, + and fall into the rest of wait_for_inferior(). */ + + inferior_pid = pid; + printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid)); + + flush_cached_frames (); + trap_expected = 0; + if (step_resume_breakpoint) { - if (stop_signal >= NSIG || signal_print[stop_signal]) - { - char *signame; - - printed = 1; - target_terminal_ours_for_output (); - printf_filtered ("\nProgram received signal "); - signame = strsigno (stop_signal); - if (signame == NULL) - printf_filtered ("%d", stop_signal); - else - printf_filtered ("%s (%d)", signame, stop_signal); - printf_filtered (", %s\n", safe_strsignal (stop_signal)); - - fflush (stdout); - } - - if (stop_signal == SIGTRAP - || stop_signal >= NSIG - || signal_stop[stop_signal]) - { -switch_thread: - inferior_pid = pid; - printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid)); - - flush_cached_frames (); - registers_changed (); - trap_expected = 0; - if (step_resume_breakpoint) - { - delete_breakpoint (step_resume_breakpoint); - step_resume_breakpoint = NULL; - } - prev_pc = 0; - prev_sp = 0; - prev_func_name = NULL; - step_range_start = 0; - step_range_end = 0; - step_frame_address = 0; - handling_longjmp = 0; - another_trap = 0; - } - else - { - if (printed) - target_terminal_inferior (); - - /* Clear the signal if it should not be passed. */ - if (signal_program[stop_signal] == 0) - stop_signal = 0; - - target_resume (-1, 0, stop_signal); - continue; - } + delete_breakpoint (step_resume_breakpoint); + step_resume_breakpoint = NULL; } - } -same_pid: + /* Not sure whether we need to blow this away too, + but probably it is like the step-resume + breakpoint. */ + if (through_sigtramp_breakpoint) + { + delete_breakpoint (through_sigtramp_breakpoint); + through_sigtramp_breakpoint = NULL; + } + prev_pc = 0; + prev_sp = 0; + prev_func_name = NULL; + step_range_start = 0; + step_range_end = 0; + step_frame_address = 0; + handling_longjmp = 0; + another_trap = 0; + } #ifdef NO_SINGLE_STEP if (one_stepped) single_step (0); /* This actually cleans up the ss */ #endif /* NO_SINGLE_STEP */ -/* If PC is pointing at a nullified instruction, then step beyond it so that - the user won't be confused when GDB appears to be ready to execute it. */ + /* If PC is pointing at a nullified instruction, then step beyond + it so that the user won't be confused when GDB appears to be ready + to execute it. */ if (INSTRUCTION_NULLIFIED) { @@ -598,7 +664,47 @@ wait_for_inferior () continue; } - set_current_frame ( create_new_frame (read_fp (), stop_pc)); + set_current_frame (create_new_frame (read_fp (), stop_pc)); + select_frame (get_current_frame (), 0); + +#ifdef HAVE_STEPPABLE_WATCHPOINT + /* It may not be necessary to disable the watchpoint to stop over + it. For example, the PA can (with some kernel cooperation) + single step over a watchpoint without disabling the watchpoint. */ + if (STOPPED_BY_WATCHPOINT (w)) + { + resume (1, 0); + continue; + } +#endif + +#ifdef HAVE_NONSTEPPABLE_WATCHPOINT + /* It is far more common to need to disable a watchpoint + to step the inferior over it. FIXME. What else might + a debug register or page protection watchpoint scheme need + here? */ + if (STOPPED_BY_WATCHPOINT (w)) + { + remove_breakpoints (); + resume (1, 0); + + /* FIXME: This is bogus. You can't interact with the + inferior except when it is stopped. It apparently + happens to work on Irix4, but it depends on /proc + allowing us to muck with the memory of a running process, + and the kernel deciding to run one instruction of the + inferior before it executes our insert_breakpoints code, + which seems like an awfully dubious assumption. */ + insert_breakpoints (); + + continue; + } +#endif + +#ifdef HAVE_CONTINUABLE_WATCHPOINT + /* It may be possible to simply continue after a watchpoint. */ + STOPPED_BY_WATCHPOINT (w); +#endif stop_frame_address = FRAME_FP (get_current_frame ()); stop_sp = read_sp (); @@ -607,7 +713,7 @@ wait_for_inferior () /* Don't care about return value; stop_func_start and stop_func_name will both be 0 if it doesn't work. */ find_pc_partial_function (stop_pc, &stop_func_name, &stop_func_start, - NULL); + &stop_func_end); stop_func_start += FUNCTION_START_OFFSET; another_trap = 0; bpstat_clear (&stop_bpstat); @@ -633,16 +739,14 @@ wait_for_inferior () Here we detect when a SIGILL or SIGEMT is really a breakpoint and change it to SIGTRAP. */ - if (stop_signal == SIGTRAP + if (stop_signal == TARGET_SIGNAL_TRAP || (breakpoints_inserted && - (stop_signal == SIGILL -#ifdef SIGEMT - || stop_signal == SIGEMT -#endif + (stop_signal == TARGET_SIGNAL_ILL + || stop_signal == TARGET_SIGNAL_EMT )) || stop_soon_quietly) { - if (stop_signal == SIGTRAP && stop_after_trap) + if (stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap) { stop_print_frame = 0; break; @@ -654,11 +758,11 @@ wait_for_inferior () if just proceeded over a breakpoint. However, if we are trying to proceed over a breakpoint - and end up in sigtramp, then step_resume_breakpoint + and end up in sigtramp, then through_sigtramp_breakpoint will be set and we should check whether we've hit the step breakpoint. */ - if (stop_signal == SIGTRAP && trap_expected - && step_resume_breakpoint == NULL) + if (stop_signal == TARGET_SIGNAL_TRAP && trap_expected + && through_sigtramp_breakpoint == NULL) bpstat_clear (&stop_bpstat); else { @@ -683,7 +787,7 @@ wait_for_inferior () stop_print_frame = 1; } - if (stop_signal == SIGTRAP) + if (stop_signal == TARGET_SIGNAL_TRAP) random_signal = !(bpstat_explains_signal (stop_bpstat) || trap_expected @@ -703,7 +807,7 @@ wait_for_inferior () #endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */ ); if (!random_signal) - stop_signal = SIGTRAP; + stop_signal = TARGET_SIGNAL_TRAP; } } else @@ -719,28 +823,23 @@ wait_for_inferior () stopped_by_random_signal = 1; - if (stop_signal >= NSIG - || signal_print[stop_signal]) + if (signal_print[stop_signal]) { - char *signame; printed = 1; target_terminal_ours_for_output (); -#ifdef PRINT_RANDOM_SIGNAL - PRINT_RANDOM_SIGNAL (stop_signal); -#else + annotate_signal (); printf_filtered ("\nProgram received signal "); - signame = strsigno (stop_signal); - if (signame == NULL) - printf_filtered ("%d", stop_signal); - else - /* Do we need to print the number as well as the name? */ - printf_filtered ("%s (%d)", signame, stop_signal); - printf_filtered (", %s\n", safe_strsignal (stop_signal)); -#endif /* PRINT_RANDOM_SIGNAL */ - fflush (stdout); + annotate_signal_name (); + printf_filtered ("%s", target_signal_to_name (stop_signal)); + annotate_signal_name_end (); + printf_filtered (", "); + annotate_signal_string (); + printf_filtered ("%s", target_signal_to_string (stop_signal)); + annotate_signal_string_end (); + printf_filtered (".\n"); + gdb_flush (gdb_stdout); } - if (stop_signal >= NSIG - || signal_stop[stop_signal]) + if (signal_stop[stop_signal]) break; /* If not going to stop, give terminal back if we took it away. */ @@ -749,7 +848,7 @@ wait_for_inferior () /* Clear the signal if it should not be passed. */ if (signal_program[stop_signal] == 0) - stop_signal = 0; + stop_signal = TARGET_SIGNAL_0; /* I'm not sure whether this needs to be check_sigtramp2 or whether it could/should be keep_going. */ @@ -788,7 +887,13 @@ wait_for_inferior () { delete_breakpoint (step_resume_breakpoint); step_resume_breakpoint = NULL; - what.step_resume = 0; + } + /* Not sure whether we need to blow this away too, but probably + it is like the step-resume breakpoint. */ + if (through_sigtramp_breakpoint != NULL) + { + delete_breakpoint (through_sigtramp_breakpoint); + through_sigtramp_breakpoint = NULL; } #if 0 @@ -833,29 +938,42 @@ wait_for_inferior () case BPSTAT_WHAT_STOP_NOISY: stop_print_frame = 1; - /* We are about to nuke the step_resume_breakpoint via the - cleanup chain, so no need to worry about it here. */ + + /* We are about to nuke the step_resume_breakpoint and + through_sigtramp_breakpoint via the cleanup chain, so + no need to worry about it here. */ + goto stop_stepping; case BPSTAT_WHAT_STOP_SILENT: stop_print_frame = 0; - /* We are about to nuke the step_resume_breakpoint via the - cleanup chain, so no need to worry about it here. */ + + /* We are about to nuke the step_resume_breakpoint and + through_sigtramp_breakpoint via the cleanup chain, so + no need to worry about it here. */ + goto stop_stepping; - case BPSTAT_WHAT_KEEP_CHECKING: - break; - } - - if (what.step_resume) - { + case BPSTAT_WHAT_STEP_RESUME: delete_breakpoint (step_resume_breakpoint); step_resume_breakpoint = NULL; + break; + + case BPSTAT_WHAT_THROUGH_SIGTRAMP: + delete_breakpoint (through_sigtramp_breakpoint); + through_sigtramp_breakpoint = NULL; /* If were waiting for a trap, hitting the step_resume_break doesn't count as getting it. */ if (trap_expected) another_trap = 1; + break; + + case BPSTAT_WHAT_LAST: + /* Not a real code, but listed here to shut up gcc -Wall. */ + + case BPSTAT_WHAT_KEEP_CHECKING: + break; } } @@ -891,10 +1009,8 @@ wait_for_inferior () /* Having a step-resume breakpoint overrides anything else having to do with stepping commands until that breakpoint is reached. */ - /* I suspect this could/should be keep_going, because if the - check_sigtramp2 check succeeds, then it will put in another - step_resume_breakpoint, and we aren't (yet) prepared to nest - them. */ + /* I'm not sure whether this needs to be check_sigtramp2 or + whether it could/should be keep_going. */ goto check_sigtramp2; if (step_range_end == 0) @@ -927,20 +1043,29 @@ wait_for_inferior () if (IN_SIGTRAMP (stop_pc, stop_func_name) && !IN_SIGTRAMP (prev_pc, prev_func_name)) { + /* We've just taken a signal; go until we are back to + the point where we took it and one more. */ + /* This code is needed at least in the following case: The user types "next" and then a signal arrives (before the "next" is done). */ - /* We've just taken a signal; go until we are back to - the point where we took it and one more. */ + + /* Note that if we are stopped at a breakpoint, then we need + the step_resume breakpoint to override any breakpoints at + the same location, so that we will still step over the + breakpoint even though the signal happened. */ + { struct symtab_and_line sr_sal; sr_sal.pc = prev_pc; sr_sal.symtab = NULL; sr_sal.line = 0; + /* We could probably be setting the frame to + prev_frame_address; the reason we don't is that it didn't used + to exist. */ step_resume_breakpoint = - set_momentary_breakpoint (sr_sal, get_current_frame (), - bp_step_resume); + set_momentary_breakpoint (sr_sal, NULL, bp_step_resume); if (breakpoints_inserted) insert_breakpoints (); } @@ -957,12 +1082,19 @@ wait_for_inferior () goto keep_going; } +#if 1 if (stop_func_start) { + struct symtab *s; + /* Do this after the IN_SIGTRAMP check; it might give an error. */ prologue_pc = stop_func_start; - SKIP_PROLOGUE (prologue_pc); + + /* Don't skip the prologue if this is assembly source */ + s = find_pc_symtab (stop_pc); + if (s && s->language != language_asm) + SKIP_PROLOGUE (prologue_pc); } if ((/* Might be a non-recursive call. If the symbols are missing @@ -977,21 +1109,28 @@ wait_for_inferior () || stop_sp != prev_sp) && (/* PC is completely out of bounds of any known objfiles. Treat like a subroutine call. */ - !stop_func_start + ! stop_func_start - /* If we do a call, we will be at the start of a function. */ + /* If we do a call, we will be at the start of a function... */ || stop_pc == stop_func_start -#if 0 - /* Not conservative enough for 4.11. FIXME: enable this - after 4.11. */ - /* Except on the Alpha with -O (and perhaps other machines - with similar calling conventions), in which we might - call the address after the load of gp. Since prologues - don't contain calls, we can't return to within one, and - we don't jump back into them, so this check is OK. */ + /* ...except on the Alpha with -O (and also Irix 5 and + perhaps others), in which we might call the address + after the load of gp. Since prologues don't contain + calls, we can't return to within one, and we don't + jump back into them, so this check is OK. */ + || stop_pc < prologue_pc -#endif + + /* ...and if it is a leaf function, the prologue might + consist of gp loading only, so the call transfers to + the first instruction after the prologue. */ + || (stop_pc == prologue_pc + + /* Distinguish this from the case where we jump back + to the first instruction after the prologue, + within a function. */ + && stop_func_start != prev_func_start) /* If we end up in certain places, it means we did a subroutine call. I'm not completely sure this is necessary now that we @@ -1004,6 +1143,14 @@ wait_for_inferior () which can no longer happen here as long as the handling_longjmp stuff is working. */ )) +#else +/* This is experimental code which greatly simplifies the subroutine call + test. I've actually tested on the Alpha, and it works great. -Stu */ + + if (in_prologue (stop_pc, NULL) + || (prev_func_start != 0 + && stop_func_start == 0)) +#endif { /* It's a subroutine call. */ @@ -1056,6 +1203,7 @@ wait_for_inferior () step_resume_breakpoint = set_momentary_breakpoint (sr_sal, get_current_frame (), bp_step_resume); + step_resume_breakpoint->frame = prev_frame_address; if (breakpoints_inserted) insert_breakpoints (); } @@ -1064,19 +1212,25 @@ wait_for_inferior () step_into_function: /* Subroutine call with source code we should not step over. Do step to the first line of code in it. */ - SKIP_PROLOGUE (stop_func_start); + { + struct symtab *s; + + s = find_pc_symtab (stop_pc); + if (s && s->language != language_asm) + SKIP_PROLOGUE (stop_func_start); + } sal = find_pc_line (stop_func_start, 0); /* Use the step_resume_break to step until the end of the prologue, even if that involves jumps (as it seems to on the vax under 4.2). */ /* If the prologue ends in the middle of a source line, - continue to the end of that source line. - Otherwise, just go to end of prologue. */ + continue to the end of that source line (if it is still + within the function). Otherwise, just go to end of prologue. */ #ifdef PROLOGUE_FIRSTLINE_OVERLAP /* no, don't either. It skips any code that's legitimately on the first line. */ #else - if (sal.end && sal.pc != stop_func_start) + if (sal.end && sal.pc != stop_func_start && sal.end < stop_func_end) stop_func_start = sal.end; #endif @@ -1108,9 +1262,7 @@ wait_for_inferior () goto keep_going; } - /* We've wandered out of the step range (but haven't done a - subroutine call or return). (Is that true? I think we get - here if we did a return and maybe a longjmp). */ + /* We've wandered out of the step range. */ sal = find_pc_line(stop_pc, 0); @@ -1132,7 +1284,8 @@ wait_for_inferior () break; } - if (stop_pc == sal.pc && current_line != sal.line) + if (stop_pc == sal.pc + && (current_line != sal.line || current_symtab != sal.symtab)) { /* We are at the start of a different line. So stop. Note that we don't stop if we step into the middle of a different line. @@ -1148,6 +1301,17 @@ wait_for_inferior () (We might not be in the original line, but if we entered a new line in mid-statement, we continue stepping. This makes things like for(;;) statements work better.) */ + + if (stop_func_end && sal.end >= stop_func_end) + { + /* If this is the last line of the function, don't keep stepping + (it would probably step us out of the function). + This is particularly necessary for a one-line function, + in which after skipping the prologue we better stop even though + we will be in mid-line. */ + stop_step = 1; + break; + } step_range_start = sal.pc; step_range_end = sal.end; goto keep_going; @@ -1172,9 +1336,11 @@ wait_for_inferior () sr_sal.pc = prev_pc; sr_sal.symtab = NULL; sr_sal.line = 0; - step_resume_breakpoint = - set_momentary_breakpoint (sr_sal, get_current_frame (), - bp_step_resume); + /* We perhaps could set the frame if we kept track of what + the frame corresponding to prev_pc was. But we don't, + so don't. */ + through_sigtramp_breakpoint = + set_momentary_breakpoint (sr_sal, NULL, bp_through_sigtramp); if (breakpoints_inserted) insert_breakpoints (); @@ -1194,14 +1360,14 @@ wait_for_inferior () original pc would not have been at the start of a function. */ - prev_func_name = stop_func_name; prev_sp = stop_sp; + prev_frame_address = stop_frame_address; /* If we did not do break;, it means we should keep running the inferior and not return to debugger. */ - if (trap_expected && stop_signal != SIGTRAP) + if (trap_expected && stop_signal != TARGET_SIGNAL_TRAP) { /* We took a signal (which we are supposed to pass through to the inferior, else we'd have done a break above) and we @@ -1223,15 +1389,16 @@ wait_for_inferior () to one-proceed past a breakpoint. */ /* If we've just finished a special step resume and we don't want to hit a breakpoint, pull em out. */ - if (step_resume_breakpoint == NULL && - remove_breakpoints_on_following_step) + if (step_resume_breakpoint == NULL + && through_sigtramp_breakpoint == NULL + && remove_breakpoints_on_following_step) { remove_breakpoints_on_following_step = 0; remove_breakpoints (); breakpoints_inserted = 0; } else if (!breakpoints_inserted && - (step_resume_breakpoint != NULL || !another_trap)) + (through_sigtramp_breakpoint != NULL || !another_trap)) { breakpoints_failed = insert_breakpoints (); if (breakpoints_failed) @@ -1241,8 +1408,8 @@ wait_for_inferior () trap_expected = another_trap; - if (stop_signal == SIGTRAP) - stop_signal = 0; + if (stop_signal == TARGET_SIGNAL_TRAP) + stop_signal = TARGET_SIGNAL_0; #ifdef SHIFT_INST_REGS /* I'm not sure when this following segment applies. I do know, now, @@ -1252,7 +1419,7 @@ wait_for_inferior () (this is only used on the 88k). */ if (!bpstat_explains_signal (stop_bpstat) - && (stop_signal != SIGCLD) + && (stop_signal != TARGET_SIGNAL_CHLD) && !stopped_by_random_signal) SHIFT_INST_REGS(); #endif /* SHIFT_INST_REGS */ @@ -1271,6 +1438,7 @@ wait_for_inferior () prev_func_start = stop_func_start; prev_func_name = stop_func_name; prev_sp = stop_sp; + prev_frame_address = stop_frame_address; } do_cleanups (old_cleanups); } @@ -1323,7 +1491,7 @@ Further execution is probably impossible.\n"); disable_current_display (); if (step_multi && stop_step) - return; + goto done; target_terminal_ours (); @@ -1336,7 +1504,7 @@ Further execution is probably impossible.\n"); } if (!target_has_stack) - return; + goto done; /* Select innermost stack frame except on return from a stack dummy routine, or if the program has exited. Print it without a level number if @@ -1344,8 +1512,6 @@ Further execution is probably impossible.\n"); if we have one. */ if (!stop_stack_dummy) { - select_frame (get_current_frame (), 0); - if (stop_print_frame) { int source_only; @@ -1374,8 +1540,14 @@ Further execution is probably impossible.\n"); POP_FRAME ends with a setting of the current frame, so we can use that next. */ POP_FRAME; + /* Set stop_pc to what it was before we called the function. Can't rely + on restore_inferior_status because that only gets called if we don't + stop in the called function. */ + stop_pc = read_pc(); select_frame (get_current_frame (), 0); } + done: + annotate_stopped (); } static int @@ -1389,41 +1561,40 @@ hook_stop_stub (cmd) int signal_stop_state (signo) int signo; { - return ((signo >= 0 && signo < NSIG) ? signal_stop[signo] : 0); + return signal_stop[signo]; } int signal_print_state (signo) int signo; { - return ((signo >= 0 && signo < NSIG) ? signal_print[signo] : 0); + return signal_print[signo]; } int signal_pass_state (signo) int signo; { - return ((signo >= 0 && signo < NSIG) ? signal_program[signo] : 0); + return signal_program[signo]; } static void sig_print_header () { - printf_filtered ("Signal\t\tStop\tPrint\tPass to program\tDescription\n"); + printf_filtered ("\ +Signal Stop\tPrint\tPass to program\tDescription\n"); } static void -sig_print_info (number) - int number; +sig_print_info (oursig) + enum target_signal oursig; { - char *name; - - if ((name = strsigno (number)) == NULL) - printf_filtered ("%d\t\t", number); - else - printf_filtered ("%s (%d)\t", name, number); - printf_filtered ("%s\t", signal_stop[number] ? "Yes" : "No"); - printf_filtered ("%s\t", signal_print[number] ? "Yes" : "No"); - printf_filtered ("%s\t\t", signal_program[number] ? "Yes" : "No"); - printf_filtered ("%s\n", safe_strsignal (number)); + char *name = target_signal_to_name (oursig); + printf_filtered ("%s", name); + printf_filtered ("%*.*s ", 13 - strlen (name), 13 - strlen (name), + " "); + printf_filtered ("%s\t", signal_stop[oursig] ? "Yes" : "No"); + printf_filtered ("%s\t", signal_print[oursig] ? "Yes" : "No"); + printf_filtered ("%s\t\t", signal_program[oursig] ? "Yes" : "No"); + printf_filtered ("%s\n", target_signal_to_string (oursig)); } /* Specify how various signals in the inferior should be handled. */ @@ -1436,6 +1607,7 @@ handle_command (args, from_tty) char **argv; int digits, wordlen; int sigfirst, signum, siglast; + enum target_signal oursig; int allsigs; int nsigs; unsigned char *sigs; @@ -1448,7 +1620,7 @@ handle_command (args, from_tty) /* Allocate and zero an array of flags for which signals to handle. */ - nsigs = signo_max () + 1; + nsigs = (int)TARGET_SIGNAL_LAST; sigs = (unsigned char *) alloca (nsigs); memset (sigs, 0, nsigs); @@ -1461,7 +1633,7 @@ handle_command (args, from_tty) } old_chain = make_cleanup (freeargv, (char *) argv); - /* Walk through the args, looking for signal numbers, signal names, and + /* Walk through the args, looking for signal oursigs, signal names, and actions. Signal numbers and signal names may be interspersed with actions, with the actions being performed for all signals cumulatively specified. Signal ranges can be specified as -. */ @@ -1517,6 +1689,12 @@ handle_command (args, from_tty) } else if (digits > 0) { + /* It is numeric. The numeric signal refers to our own internal + signal numbering from target.h, not to host/target signal number. + This is a feature; users really should be using symbolic names + anyway, and the common ones like SIGHUP, SIGINT, SIGALRM, etc. + will work right anyway. */ + sigfirst = siglast = atoi (*argv); if ((*argv)[digits] == '-') { @@ -1538,14 +1716,18 @@ handle_command (args, from_tty) error ("Signal %d not in range 0-%d", siglast, nsigs - 1); } } - else if ((signum = strtosigno (*argv)) != 0) - { - sigfirst = siglast = signum; - } else { - /* Not a number and not a recognized flag word => complain. */ - error ("Unrecognized or ambiguous flag word: \"%s\".", *argv); + oursig = target_signal_from_name (*argv); + if (oursig != TARGET_SIGNAL_UNKNOWN) + { + sigfirst = siglast = (int)oursig; + } + else + { + /* Not a number and not a recognized flag word => complain. */ + error ("Unrecognized or ambiguous flag word: \"%s\".", *argv); + } } /* If any signal numbers or symbol names were found, set flags for @@ -1553,20 +1735,23 @@ handle_command (args, from_tty) for (signum = sigfirst; signum >= 0 && signum <= siglast; signum++) { - switch (signum) + switch ((enum target_signal)signum) { - case SIGTRAP: - case SIGINT: + case TARGET_SIGNAL_TRAP: + case TARGET_SIGNAL_INT: if (!allsigs && !sigs[signum]) { - if (query ("%s is used by the debugger.\nAre you sure you want to change it? ", strsigno (signum))) + if (query ("%s is used by the debugger.\n\ +Are you sure you want to change it? ", + target_signal_to_name + ((enum target_signal)signum))) { sigs[signum] = 1; } else { - printf ("Not confirmed, unchanged.\n"); - fflush (stdout); + printf_unfiltered ("Not confirmed, unchanged.\n"); + gdb_flush (gdb_stdout); } } break; @@ -1597,38 +1782,56 @@ handle_command (args, from_tty) do_cleanups (old_chain); } -/* Print current contents of the tables set by the handle command. */ +/* Print current contents of the tables set by the handle command. + It is possible we should just be printing signals actually used + by the current target (but for things to work right when switching + targets, all signals should be in the signal tables). */ static void signals_info (signum_exp, from_tty) char *signum_exp; int from_tty; { - register int i; + enum target_signal oursig; sig_print_header (); if (signum_exp) { /* First see if this is a symbol name. */ - i = strtosigno (signum_exp); - if (i == 0) + oursig = target_signal_from_name (signum_exp); + if (oursig == TARGET_SIGNAL_UNKNOWN) { /* Nope, maybe it's an address which evaluates to a signal number. */ - i = parse_and_eval_address (signum_exp); - if (i >= NSIG || i < 0) + /* The numeric signal refers to our own internal + signal numbering from target.h, not to host/target signal number. + This is a feature; users really should be using symbolic names + anyway, and the common ones like SIGHUP, SIGINT, SIGALRM, etc. + will work right anyway. */ + int i = parse_and_eval_address (signum_exp); + if (i >= (int)TARGET_SIGNAL_LAST + || i < 0 + || i == (int)TARGET_SIGNAL_UNKNOWN + || i == (int)TARGET_SIGNAL_DEFAULT) error ("Signal number out of bounds."); + oursig = (enum target_signal)i; } - sig_print_info (i); + sig_print_info (oursig); return; } printf_filtered ("\n"); - for (i = 0; i < NSIG; i++) + /* These ugly casts brought to you by the native VAX compiler. */ + for (oursig = TARGET_SIGNAL_FIRST; + (int)oursig < (int)TARGET_SIGNAL_LAST; + oursig = (enum target_signal)((int)oursig + 1)) { QUIT; - sig_print_info (i); + if (oursig != TARGET_SIGNAL_UNKNOWN + && oursig != TARGET_SIGNAL_DEFAULT + && oursig != TARGET_SIGNAL_0) + sig_print_info (oursig); } printf_filtered ("\nUse the \"handle\" command to change these tables.\n"); @@ -1797,13 +2000,13 @@ Pass and Stop may be combined."); This allows you to set a list of commands to be run each time execution\n\ of the program stops.", &cmdlist); - numsigs = signo_max () + 1; - signal_stop = (unsigned char *) - xmalloc (sizeof (signal_stop[0]) * numsigs); - signal_print = (unsigned char *) - xmalloc (sizeof (signal_print[0]) * numsigs); + numsigs = (int)TARGET_SIGNAL_LAST; + signal_stop = (unsigned char *) + xmalloc (sizeof (signal_stop[0]) * numsigs); + signal_print = (unsigned char *) + xmalloc (sizeof (signal_print[0]) * numsigs); signal_program = (unsigned char *) - xmalloc (sizeof (signal_program[0]) * numsigs); + xmalloc (sizeof (signal_program[0]) * numsigs); for (i = 0; i < numsigs; i++) { signal_stop[i] = 1; @@ -1813,36 +2016,22 @@ of the program stops.", &cmdlist); /* Signals caused by debugger's own actions should not be given to the program afterwards. */ - signal_program[SIGTRAP] = 0; - signal_program[SIGINT] = 0; + signal_program[TARGET_SIGNAL_TRAP] = 0; + signal_program[TARGET_SIGNAL_INT] = 0; /* Signals that are not errors should not normally enter the debugger. */ -#ifdef SIGALRM - signal_stop[SIGALRM] = 0; - signal_print[SIGALRM] = 0; -#endif /* SIGALRM */ -#ifdef SIGVTALRM - signal_stop[SIGVTALRM] = 0; - signal_print[SIGVTALRM] = 0; -#endif /* SIGVTALRM */ -#ifdef SIGPROF - signal_stop[SIGPROF] = 0; - signal_print[SIGPROF] = 0; -#endif /* SIGPROF */ -#ifdef SIGCHLD - signal_stop[SIGCHLD] = 0; - signal_print[SIGCHLD] = 0; -#endif /* SIGCHLD */ -#ifdef SIGCLD - signal_stop[SIGCLD] = 0; - signal_print[SIGCLD] = 0; -#endif /* SIGCLD */ -#ifdef SIGIO - signal_stop[SIGIO] = 0; - signal_print[SIGIO] = 0; -#endif /* SIGIO */ -#ifdef SIGURG - signal_stop[SIGURG] = 0; - signal_print[SIGURG] = 0; -#endif /* SIGURG */ + signal_stop[TARGET_SIGNAL_ALRM] = 0; + signal_print[TARGET_SIGNAL_ALRM] = 0; + signal_stop[TARGET_SIGNAL_VTALRM] = 0; + signal_print[TARGET_SIGNAL_VTALRM] = 0; + signal_stop[TARGET_SIGNAL_PROF] = 0; + signal_print[TARGET_SIGNAL_PROF] = 0; + signal_stop[TARGET_SIGNAL_CHLD] = 0; + signal_print[TARGET_SIGNAL_CHLD] = 0; + signal_stop[TARGET_SIGNAL_IO] = 0; + signal_print[TARGET_SIGNAL_IO] = 0; + signal_stop[TARGET_SIGNAL_POLL] = 0; + signal_print[TARGET_SIGNAL_POLL] = 0; + signal_stop[TARGET_SIGNAL_URG] = 0; + signal_print[TARGET_SIGNAL_URG] = 0; } diff --git a/gnu/usr.bin/gdb/gdb/inftarg.c b/gnu/usr.bin/gdb/gdb/inftarg.c index f937be4ea6e1..6515c262453a 100644 --- a/gnu/usr.bin/gdb/gdb/inftarg.c +++ b/gnu/usr.bin/gdb/gdb/inftarg.c @@ -24,19 +24,17 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "target.h" #include "wait.h" #include "gdbcore.h" - +#include "command.h" #include static void child_prepare_to_store PARAMS ((void)); #ifndef CHILD_WAIT -static int -child_wait PARAMS ((int, int *)); +static int child_wait PARAMS ((int, struct target_waitstatus *)); #endif /* CHILD_WAIT */ -static void -child_open PARAMS ((char *, int)); +static void child_open PARAMS ((char *, int)); static void child_files_info PARAMS ((struct target_ops *)); @@ -53,8 +51,7 @@ ptrace_me PARAMS ((void)); static void ptrace_him PARAMS ((int)); -static void -child_create_inferior PARAMS ((char *, char *, char **)); +static void child_create_inferior PARAMS ((char *, char *, char **)); static void child_mourn_inferior PARAMS ((void)); @@ -70,22 +67,27 @@ extern struct target_ops child_ops; #ifndef CHILD_WAIT /* Wait for child to do something. Return pid of child, or -1 in case - of error; store status through argument pointer STATUS. */ + of error; store status through argument pointer OURSTATUS. */ static int -child_wait (pid, status) +child_wait (pid, ourstatus) int pid; - int *status; + struct target_waitstatus *ourstatus; { int save_errno; + int status; do { if (attach_flag) set_sigint_trap(); /* Causes SIGINT to be passed on to the attached process. */ - pid = wait (status); + set_sigio_trap (); + + pid = proc_wait (inferior_pid, &status); save_errno = errno; + clear_sigio_trap (); + if (attach_flag) clear_sigint_trap(); @@ -93,12 +95,15 @@ child_wait (pid, status) { if (save_errno == EINTR) continue; - fprintf (stderr, "Child process unexpectedly missing: %s.\n", + fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n", safe_strerror (save_errno)); - *status = 42; /* Claim it exited with signal 42 */ + /* Claim it exited with unknown signal. */ + ourstatus->kind = TARGET_WAITKIND_SIGNALLED; + ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; return -1; } } while (pid != inferior_pid); /* Some other child died or stopped */ + store_waitstatus (ourstatus, status); return pid; } #endif /* CHILD_WAIT */ @@ -110,35 +115,38 @@ child_attach (args, from_tty) char *args; int from_tty; { - char *exec_file; - int pid; - if (!args) error_no_arg ("process-id to attach"); #ifndef ATTACH_DETACH error ("Can't attach to a process on this machine."); #else - pid = atoi (args); + { + char *exec_file; + int pid; - if (pid == getpid()) /* Trying to masturbate? */ - error ("I refuse to debug myself!"); + pid = atoi (args); - if (from_tty) - { - exec_file = (char *) get_exec_file (0); + if (pid == getpid()) /* Trying to masturbate? */ + error ("I refuse to debug myself!"); - if (exec_file) - printf ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid)); - else - printf ("Attaching to %s\n", target_pid_to_str (pid)); + if (from_tty) + { + exec_file = (char *) get_exec_file (0); - fflush (stdout); - } + if (exec_file) + printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, + target_pid_to_str (pid)); + else + printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid)); - attach (pid); - inferior_pid = pid; - push_target (&child_ops); + gdb_flush (gdb_stdout); + } + + attach (pid); + inferior_pid = pid; + push_target (&child_ops); + } #endif /* ATTACH_DETACH */ } @@ -156,26 +164,28 @@ child_detach (args, from_tty) char *args; int from_tty; { - int siggnal = 0; - #ifdef ATTACH_DETACH - if (from_tty) - { - char *exec_file = get_exec_file (0); - if (exec_file == 0) - exec_file = ""; - printf ("Detaching from program: %s %s\n", exec_file, - target_pid_to_str (inferior_pid)); - fflush (stdout); - } - if (args) - siggnal = atoi (args); - - detach (siggnal); - inferior_pid = 0; - unpush_target (&child_ops); /* Pop out of handling an inferior */ + { + int siggnal = 0; + + if (from_tty) + { + char *exec_file = get_exec_file (0); + if (exec_file == 0) + exec_file = ""; + printf_unfiltered ("Detaching from program: %s %s\n", exec_file, + target_pid_to_str (inferior_pid)); + gdb_flush (gdb_stdout); + } + if (args) + siggnal = atoi (args); + + detach (siggnal); + inferior_pid = 0; + unpush_target (&child_ops); + } #else - error ("This version of Unix does not support detaching a process."); + error ("This version of Unix does not support detaching a process."); #endif } @@ -199,7 +209,7 @@ static void child_files_info (ignore) struct target_ops *ignore; { - printf ("\tUsing the running image of %s %s.\n", + printf_unfiltered ("\tUsing the running image of %s %s.\n", attach_flag? "attached": "child", target_pid_to_str (inferior_pid)); } @@ -230,6 +240,13 @@ ptrace_him (pid) int pid; { push_target (&child_ops); + +#ifdef START_INFERIOR_TRAPS_EXPECTED + startup_inferior (START_INFERIOR_TRAPS_EXPECTED); +#else + /* One trap to exec the shell, one to exec the program being debugged. */ + startup_inferior (2); +#endif } /* Start an inferior Unix child process and sets inferior_pid to its pid. @@ -243,16 +260,17 @@ child_create_inferior (exec_file, allargs, env) char *allargs; char **env; { - fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him); + fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him, NULL); /* We are at the first instruction we care about. */ /* Pedal to the metal... */ - proceed ((CORE_ADDR) -1, 0, 0); + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0); } static void child_mourn_inferior () { unpush_target (&child_ops); + proc_remove_foreign (inferior_pid); generic_mourn_inferior (); } diff --git a/gnu/usr.bin/gdb/gdb/init.c b/gnu/usr.bin/gdb/gdb/init.c index 26afe1d761eb..7606e3cf21ab 100644 --- a/gnu/usr.bin/gdb/gdb/init.c +++ b/gnu/usr.bin/gdb/gdb/init.c @@ -1,47 +1,54 @@ -/* Do not modify this file. It is created automatically by "munch". */ +#include "defs.h" /* for KERNEL_DEBUG */ +/* Do not modify this file. */ +/* It is created automatically by the Makefile. */ void initialize_all_files () { {extern void _initialize_blockframe (); _initialize_blockframe ();} {extern void _initialize_breakpoint (); _initialize_breakpoint ();} - {extern void _initialize_buildsym (); _initialize_buildsym ();} - {extern void _initialize_c_language (); _initialize_c_language ();} - {extern void _initialize_chill_language (); _initialize_chill_language ();} - {extern void _initialize_coffread (); _initialize_coffread ();} - {extern void _initialize_command (); _initialize_command ();} - {extern void _initialize_complaints (); _initialize_complaints ();} - {extern void _initialize_copying (); _initialize_copying ();} - {extern void _initialize_core (); _initialize_core ();} - {extern void _initialize_corelow (); _initialize_corelow ();} - {extern void _initialize_cp_valprint (); _initialize_cp_valprint ();} - {extern void _initialize_dbxread (); _initialize_dbxread ();} - {extern void _initialize_demangler (); _initialize_demangler ();} - {extern void _initialize_elfread (); _initialize_elfread ();} - {extern void _initialize_exec (); _initialize_exec ();} - {extern void _initialize_gdbtypes (); _initialize_gdbtypes ();} - {extern void _initialize_infcmd (); _initialize_infcmd ();} - {extern void _initialize_inflow (); _initialize_inflow ();} - {extern void _initialize_infrun (); _initialize_infrun ();} - {extern void _initialize_inftarg (); _initialize_inftarg ();} - {extern void _initialize_language (); _initialize_language ();} - {extern void _initialize_m2_language (); _initialize_m2_language ();} - {extern void _initialize_maint_cmds (); _initialize_maint_cmds ();} - {extern void _initialize_mipsread (); _initialize_mipsread ();} - {extern void _initialize_nlmread (); _initialize_nlmread ();} - {extern void _initialize_parse (); _initialize_parse ();} - {extern void _initialize_printcmd (); _initialize_printcmd ();} - {extern void _initialize_remote (); _initialize_remote ();} - {extern void _initialize_ser_hardwire (); _initialize_ser_hardwire ();} - {extern void _initialize_solib (); _initialize_solib ();} - {extern void _initialize_source (); _initialize_source ();} - {extern void _initialize_sr_support (); _initialize_sr_support ();} - {extern void _initialize_stabsread (); _initialize_stabsread ();} {extern void _initialize_stack (); _initialize_stack ();} + {extern void _initialize_thread (); _initialize_thread ();} + {extern void _initialize_source (); _initialize_source ();} + {extern void _initialize_values (); _initialize_values ();} + {extern void _initialize_valarith (); _initialize_valarith ();} + {extern void _initialize_valprint (); _initialize_valprint ();} + {extern void _initialize_printcmd (); _initialize_printcmd ();} + {extern void _initialize_symtab (); _initialize_symtab ();} {extern void _initialize_symfile (); _initialize_symfile ();} {extern void _initialize_symmisc (); _initialize_symmisc ();} - {extern void _initialize_symtab (); _initialize_symtab ();} + {extern void _initialize_infcmd (); _initialize_infcmd ();} + {extern void _initialize_infrun (); _initialize_infrun ();} + {extern void _initialize_command (); _initialize_command ();} + {extern void _initialize_gdbtypes (); _initialize_gdbtypes ();} + {extern void _initialize_copying (); _initialize_copying ();} + {extern void _initialize_solib (); _initialize_solib ();} + {extern void _initialize_ser_hardwire (); _initialize_ser_hardwire ();} + {extern void _initialize_exec (); _initialize_exec ();} + {extern void _initialize_kernel_u_addr (); _initialize_kernel_u_addr ();} + {extern void _initialize_inftarg (); _initialize_inftarg ();} + {extern void _initialize_corelow (); _initialize_corelow ();} +#ifdef KERNEL_DEBUG + {extern void _initialize_kcorelow (); _initialize_kcorelow ();} +#endif + {extern void _initialize_remote (); _initialize_remote ();} + {extern void _initialize_sr_support (); _initialize_sr_support ();} {extern void _initialize_targets (); _initialize_targets ();} - {extern void _initialize_thread (); _initialize_thread ();} + {extern void _initialize_parse (); _initialize_parse ();} + {extern void _initialize_language (); _initialize_language ();} + {extern void _initialize_buildsym (); _initialize_buildsym ();} + {extern void _initialize_maint_cmds (); _initialize_maint_cmds ();} + {extern void _initialize_demangler (); _initialize_demangler ();} + {extern void _initialize_dbxread (); _initialize_dbxread ();} + {extern void _initialize_coffread (); _initialize_coffread ();} + {extern void _initialize_elfread (); _initialize_elfread ();} + {extern void _initialize_stabsread (); _initialize_stabsread ();} + {extern void _initialize_core (); _initialize_core ();} + {extern void _initialize_c_language (); _initialize_c_language ();} + {extern void _initialize_chill_language (); _initialize_chill_language ();} + {extern void _initialize_m2_language (); _initialize_m2_language ();} + {extern void _initialize_complaints (); _initialize_complaints ();} {extern void _initialize_typeprint (); _initialize_typeprint ();} + {extern void _initialize_cp_valprint (); _initialize_cp_valprint ();} + {extern void _initialize_serial (); _initialize_serial ();} + {extern void _initialize_mdebugread (); _initialize_mdebugread ();} {extern void _initialize_utils (); _initialize_utils ();} - {extern void _initialize_valprint (); _initialize_valprint ();} - {extern void _initialize_values (); _initialize_values ();} + {extern void _initialize_inflow (); _initialize_inflow ();} } diff --git a/gnu/usr.bin/gdb/gdb/language.c b/gnu/usr.bin/gdb/gdb/language.c index be519532caf3..4a3b6a0ee6ae 100644 --- a/gnu/usr.bin/gdb/gdb/language.c +++ b/gnu/usr.bin/gdb/gdb/language.c @@ -161,12 +161,12 @@ set_language_command (ignore, from_tty) /* FIXME -- do this from the list, with HELP. */ if (!language || !language[0]) { - printf("The currently understood settings are:\n\n"); - printf ("local or auto Automatic setting based on source file\n"); - printf ("c Use the C language\n"); - printf ("c++ Use the C++ language\n"); - printf ("chill Use the Chill language\n"); - printf ("modula-2 Use the Modula-2 language\n"); + printf_unfiltered("The currently understood settings are:\n\n"); + printf_unfiltered ("local or auto Automatic setting based on source file\n"); + printf_unfiltered ("c Use the C language\n"); + printf_unfiltered ("c++ Use the C++ language\n"); + printf_unfiltered ("chill Use the Chill language\n"); + printf_unfiltered ("modula-2 Use the Modula-2 language\n"); /* Restore the silly string. */ set_language(current_language->la_language); return; @@ -212,7 +212,7 @@ show_type_command(ignore, from_tty) int from_tty; { if (type_check != current_language->la_type_check) - printf( + printf_unfiltered( "Warning: the current type check setting does not match the language.\n"); } @@ -258,7 +258,7 @@ show_range_command(ignore, from_tty) { if (range_check != current_language->la_range_check) - printf( + printf_unfiltered( "Warning: the current range check setting does not match the language.\n"); } @@ -411,14 +411,14 @@ language_info (quietly) return; expected_language = current_language; - printf("Current language: %s\n",language); + printf_unfiltered("Current language: %s\n",language); show_language_command((char *)0, 1); if (!quietly) { - printf("Type checking: %s\n",type); + printf_unfiltered("Type checking: %s\n",type); show_type_command((char *)0, 1); - printf("Range checking: %s\n",range); + printf_unfiltered("Range checking: %s\n",range); show_range_command((char *)0, 1); } } @@ -428,8 +428,8 @@ language_info (quietly) #if 0 /* Currently unused */ struct type * -binop_result_type(v1,v2) - value v1,v2; +binop_result_type (v1, v2) + value_ptr v1, v2; { int l1,l2,size,uns; @@ -698,18 +698,20 @@ int boolean_type (type) struct type *type; { - switch(current_language->la_language) - { - case language_chill: - case language_m2: - return TYPE_CODE(type) != TYPE_CODE_BOOL ? 0 : 1; - - case language_c: - case language_cplus: - return TYPE_CODE(type) != TYPE_CODE_INT ? 0 : 1; + if (TYPE_CODE (type) == TYPE_CODE_BOOL) + return 1; + switch(current_language->la_language) + { + case language_c: + case language_cplus: + /* Might be more cleanly handled by having a TYPE_CODE_INT_NOT_BOOL + for CHILL and such languages, or a TYPE_CODE_INT_OR_BOOL for C. */ + if (TYPE_CODE (type) == TYPE_CODE_INT) + return 1; default: - return (0); + break; } + return 0; } /* Returns non-zero if the value is a floating-point type */ @@ -757,46 +759,16 @@ structured_type(type) /* Returns non-zero if the value VAL represents a true value. */ int -value_true(val) - value val; +value_true (val) + value_ptr val; { - int len, i; - struct type *type; - LONGEST v; - - switch (current_language->la_language) { - - case language_c: - case language_cplus: - return !value_logical_not (val); - - case language_m2: - type = VALUE_TYPE(val); - if (TYPE_CODE (type) != TYPE_CODE_BOOL) - return 0; /* Not a BOOLEAN at all */ - /* Search the fields for one that matches the current value. */ - len = TYPE_NFIELDS (type); - v = value_as_long (val); - for (i = 0; i < len; i++) - { - QUIT; - if (v == TYPE_FIELD_BITPOS (type, i)) - break; - } - if (i >= len) - return 0; /* Not a valid BOOLEAN value */ - if (STREQ ("TRUE", TYPE_FIELD_NAME(VALUE_TYPE(val), i))) - return 1; /* BOOLEAN with value TRUE */ - else - return 0; /* BOOLEAN with value FALSE */ - break; - - case language_chill: - error ("Missing Chill support in function value_type."); /*FIXME*/ - - default: - error ("Language not supported."); - } + /* It is possible that we should have some sort of error if a non-boolean + value is used in this context. Possibly dependent on some kind of + "boolean-checking" option like range checking. But it should probably + not depend on the language except insofar as is necessary to identify + a "boolean" value (i.e. in C using a float, pointer, etc., as a boolean + should be an error, probably). */ + return !value_logical_not (val); } /* Returns non-zero if the operator OP is defined on @@ -806,7 +778,7 @@ value_true(val) void binop_type_check(arg1,arg2,op) - value arg1,arg2; + value_ptr arg1,arg2; int op; { struct type *t1, *t2; @@ -816,7 +788,7 @@ binop_type_check(arg1,arg2,op) return; t1=VALUE_TYPE(arg1); - if (arg2!=(value)NULL) + if (arg2 != NULL) t2=VALUE_TYPE(arg2); else t2=NULL; @@ -1011,18 +983,18 @@ type_error (va_alist) va_list args; char *string; - if (type_check==type_check_warn) - fprintf(stderr,warning_pre_print); + if (type_check == type_check_warn) + fprintf_filtered (gdb_stderr, warning_pre_print); else - target_terminal_ours(); + error_begin (); va_start (args); string = va_arg (args, char *); - vfprintf (stderr, string, args); - fprintf (stderr, "\n"); + vfprintf_filtered (gdb_stderr, string, args); + fprintf_filtered (gdb_stderr, "\n"); va_end (args); - if (type_check==type_check_on) - return_to_top_level (RETURN_ERROR); + if (type_check == type_check_on) + return_to_top_level (RETURN_ERROR); } void @@ -1032,18 +1004,18 @@ range_error (va_alist) va_list args; char *string; - if (range_check==range_check_warn) - fprintf(stderr,warning_pre_print); + if (range_check == range_check_warn) + fprintf_filtered (gdb_stderr, warning_pre_print); else - target_terminal_ours(); + error_begin (); va_start (args); string = va_arg (args, char *); - vfprintf (stderr, string, args); - fprintf (stderr, "\n"); + vfprintf_filtered (gdb_stderr, string, args); + fprintf_filtered (gdb_stderr, "\n"); va_end (args); - if (range_check==range_check_on) - return_to_top_level (RETURN_ERROR); + if (range_check == range_check_on) + return_to_top_level (RETURN_ERROR); } @@ -1085,9 +1057,9 @@ set_check (ignore, from_tty) char *ignore; int from_tty; { - printf( + printf_unfiltered( "\"set check\" must be followed by the name of a check subcommand.\n"); - help_list(setchecklist, "set check ", -1, stdout); + help_list(setchecklist, "set check ", -1, gdb_stdout); } static void @@ -1106,7 +1078,7 @@ add_language (lang) { if (lang->la_magic != LANG_MAGIC) { - fprintf(stderr, "Magic number of %s language struct wrong\n", + fprintf_unfiltered(gdb_stderr, "Magic number of %s language struct wrong\n", lang->la_name); abort(); } @@ -1144,14 +1116,14 @@ unk_lang_error (msg) static void unk_lang_printchar (c, stream) register int c; - FILE *stream; + GDB_FILE *stream; { error ("internal error - unimplemented function unk_lang_printchar called."); } static void unk_lang_printstr (stream, string, length, force_ellipses) - FILE *stream; + GDB_FILE *stream; char *string; unsigned int length; int force_ellipses; @@ -1171,7 +1143,7 @@ void unk_lang_print_type (type, varstring, stream, show, level) struct type *type; char *varstring; - FILE *stream; + GDB_FILE *stream; int show; int level; { @@ -1184,7 +1156,7 @@ unk_lang_val_print (type, valaddr, address, stream, format, deref_ref, struct type *type; char *valaddr; CORE_ADDR address; - FILE *stream; + GDB_FILE *stream; int format; int deref_ref; int recurse; @@ -1193,6 +1165,16 @@ unk_lang_val_print (type, valaddr, address, stream, format, deref_ref, error ("internal error - unimplemented function unk_lang_val_print called."); } +int +unk_lang_value_print (val, stream, format, pretty) + value_ptr val; + GDB_FILE *stream; + int format; + enum val_prettyprint pretty; +{ + error ("internal error - unimplemented function unk_lang_value_print called."); +} + static struct type ** const (unknown_builtin_types[]) = { 0 }; static const struct op_print unk_op_print_tab[] = { {NULL, OP_NULL, PREC_NULL, 0} @@ -1211,8 +1193,7 @@ const struct language_defn unknown_language_defn = { unk_lang_create_fundamental_type, unk_lang_print_type, /* Print a type using appropriate syntax */ unk_lang_val_print, /* Print a value using appropriate syntax */ - &builtin_type_error, /* longest signed integral type */ - &builtin_type_error, /* longest unsigned integral type */ + unk_lang_value_print, /* Print a top-level value */ &builtin_type_error, /* longest floating point type */ {"", "", "", ""}, /* Binary format info */ {"0%lo", "0", "o", ""}, /* Octal format info */ @@ -1236,8 +1217,7 @@ const struct language_defn auto_language_defn = { unk_lang_create_fundamental_type, unk_lang_print_type, /* Print a type using appropriate syntax */ unk_lang_val_print, /* Print a value using appropriate syntax */ - &builtin_type_error, /* longest signed integral type */ - &builtin_type_error, /* longest unsigned integral type */ + unk_lang_value_print, /* Print a top-level value */ &builtin_type_error, /* longest floating point type */ {"", "", "", ""}, /* Binary format info */ {"0%lo", "0", "o", ""}, /* Octal format info */ @@ -1260,8 +1240,7 @@ const struct language_defn local_language_defn = { unk_lang_create_fundamental_type, unk_lang_print_type, /* Print a type using appropriate syntax */ unk_lang_val_print, /* Print a value using appropriate syntax */ - &builtin_type_error, /* longest signed integral type */ - &builtin_type_error, /* longest unsigned integral type */ + unk_lang_value_print, /* Print a top-level value */ &builtin_type_error, /* longest floating point type */ {"", "", "", ""}, /* Binary format info */ {"0%lo", "0", "o", ""}, /* Octal format info */ diff --git a/gnu/usr.bin/gdb/gdb/language.h b/gnu/usr.bin/gdb/gdb/language.h index 9df5345c9301..a4ec6fb52347 100644 --- a/gnu/usr.bin/gdb/gdb/language.h +++ b/gnu/usr.bin/gdb/gdb/language.h @@ -106,7 +106,10 @@ struct language_defn enum language la_language; - /* Its builtin types */ + /* Its builtin types. This is a vector ended by a NULL pointer. These + types can be specified by name in parsing types in expressions, + regardless of whether the program being debugged actually defines + such a type. */ struct type ** const *la_builtin_type_vector; @@ -126,28 +129,25 @@ struct language_defn void (*la_error) PARAMS ((char *)); - void (*la_printchar) PARAMS ((int, FILE *)); + void (*la_printchar) PARAMS ((int, GDB_FILE *)); - void (*la_printstr) PARAMS ((FILE *, char *, unsigned int, int)); + void (*la_printstr) PARAMS ((GDB_FILE *, char *, unsigned int, int)); struct type *(*la_fund_type) PARAMS ((struct objfile *, int)); /* Print a type using syntax appropriate for this language. */ - void (*la_print_type) PARAMS ((struct type *, char *, FILE *, int, int)); + void (*la_print_type) PARAMS ((struct type *, char *, GDB_FILE *, int, int)); /* Print a value using syntax appropriate for this language. */ - int (*la_val_print) PARAMS ((struct type *, char *, CORE_ADDR, FILE *, + int (*la_val_print) PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); - /* Longest signed integral type */ + /* Print a top-level value using syntax appropriate for this language. */ - struct type **la_longest_int; - - /* Longest unsigned integral type */ - - struct type **la_longest_unsigned_int; + int (*la_value_print) PARAMS ((struct value *, GDB_FILE *, + int, enum val_prettyprint)); /* Longest floating point type */ @@ -241,8 +241,6 @@ set_language PARAMS ((enum language)); with the "set language" command. */ /* Returns some built-in types */ -#define longest_int() (*current_language->la_longest_int) -#define longest_unsigned_int() (*current_language->la_longest_unsigned_int) #define longest_float() (*current_language->la_longest_float) #define create_fundamental_type(objfile,typeid) \ @@ -254,6 +252,8 @@ set_language PARAMS ((enum language)); #define LA_VAL_PRINT(type,valaddr,addr,stream,fmt,deref,recurse,pretty) \ (current_language->la_val_print(type,valaddr,addr,stream,fmt,deref, \ recurse,pretty)) +#define LA_VALUE_PRINT(val,stream,fmt,pretty) \ + (current_language->la_value_print(val,stream,fmt,pretty)) /* Return a format string for printf that will print a number in one of the local (language-specific) formats. Result is static and is diff --git a/gnu/usr.bin/gdb/gdb/m2-lang.c b/gnu/usr.bin/gdb/gdb/m2-lang.c index 0b678fd9c3c1..c12b7ddf5d6c 100644 --- a/gnu/usr.bin/gdb/gdb/m2-lang.c +++ b/gnu/usr.bin/gdb/gdb/m2-lang.c @@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "parser-defs.h" #include "language.h" #include "m2-lang.h" +#include "c-lang.h" /* Print the character C on STREAM as part of the contents of a literal string whose delimiter is QUOTER. Note that that format for printing @@ -35,7 +36,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ static void emit_char (c, stream, quoter) register int c; - FILE *stream; + GDB_FILE *stream; int quoter; { @@ -87,7 +88,7 @@ emit_char (c, stream, quoter) static void m2_printchar (c, stream) int c; - FILE *stream; + GDB_FILE *stream; { fputs_filtered ("'", stream); emit_char (c, stream, '\''); @@ -103,7 +104,7 @@ m2_printchar (c, stream) static void m2_printstr (stream, string, length, force_ellipses) - FILE *stream; + GDB_FILE *stream; char *string; unsigned int length; int force_ellipses; @@ -118,7 +119,7 @@ m2_printstr (stream, string, length, force_ellipses) if (length == 0) { - fputs_filtered ("\"\"", stdout); + fputs_filtered ("\"\"", gdb_stdout); return; } @@ -236,7 +237,7 @@ m2_create_fundamental_type (objfile, typeid) case FT_SIGNED_CHAR: type = init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_SIGNED, "signed char", objfile); + 0, "signed char", objfile); break; case FT_UNSIGNED_CHAR: type = init_type (TYPE_CODE_INT, @@ -251,7 +252,7 @@ m2_create_fundamental_type (objfile, typeid) case FT_SIGNED_SHORT: type = init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_SIGNED, "short", objfile); /* FIXME-fnf */ + 0, "short", objfile); /* FIXME-fnf */ break; case FT_UNSIGNED_SHORT: type = init_type (TYPE_CODE_INT, @@ -266,7 +267,7 @@ m2_create_fundamental_type (objfile, typeid) case FT_SIGNED_INTEGER: type = init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_SIGNED, "int", objfile); /* FIXME -fnf */ + 0, "int", objfile); /* FIXME -fnf */ break; case FT_UNSIGNED_INTEGER: type = init_type (TYPE_CODE_INT, @@ -286,7 +287,7 @@ m2_create_fundamental_type (objfile, typeid) case FT_SIGNED_LONG: type = init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_SIGNED, "long", objfile); /* FIXME -fnf */ + 0, "long", objfile); /* FIXME -fnf */ break; case FT_UNSIGNED_LONG: type = init_type (TYPE_CODE_INT, @@ -301,7 +302,7 @@ m2_create_fundamental_type (objfile, typeid) case FT_SIGNED_LONG_LONG: type = init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_SIGNED, "signed long long", objfile); + 0, "signed long long", objfile); break; case FT_UNSIGNED_LONG_LONG: type = init_type (TYPE_CODE_INT, @@ -405,8 +406,7 @@ const struct language_defn m2_language_defn = { m2_create_fundamental_type, /* Create fundamental type in this language */ m2_print_type, /* Print a type using appropriate syntax */ m2_val_print, /* Print a value using appropriate syntax */ - &builtin_type_m2_int, /* longest signed integral type */ - &builtin_type_m2_card, /* longest unsigned integral type */ + c_value_print, /* Print a top-level value */ &builtin_type_m2_real, /* longest floating point type */ {"", "", "", ""}, /* Binary format info */ {"%loB", "", "o", "B"}, /* Octal format info */ @@ -443,15 +443,5 @@ _initialize_m2_language () TYPE_FLAG_UNSIGNED, "BOOLEAN", (struct objfile *) NULL); - TYPE_NFIELDS(builtin_type_m2_bool) = 2; - TYPE_FIELDS(builtin_type_m2_bool) = - (struct field *) xmalloc (sizeof (struct field) * 2); - TYPE_FIELD_BITPOS(builtin_type_m2_bool,0) = 0; - TYPE_FIELD_NAME(builtin_type_m2_bool,0) = (char *)xmalloc(6); - strcpy(TYPE_FIELD_NAME(builtin_type_m2_bool,0),"FALSE"); - TYPE_FIELD_BITPOS(builtin_type_m2_bool,1) = 1; - TYPE_FIELD_NAME(builtin_type_m2_bool,1) = (char *)xmalloc(5); - strcpy(TYPE_FIELD_NAME(builtin_type_m2_bool,1),"TRUE"); - add_language (&m2_language_defn); } diff --git a/gnu/usr.bin/gdb/gdb/m2-lang.h b/gnu/usr.bin/gdb/gdb/m2-lang.h index 4bc57f5c2943..38f46879f629 100644 --- a/gnu/usr.bin/gdb/gdb/m2-lang.h +++ b/gnu/usr.bin/gdb/gdb/m2-lang.h @@ -24,8 +24,8 @@ extern void m2_error PARAMS ((char *)); /* Defined in m2-exp.y */ extern void /* Defined in m2-typeprint.c */ -m2_print_type PARAMS ((struct type *, char *, FILE *, int, int)); +m2_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int)); extern int -m2_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int, +m2_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); diff --git a/gnu/usr.bin/gdb/gdb/m2-typeprint.c b/gnu/usr.bin/gdb/gdb/m2-typeprint.c index ef66a80a8b90..c9ee800f3180 100644 --- a/gnu/usr.bin/gdb/gdb/m2-typeprint.c +++ b/gnu/usr.bin/gdb/gdb/m2-typeprint.c @@ -39,11 +39,11 @@ void m2_print_type (type, varstring, stream, show, level) struct type *type; char *varstring; - FILE *stream; + GDB_FILE *stream; int show; int level; { - extern void c_print_type PARAMS ((struct type *, char *, FILE *, int, int)); + extern void c_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int)); c_print_type (type, varstring, stream, show, level); /* FIXME */ } diff --git a/gnu/usr.bin/gdb/gdb/m2-valprint.c b/gnu/usr.bin/gdb/gdb/m2-valprint.c index fc17ea50c9a3..4a314b9cc252 100644 --- a/gnu/usr.bin/gdb/gdb/m2-valprint.c +++ b/gnu/usr.bin/gdb/gdb/m2-valprint.c @@ -31,14 +31,14 @@ m2_val_print (type, valaddr, address, stream, format, deref_ref, recurse, struct type *type; char *valaddr; CORE_ADDR address; - FILE *stream; + GDB_FILE *stream; int format; int deref_ref; int recurse; enum val_prettyprint pretty; { extern int - c_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int, + c_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); return (c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty)); diff --git a/gnu/usr.bin/gdb/gdb/main.c b/gnu/usr.bin/gdb/gdb/main.c index deaf6240ef98..5b5b10a580a5 100644 --- a/gnu/usr.bin/gdb/gdb/main.c +++ b/gnu/usr.bin/gdb/gdb/main.c @@ -1,5 +1,5 @@ -/* Top level `main' program for GDB, the GNU debugger. - Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992 +/* Top level stuff for GDB, the GNU debugger. + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -19,331 +19,27 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" -#include "gdbcmd.h" -#include "call-cmds.h" -#include "symtab.h" -#include "inferior.h" -#include "signals.h" +#include +#include "top.h" #include "target.h" -#include "breakpoint.h" -#include "gdbtypes.h" -#include "expression.h" -#include "language.h" -#include "terminal.h" /* For job_control. */ +#include "inferior.h" +#include "call-cmds.h" #include "getopt.h" -/* readline include files */ -#include "readline.h" -#include "history.h" - -/* readline defines this. */ -#undef savestring - -#ifdef USG #include -#include -#endif - -#include -#ifndef NO_SYS_FILE -#include -#endif -#include -#include #include #include -#ifdef SET_STACK_LIMIT_HUGE -#include -#include - -int original_stack_limit; +#include +/* R_OK lives in either unistd.h or sys/file.h. */ +#ifdef USG +#include #endif - -/* Prototypes for local functions */ - -static char * -symbol_completion_function PARAMS ((char *, int)); - -static void -command_loop PARAMS ((void)); - -static void -command_loop_marker PARAMS ((int)); - -static void -print_gdb_version PARAMS ((FILE *)); - -static void -quit_command PARAMS ((char *, int)); - -static void -init_main PARAMS ((void)); - -static void -init_history PARAMS ((void)); - -static void -init_cmd_lists PARAMS ((void)); - -static void -float_handler PARAMS ((int)); - -static void -source_command PARAMS ((char *, int)); - -static void cd_command PARAMS ((char *, int)); - -static void -print_gnu_advertisement PARAMS ((void)); - -static void -init_signals PARAMS ((void)); - -static void -read_command_file PARAMS ((FILE *)); - -static void -set_verbose PARAMS ((char *, int, struct cmd_list_element *)); - -static void -show_history PARAMS ((char *, int)); - -static void -set_history PARAMS ((char *, int)); - -static void -set_history_size_command PARAMS ((char *, int, struct cmd_list_element *)); - -static void -show_commands PARAMS ((char *, int)); - -static void -echo_command PARAMS ((char *, int)); - -static void -pwd_command PARAMS ((char *, int)); - -static void -show_version PARAMS ((char *, int)); - -static void -document_command PARAMS ((char *, int)); - -static void -define_command PARAMS ((char *, int)); - -static void -validate_comname PARAMS ((char *)); - -static void -help_command PARAMS ((char *, int)); - -static void -show_command PARAMS ((char *, int)); - -static void -info_command PARAMS ((char *, int)); - -static void -do_nothing PARAMS ((int)); - -static int -quit_cover PARAMS ((char *)); - -static void -disconnect PARAMS ((int)); - -static void -source_cleanup PARAMS ((FILE *)); - -/* If this definition isn't overridden by the header files, assume - that isatty and fileno exist on this system. */ -#ifndef ISATTY -#define ISATTY(FP) (isatty (fileno (FP))) +#ifndef NO_SYS_FILE +#include #endif -/* Initialization file name for gdb. This is overridden in some configs. */ - -#ifndef GDBINIT_FILENAME -#define GDBINIT_FILENAME ".gdbinit" -#endif -static char gdbinit[] = GDBINIT_FILENAME; -static int inhibit_gdbinit = 0; - -#define ALL_CLEANUPS ((struct cleanup *)0) - -/* Version number of GDB, as a string. */ - -extern char *version; - -/* Canonical host name as a string. */ - -extern char *host_canonical; - -/* Canonical target name as a string. */ - -extern char *target_canonical; - -/* Message to be printed before the error message, when an error occurs. */ - -extern char *error_pre_print; - -/* Message to be printed before the warning message, when a warning occurs. */ - -extern char *warning_pre_print; - -extern char lang_frame_mismatch_warn[]; /* language.c */ - -/* Flag for whether we want all the "from_tty" gubbish printed. */ - -int caution = 1; /* Default is yes, sigh. */ - -/* - * Define all cmd_list_element's - */ - -/* Chain containing all defined commands. */ - -struct cmd_list_element *cmdlist; - -/* Chain containing all defined info subcommands. */ - -struct cmd_list_element *infolist; - -/* Chain containing all defined enable subcommands. */ - -struct cmd_list_element *enablelist; - -/* Chain containing all defined disable subcommands. */ - -struct cmd_list_element *disablelist; - -/* Chain containing all defined delete subcommands. */ - -struct cmd_list_element *deletelist; - -/* Chain containing all defined "enable breakpoint" subcommands. */ - -struct cmd_list_element *enablebreaklist; - -/* Chain containing all defined set subcommands */ - -struct cmd_list_element *setlist; - -/* Chain containing all defined unset subcommands */ - -struct cmd_list_element *unsetlist; - -/* Chain containing all defined show subcommands. */ - -struct cmd_list_element *showlist; - -/* Chain containing all defined \"set history\". */ - -struct cmd_list_element *sethistlist; - -/* Chain containing all defined \"show history\". */ - -struct cmd_list_element *showhistlist; - -/* Chain containing all defined \"unset history\". */ - -struct cmd_list_element *unsethistlist; - -/* Chain containing all defined maintenance subcommands. */ - -#if MAINTENANCE_CMDS -struct cmd_list_element *maintenancelist; -#endif - -/* Chain containing all defined "maintenance info" subcommands. */ - -#if MAINTENANCE_CMDS -struct cmd_list_element *maintenanceinfolist; -#endif - -/* Chain containing all defined "maintenance print" subcommands. */ - -#if MAINTENANCE_CMDS -struct cmd_list_element *maintenanceprintlist; -#endif - -struct cmd_list_element *setprintlist; - -struct cmd_list_element *showprintlist; - -struct cmd_list_element *setchecklist; - -struct cmd_list_element *showchecklist; - -/* stdio stream that command input is being read from. Set to stdin normally. - Set by source_command to the file we are sourcing. Set to NULL if we are - executing a user-defined command. */ - -FILE *instream; - -/* Current working directory. */ - -char *current_directory; - -/* The directory name is actually stored here (usually). */ -static char dirbuf[1024]; - -/* Function to call before reading a command, if nonzero. - The function receives two args: an input stream, - and a prompt string. */ - -void (*window_hook) PARAMS ((FILE *, char *)); - -extern int mapped_symbol_files; -extern int readnow_symbol_files; - -int epoch_interface; -int xgdb_verbose; - -/* gdb prints this when reading a command interactively */ -static char *prompt; - -/* Buffer used for reading command lines, and the size - allocated for it so far. */ - -char *line; -int linesize = 100; - -/* Baud rate specified for talking to serial target systems. Default - is left as -1, so targets can choose their own defaults. */ - -int baud_rate = -1; - -/* Non-zero tells remote* modules to output debugging info. */ - -int remote_debug = 0; - -/* Signal to catch ^Z typed while reading a command: SIGTSTP or SIGCONT. */ - -#ifndef STOP_SIGNAL -#ifdef SIGTSTP -#define STOP_SIGNAL SIGTSTP -static void stop_sig PARAMS ((int)); -#endif -#endif - -/* Some System V have job control but not sigsetmask(). */ -#if !defined (HAVE_SIGSETMASK) -#define HAVE_SIGSETMASK !defined (USG) -#endif - -#if 0 == (HAVE_SIGSETMASK) -#define sigsetmask(n) -#endif - -/* Where to go for return_to_top_level (RETURN_ERROR). */ -static jmp_buf error_return; -/* Where to go for return_to_top_level (RETURN_QUIT). */ -static jmp_buf quit_return; - /* Temporary variable for SET_TOP_LEVEL. */ static int top_level_val; @@ -356,137 +52,8 @@ static int top_level_val; ? (PTR) 0 : (PTR) memcpy (quit_return, error_return, sizeof (jmp_buf))) \ , top_level_val) -/* Return for reason REASON. This generally gets back to the command - loop, but can be caught via catch_errors. */ +extern void gdb_init PARAMS ((void)); -NORETURN void -return_to_top_level (reason) - enum return_reason reason; -{ - quit_flag = 0; - immediate_quit = 0; - - /* Perhaps it would be cleaner to do this via the cleanup chain (not sure - I can think of a reason why that is vital, though). */ - bpstat_clear_actions(stop_bpstat); /* Clear queued breakpoint commands */ - - disable_current_display (); - do_cleanups (ALL_CLEANUPS); - (NORETURN void) longjmp - (reason == RETURN_ERROR ? error_return : quit_return, 1); -} - -/* Call FUNC with arg ARGS, catching any errors. If there is no - error, return the value returned by FUNC. If there is an error, - print ERRSTRING, print the specific error message, then return - zero. - - Must not be called with immediate_quit in effect (bad things might - happen, say we got a signal in the middle of a memcpy to quit_return). - This is an OK restriction; with very few exceptions immediate_quit can - be replaced by judicious use of QUIT. - - MASK specifies what to catch; it is normally set to - RETURN_MASK_ALL, if for no other reason than that the code which - calls catch_errors might not be set up to deal with a quit which - isn't caught. But if the code can deal with it, it generally - should be RETURN_MASK_ERROR, unless for some reason it is more - useful to abort only the portion of the operation inside the - catch_errors. Note that quit should return to the command line - fairly quickly, even if some further processing is being done. */ - -int -catch_errors (func, args, errstring, mask) - int (*func) PARAMS ((char *)); - PTR args; - char *errstring; - return_mask mask; -{ - jmp_buf saved_error; - jmp_buf saved_quit; - jmp_buf tmp_jmp; - int val; - struct cleanup *saved_cleanup_chain; - char *saved_error_pre_print; - - saved_cleanup_chain = save_cleanups (); - saved_error_pre_print = error_pre_print; - - if (mask & RETURN_MASK_ERROR) - memcpy ((char *)saved_error, (char *)error_return, sizeof (jmp_buf)); - if (mask & RETURN_MASK_QUIT) - memcpy (saved_quit, quit_return, sizeof (jmp_buf)); - error_pre_print = errstring; - - if (setjmp (tmp_jmp) == 0) - { - if (mask & RETURN_MASK_ERROR) - memcpy (error_return, tmp_jmp, sizeof (jmp_buf)); - if (mask & RETURN_MASK_QUIT) - memcpy (quit_return, tmp_jmp, sizeof (jmp_buf)); - val = (*func) (args); - } - else - val = 0; - - restore_cleanups (saved_cleanup_chain); - - error_pre_print = saved_error_pre_print; - if (mask & RETURN_MASK_ERROR) - memcpy (error_return, saved_error, sizeof (jmp_buf)); - if (mask & RETURN_MASK_QUIT) - memcpy (quit_return, saved_quit, sizeof (jmp_buf)); - return val; -} - -/* Handler for SIGHUP. */ - -static void -disconnect (signo) -int signo; -{ - catch_errors (quit_cover, NULL, - "Could not kill the program being debugged", RETURN_MASK_ALL); - signal (SIGHUP, SIG_DFL); - kill (getpid (), SIGHUP); -} - -/* Just a little helper function for disconnect(). */ - -static int -quit_cover (s) -char *s; -{ - caution = 0; /* Throw caution to the wind -- we're exiting. - This prevents asking the user dumb questions. */ - quit_command((char *)0, 0); - return 0; -} - -/* Clean up on error during a "source" command (or execution of a - user-defined command). */ - -static void -source_cleanup (stream) - FILE *stream; -{ - /* Restore the previous input stream. */ - instream = stream; -} - -/* Read commands from STREAM. */ -static void -read_command_file (stream) - FILE *stream; -{ - struct cleanup *cleanups; - - cleanups = make_cleanup (source_cleanup, instream); - instream = stream; - command_loop (); - do_cleanups (cleanups); -} - int main (argc, argv) int argc; @@ -552,21 +119,13 @@ main (argc, argv) line[0] = '\0'; /* Terminate saved (now empty) cmd line */ instream = stdin; - getcwd (dirbuf, sizeof (dirbuf)); - current_directory = dirbuf; + getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)); + current_directory = gdb_dirbuf; -#ifdef SET_STACK_LIMIT_HUGE - { - struct rlimit rlim; - - /* Set the stack limit huge so that alloca (particularly stringtab - * in dbxread.c) does not fail. */ - getrlimit (RLIMIT_STACK, &rlim); - original_stack_limit = rlim.rlim_cur; - rlim.rlim_cur = rlim.rlim_max; - setrlimit (RLIMIT_STACK, &rlim); - } -#endif /* SET_STACK_LIMIT_HUGE */ +#ifdef KERNEL_DEBUG + if (strstr(argv[0], "kgdb") != NULL) + kernel_debugging = 1; +#endif /* Parse arguments and options. */ { @@ -587,8 +146,14 @@ main (argc, argv) {"n", no_argument, &inhibit_gdbinit, 1}, {"batch", no_argument, &batch, 1}, {"epoch", no_argument, &epoch_interface, 1}, - {"fullname", no_argument, &frame_file_full_name, 1}, - {"f", no_argument, &frame_file_full_name, 1}, + + /* This is a synonym for "--annotate=1". --annotate is now preferred, + but keep this here for a long time because people will be running + emacses which use --fullname. */ + {"fullname", no_argument, 0, 'f'}, + {"f", no_argument, 0, 'f'}, + + {"annotate", required_argument, 0, 12}, {"help", no_argument, &print_help, 1}, {"se", required_argument, 0, 10}, {"symbols", required_argument, 0, 's'}, @@ -605,6 +170,10 @@ main (argc, argv) {"tty", required_argument, 0, 't'}, {"baud", required_argument, 0, 'b'}, {"b", required_argument, 0, 'b'}, +#ifdef KERNEL_DEBUG + {"kernel", no_argument, &kernel_debugging, 1}, + {"k", no_argument, &kernel_debugging, 1}, +#endif /* Allow machine descriptions to add more options... */ #ifdef ADDITIONAL_OPTIONS ADDITIONAL_OPTIONS @@ -637,6 +206,13 @@ main (argc, argv) case 11: cdarg = optarg; break; + case 12: + /* FIXME: what if the syntax is wrong (e.g. not digits)? */ + annotation_level = atoi (optarg); + break; + case 'f': + annotation_level = 1; + break; case 's': symarg = optarg; break; @@ -677,17 +253,28 @@ main (argc, argv) i = strtol (optarg, &p, 0); if (i == 0 && p == optarg) - warning ("Could not set baud rate to `%s'.\n", optarg); + + /* Don't use *_filtered or warning() (which relies on + current_target) until after initialize_all_files(). */ + + fprintf_unfiltered + (gdb_stderr, + "warning: could not set baud rate to `%s'.\n", optarg); else baud_rate = i; } break; +#ifdef KERNEL_DEBUG + case 'k': + kernel_debugging = 1; + break; +#endif #ifdef ADDITIONAL_OPTION_CASES ADDITIONAL_OPTION_CASES #endif case '?': - fprintf (stderr, + fprintf_unfiltered (gdb_stderr, "Use `%s --help' for a complete list of options.\n", argv[0]); exit (1); @@ -707,7 +294,7 @@ main (argc, argv) corearg = argv[optind]; break; case 3: - fprintf (stderr, + fprintf_unfiltered (gdb_stderr, "Excess command line arguments ignored. (%s%s)\n", argv[optind], (optind == argc - 1) ? "" : " ..."); break; @@ -716,18 +303,13 @@ main (argc, argv) quiet = 1; } - /* Run the init function of each source file */ - - init_cmd_lists (); /* This needs to be done first */ - initialize_all_files (); - init_main (); /* But that omits this file! Do it now */ - init_signals (); + gdb_init (); /* Do these (and anything which might call wrap_here or *_filtered) after initialize_all_files. */ if (print_version) { - print_gdb_version (stdout); + print_gdb_version (gdb_stdout); wrap_here (""); printf_filtered ("\n"); exit (0); @@ -739,14 +321,14 @@ main (argc, argv) are printing the version here, and the help is long enough already. */ - print_gdb_version (stdout); + print_gdb_version (gdb_stdout); /* Make sure the output gets printed. */ wrap_here (""); printf_filtered ("\n"); /* But don't use *_filtered here. We don't want to prompt for continue no matter how small the screen or how much we're going to print. */ - fputs ("\ + fputs_unfiltered ("\ This is the GNU debugger. Usage:\n\ gdb [options] [executable-file [core-file or process-id]]\n\ Options:\n\ @@ -767,13 +349,13 @@ Options:\n\ -b BAUDRATE Set serial port baud rate used for remote debugging.\n\ --mapped Use mapped symbol files if supported on this system.\n\ --readnow Fully read symbol files on first access.\n\ -", stdout); +", gdb_stdout); #ifdef ADDITIONAL_OPTION_HELP - fputs (ADDITIONAL_OPTION_HELP, stdout); + fputs_unfiltered (ADDITIONAL_OPTION_HELP, gdb_stdout); #endif - fputs ("\n\ + fputs_unfiltered ("\n\ For more information, type \"help\" from within GDB, or consult the\n\ -GDB manual (available as on-line info or a printed manual).\n", stdout); +GDB manual (available as on-line info or a printed manual).\n", gdb_stdout); exit (0); } @@ -782,23 +364,17 @@ GDB manual (available as on-line info or a printed manual).\n", stdout); /* Print all the junk at the top, with trailing "..." if we are about to read a symbol file (possibly slowly). */ print_gnu_advertisement (); - print_gdb_version (stdout); + print_gdb_version (gdb_stdout); if (symarg) printf_filtered (".."); wrap_here(""); - fflush (stdout); /* Force to screen during slow operations */ + gdb_flush (gdb_stdout); /* Force to screen during slow operations */ } error_pre_print = "\n\n"; /* We may get more than one warning, don't double space all of them... */ warning_pre_print = "\nwarning: "; - /* We need a default language for parsing expressions, so simple things like - "set width 0" won't fail if no language is explicitly set in a config file - or implicitly set by reading an executable during startup. */ - set_language (language_c); - expected_language = current_language; /* don't warn about the change. */ - /* Read and execute $HOME/.gdbinit file, if it exists. This is done *before* all the command line arguments are processed; it sets global parameters, which are independent of what file you are @@ -837,7 +413,6 @@ GDB manual (available as on-line info or a printed manual).\n", stdout); if (!SET_TOP_LEVEL ()) { cd_command (cdarg, 0); - init_source_path (); } } do_cleanups (ALL_CLEANUPS); @@ -953,1847 +528,32 @@ GDB manual (available as on-line info or a printed manual).\n", stdout); } /* No exit -- exit is through quit_command. */ } - + void -execute_user_command (c, args) - struct cmd_list_element *c; - char *args; -{ - register struct command_line *cmdlines; - struct cleanup *old_chain; - - if (args) - error ("User-defined commands cannot take arguments."); - - cmdlines = c->user_commands; - if (cmdlines == 0) - /* Null command */ - return; - - /* Set the instream to 0, indicating execution of a - user-defined function. */ - old_chain = make_cleanup (source_cleanup, instream); - instream = (FILE *) 0; - while (cmdlines) - { - execute_command (cmdlines->line, 0); - cmdlines = cmdlines->next; - } - do_cleanups (old_chain); -} - -/* Execute the line P as a command. - Pass FROM_TTY as second argument to the defining function. */ - -void -execute_command (p, from_tty) - char *p; - int from_tty; -{ - register struct cmd_list_element *c; - register enum language flang; - static int warned = 0; - - free_all_values (); - - /* This can happen when command_line_input hits end of file. */ - if (p == NULL) - return; - - while (*p == ' ' || *p == '\t') p++; - if (*p) - { - char *arg; - - c = lookup_cmd (&p, cmdlist, "", 0, 1); - /* Pass null arg rather than an empty one. */ - arg = *p ? p : 0; - - /* If this command has been hooked, run the hook first. */ - if (c->hook) - execute_user_command (c->hook, (char *)0); - - if (c->class == class_user) - execute_user_command (c, arg); - else if (c->type == set_cmd || c->type == show_cmd) - do_setshow_command (arg, from_tty & caution, c); - else if (c->function.cfunc == NO_FUNCTION) - error ("That is not a command, just a help topic."); - else - (*c->function.cfunc) (arg, from_tty & caution); - } - - /* Tell the user if the language has changed (except first time). */ - if (current_language != expected_language) - { - if (language_mode == language_mode_auto) { - language_info (1); /* Print what changed. */ - } - warned = 0; - } - - /* Warn the user if the working language does not match the - language of the current frame. Only warn the user if we are - actually running the program, i.e. there is a stack. */ - /* FIXME: This should be cacheing the frame and only running when - the frame changes. */ - if (target_has_stack) - { - flang = get_frame_language (); - if (!warned - && flang != language_unknown - && flang != current_language->la_language) - { - printf_filtered ("%s\n", lang_frame_mismatch_warn); - warned = 1; - } - } -} - -/* ARGSUSED */ -static void -command_loop_marker (foo) - int foo; +init_proc () { } -/* Read commands from `instream' and execute them - until end of file or error reading instream. */ -static void -command_loop () -{ - struct cleanup *old_chain; - char *command; - int stdin_is_tty = ISATTY (stdin); - - while (!feof (instream)) - { - if (window_hook && instream == stdin) - (*window_hook) (instream, prompt); - - quit_flag = 0; - if (instream == stdin && stdin_is_tty) - reinitialize_more_filter (); - old_chain = make_cleanup (command_loop_marker, 0); - command = command_line_input (instream == stdin ? prompt : (char *) NULL, - instream == stdin); - if (command == 0) - return; - execute_command (command, instream == stdin); - /* Do any commands attached to breakpoint we stopped at. */ - bpstat_do_actions (&stop_bpstat); - do_cleanups (old_chain); - } -} - -/* Commands call this if they do not want to be repeated by null lines. */ - -void -dont_repeat () -{ - /* If we aren't reading from standard input, we are saving the last - thing read from stdin in line and don't want to delete it. Null lines - won't repeat here in any case. */ - if (instream == stdin) - *line = 0; -} - -/* Read a line from the stream "instream" without command line editing. - - It prints PRROMPT once at the start. - Action is compatible with "readline", e.g. space for the result is - malloc'd and should be freed by the caller. - - A NULL return means end of file. */ -char * -gdb_readline (prrompt) - char *prrompt; -{ - int c; - char *result; - int input_index = 0; - int result_size = 80; - - if (prrompt) - { - /* Don't use a _filtered function here. It causes the assumed - character position to be off, since the newline we read from - the user is not accounted for. */ - fputs (prrompt, stdout); - fflush (stdout); - } - - result = (char *) xmalloc (result_size); - - while (1) - { - /* Read from stdin if we are executing a user defined command. - This is the right thing for prompt_for_continue, at least. */ - c = fgetc (instream ? instream : stdin); - - if (c == EOF) - { - if (input_index > 0) - /* The last line does not end with a newline. Return it, and - if we are called again fgetc will still return EOF and - we'll return NULL then. */ - break; - free (result); - return NULL; - } - - if (c == '\n') - break; - - result[input_index++] = c; - while (input_index >= result_size) - { - result_size *= 2; - result = (char *) xrealloc (result, result_size); - } - } - - result[input_index++] = '\0'; - return result; -} - -/* Variables which control command line editing and history - substitution. These variables are given default values at the end - of this file. */ -static int command_editing_p; -static int history_expansion_p; -static int write_history_p; -static int history_size; -static char *history_filename; - -/* readline uses the word breaks for two things: - (1) In figuring out where to point the TEXT parameter to the - rl_completion_entry_function. Since we don't use TEXT for much, - it doesn't matter a lot what the word breaks are for this purpose, but - it does affect how much stuff M-? lists. - (2) If one of the matches contains a word break character, readline - will quote it. That's why we switch between - gdb_completer_word_break_characters and - gdb_completer_command_word_break_characters. I'm not sure when - we need this behavior (perhaps for funky characters in C++ symbols?). */ - -/* Variables which are necessary for fancy command line editing. */ -char *gdb_completer_word_break_characters = - " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,-"; - -/* When completing on command names, we remove '-' from the list of - word break characters, since we use it in command names. If the - readline library sees one in any of the current completion strings, - it thinks that the string needs to be quoted and automatically supplies - a leading quote. */ -char *gdb_completer_command_word_break_characters = - " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,"; - -/* Characters that can be used to quote completion strings. Note that we - can't include '"' because the gdb C parser treats such quoted sequences - as strings. */ -char *gdb_completer_quote_characters = - "'"; - -/* Functions that are used as part of the fancy command line editing. */ - -/* This can be used for functions which don't want to complete on symbols - but don't want to complete on anything else either. */ -/* ARGSUSED */ -char ** -noop_completer (text, prefix) - char *text; - char *prefix; -{ - return NULL; -} - -/* Complete on filenames. */ -char ** -filename_completer (text, word) - char *text; - char *word; -{ - /* From readline. */ - extern char *filename_completion_function (); - int subsequent_name; - char **return_val; - int return_val_used; - int return_val_alloced; - - return_val_used = 0; - /* Small for testing. */ - return_val_alloced = 1; - return_val = (char **) xmalloc (return_val_alloced * sizeof (char *)); - - subsequent_name = 0; - while (1) - { - char *p; - p = filename_completion_function (text, subsequent_name); - if (return_val_used >= return_val_alloced) - { - return_val_alloced *= 2; - return_val = - (char **) xrealloc (return_val, - return_val_alloced * sizeof (char *)); - } - if (p == NULL) - { - return_val[return_val_used++] = p; - break; - } - /* Like emacs, don't complete on old versions. Especially useful - in the "source" command. */ - if (p[strlen (p) - 1] == '~') - continue; - - { - char *q; - if (word == text) - /* Return exactly p. */ - return_val[return_val_used++] = p; - else if (word > text) - { - /* Return some portion of p. */ - q = xmalloc (strlen (p) + 5); - strcpy (q, p + (word - text)); - return_val[return_val_used++] = q; - free (p); - } - else - { - /* Return some of TEXT plus p. */ - q = xmalloc (strlen (p) + (text - word) + 5); - strncpy (q, word, text - word); - q[text - word] = '\0'; - strcat (q, p); - return_val[return_val_used++] = q; - free (p); - } - } - subsequent_name = 1; - } -#if 0 - /* There is no way to do this just long enough to affect quote inserting - without also affecting the next completion. This should be fixed in - readline. FIXME. */ - /* Insure that readline does the right thing - with respect to inserting quotes. */ - rl_completer_word_break_characters = ""; -#endif - return return_val; -} - -/* Here are some useful test cases for completion. FIXME: These should - be put in the test suite. They should be tested with both M-? and TAB. - - "show output-" "radix" - "show output" "-radix" - "p" ambiguous (commands starting with p--path, print, printf, etc.) - "p " ambiguous (all symbols) - "info t foo" no completions - "info t " no completions - "info t" ambiguous ("info target", "info terminal", etc.) - "info ajksdlfk" no completions - "info ajksdlfk " no completions - "info" " " - "info " ambiguous (all info commands) - "p \"a" no completions (string constant) - "p 'a" ambiguous (all symbols starting with a) - "p b-a" ambiguous (all symbols starting with a) - "p b-" ambiguous (all symbols) - "file Make" "file" (word break hard to screw up here) - "file ../gdb.stabs/wi" "erd" (needs to not break word at slash) - */ - -/* Generate completions one by one for the completer. Each time we are - called return another potential completion to the caller. The function - is misnamed; it just completes on commands or passes the buck to the - command's completer function; the stuff specific to symbol completion - is in make_symbol_completion_list. - - TEXT is readline's idea of the "word" we are looking at; we don't really - like readline's ideas about word breaking so we ignore it. - - MATCHES is the number of matches that have currently been collected from - calling this completion function. When zero, then we need to initialize, - otherwise the initialization has already taken place and we can just - return the next potential completion string. - - Returns NULL if there are no more completions, else a pointer to a string - which is a possible completion. - - RL_LINE_BUFFER is available to be looked at; it contains the entire text - of the line. RL_POINT is the offset in that line of the cursor. You - should pretend that the line ends at RL_POINT. */ - -static char * -symbol_completion_function (text, matches) - char *text; - int matches; -{ - static char **list = (char **)NULL; /* Cache of completions */ - static int index; /* Next cached completion */ - char *output = NULL; - char *tmp_command, *p; - /* Pointer within tmp_command which corresponds to text. */ - char *word; - struct cmd_list_element *c, *result_list; - extern char *rl_line_buffer; - extern int rl_point; - - if (matches == 0) - { - /* The caller is beginning to accumulate a new set of completions, so - we need to find all of them now, and cache them for returning one at - a time on future calls. */ - - if (list) - { - /* Free the storage used by LIST, but not by the strings inside. - This is because rl_complete_internal () frees the strings. */ - free ((PTR)list); - } - list = 0; - index = 0; - - /* Choose the default set of word break characters to break completions. - If we later find out that we are doing completions on command strings - (as opposed to strings supplied by the individual command completer - functions, which can be any string) then we will switch to the - special word break set for command strings, which leaves out the - '-' character used in some commands. */ - - rl_completer_word_break_characters = - gdb_completer_word_break_characters; - - /* Decide whether to complete on a list of gdb commands or on symbols. */ - tmp_command = (char *) alloca (rl_point + 1); - p = tmp_command; - - strncpy (tmp_command, rl_line_buffer, rl_point); - tmp_command[rl_point] = '\0'; - /* Since text always contains some number of characters leading up - to rl_point, we can find the equivalent position in tmp_command - by subtracting that many characters from the end of tmp_command. */ - word = tmp_command + rl_point - strlen (text); - - if (rl_point == 0) - { - /* An empty line we want to consider ambiguous; that is, it - could be any command. */ - c = (struct cmd_list_element *) -1; - result_list = 0; - } - else - { - c = lookup_cmd_1 (&p, cmdlist, &result_list, 1); - } - - /* Move p up to the next interesting thing. */ - while (*p == ' ' || *p == '\t') - { - p++; - } - - if (!c) - { - /* It is an unrecognized command. So there are no - possible completions. */ - list = NULL; - } - else if (c == (struct cmd_list_element *) -1) - { - char *q; - - /* lookup_cmd_1 advances p up to the first ambiguous thing, but - doesn't advance over that thing itself. Do so now. */ - q = p; - while (*q && (isalnum (*q) || *q == '-' || *q == '_')) - ++q; - if (q != tmp_command + rl_point) - { - /* There is something beyond the ambiguous - command, so there are no possible completions. For - example, "info t " or "info t foo" does not complete - to anything, because "info t" can be "info target" or - "info terminal". */ - list = NULL; - } - else - { - /* We're trying to complete on the command which was ambiguous. - This we can deal with. */ - if (result_list) - { - list = complete_on_cmdlist (*result_list->prefixlist, p, - word); - } - else - { - list = complete_on_cmdlist (cmdlist, p, word); - } - /* Insure that readline does the right thing with respect to - inserting quotes. */ - rl_completer_word_break_characters = - gdb_completer_command_word_break_characters; - } - } - else - { - /* We've recognized a full command. */ - - if (p == tmp_command + rl_point) - { - /* There is no non-whitespace in the line beyond the command. */ - - if (p[-1] == ' ' || p[-1] == '\t') - { - /* The command is followed by whitespace; we need to complete - on whatever comes after command. */ - if (c->prefixlist) - { - /* It is a prefix command; what comes after it is - a subcommand (e.g. "info "). */ - list = complete_on_cmdlist (*c->prefixlist, p, word); - - /* Insure that readline does the right thing - with respect to inserting quotes. */ - rl_completer_word_break_characters = - gdb_completer_command_word_break_characters; - } - else - { - /* It is a normal command; what comes after it is - completed by the command's completer function. */ - list = (*c->completer) (p, word); - } - } - else - { - /* The command is not followed by whitespace; we need to - complete on the command itself. e.g. "p" which is a - command itself but also can complete to "print", "ptype" - etc. */ - char *q; - - /* Find the command we are completing on. */ - q = p; - while (q > tmp_command) - { - if (isalnum (q[-1]) || q[-1] == '-' || q[-1] == '_') - --q; - else - break; - } - - list = complete_on_cmdlist (result_list, q, word); - - /* Insure that readline does the right thing - with respect to inserting quotes. */ - rl_completer_word_break_characters = - gdb_completer_command_word_break_characters; - } - } - else - { - /* There is non-whitespace beyond the command. */ - - if (c->prefixlist && !c->allow_unknown) - { - /* It is an unrecognized subcommand of a prefix command, - e.g. "info adsfkdj". */ - list = NULL; - } - else - { - /* It is a normal command. */ - list = (*c->completer) (p, word); - } - } - } - } - - /* If we found a list of potential completions during initialization then - dole them out one at a time. The vector of completions is NULL - terminated, so after returning the last one, return NULL (and continue - to do so) each time we are called after that, until a new list is - available. */ - - if (list) - { - output = list[index]; - if (output) - { - index++; - } - } - -#if 0 - /* Can't do this because readline hasn't yet checked the word breaks - for figuring out whether to insert a quote. */ - if (output == NULL) - /* Make sure the word break characters are set back to normal for the - next time that readline tries to complete something. */ - rl_completer_word_break_characters = - gdb_completer_word_break_characters; -#endif - - return (output); -} - -/* Skip over a possibly quoted word (as defined by the quote characters - and word break characters the completer uses). Returns pointer to the - location after the "word". */ - -char * -skip_quoted (str) - char *str; -{ - char quote_char = '\0'; - char *scan; - - for (scan = str; *scan != '\0'; scan++) - { - if (quote_char != '\0') - { - /* Ignore everything until the matching close quote char */ - if (*scan == quote_char) - { - /* Found matching close quote. */ - scan++; - break; - } - } - else if (strchr (gdb_completer_quote_characters, *scan)) - { - /* Found start of a quoted string. */ - quote_char = *scan; - } - else if (strchr (gdb_completer_word_break_characters, *scan)) - { - break; - } - } - return (scan); -} - - -#ifdef STOP_SIGNAL -static void -stop_sig (signo) -int signo; -{ -#if STOP_SIGNAL == SIGTSTP - signal (SIGTSTP, SIG_DFL); - sigsetmask (0); - kill (getpid (), SIGTSTP); - signal (SIGTSTP, stop_sig); -#else - signal (STOP_SIGNAL, stop_sig); -#endif - printf ("%s", prompt); - fflush (stdout); - - /* Forget about any previous command -- null line now will do nothing. */ - dont_repeat (); -} -#endif /* STOP_SIGNAL */ - -/* Initialize signal handlers. */ -static void -do_nothing (signo) -int signo; -{ -} - -static void -init_signals () -{ - signal (SIGINT, request_quit); - - /* If we initialize SIGQUIT to SIG_IGN, then the SIG_IGN will get - passed to the inferior, which we don't want. It would be - possible to do a "signal (SIGQUIT, SIG_DFL)" after we fork, but - on BSD4.3 systems using vfork, that can affect the - GDB process as well as the inferior (the signal handling tables - might be in memory, shared between the two). Since we establish - a handler for SIGQUIT, when we call exec it will set the signal - to SIG_DFL for us. */ - signal (SIGQUIT, do_nothing); - if (signal (SIGHUP, do_nothing) != SIG_IGN) - signal (SIGHUP, disconnect); - signal (SIGFPE, float_handler); - -#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER) - signal (SIGWINCH, SIGWINCH_HANDLER); -#endif -} - -/* Read one line from the command input stream `instream' - into the local static buffer `linebuffer' (whose current length - is `linelength'). - The buffer is made bigger as necessary. - Returns the address of the start of the line. - - NULL is returned for end of file. - - *If* the instream == stdin & stdin is a terminal, the line read - is copied into the file line saver (global var char *line, - length linesize) so that it can be duplicated. - - This routine either uses fancy command line editing or - simple input as the user has requested. */ - -char * -command_line_input (prrompt, repeat) - char *prrompt; - int repeat; -{ - static char *linebuffer = 0; - static unsigned linelength = 0; - register char *p; - char *p1; - char *rl; - char *local_prompt = prrompt; - register int c; - char *nline; - char got_eof = 0; - - if (linebuffer == 0) - { - linelength = 80; - linebuffer = (char *) xmalloc (linelength); - } - - p = linebuffer; - - /* Control-C quits instantly if typed while in this loop - since it should not wait until the user types a newline. */ - immediate_quit++; -#ifdef STOP_SIGNAL - if (job_control) - signal (STOP_SIGNAL, stop_sig); -#endif - - while (1) - { - /* Reports are that some Sys V's don't flush stdout/err on reads - from stdin, when stdin/out are sockets rather than ttys. So we - have to do it ourselves, to make emacs-gdb and xxgdb work. - On other machines, doing this once per input should be a cheap nop. */ - fflush (stdout); - fflush (stderr); - - /* Don't use fancy stuff if not talking to stdin. */ - if (command_editing_p && instream == stdin - && ISATTY (instream)) - rl = readline (local_prompt); - else - rl = gdb_readline (local_prompt); - - if (!rl || rl == (char *) EOF) - { - got_eof = 1; - break; - } - if (strlen(rl) + 1 + (p - linebuffer) > linelength) - { - linelength = strlen(rl) + 1 + (p - linebuffer); - nline = (char *) xrealloc (linebuffer, linelength); - p += nline - linebuffer; - linebuffer = nline; - } - p1 = rl; - /* Copy line. Don't copy null at end. (Leaves line alone - if this was just a newline) */ - while (*p1) - *p++ = *p1++; - - free (rl); /* Allocated in readline. */ - - if (p == linebuffer || *(p - 1) != '\\') - break; - - p--; /* Put on top of '\'. */ - local_prompt = (char *) 0; - } - -#ifdef STOP_SIGNAL - if (job_control) - signal (STOP_SIGNAL, SIG_DFL); -#endif - immediate_quit--; - - if (got_eof) - return NULL; - - /* Do history expansion if that is wished. */ - if (history_expansion_p && instream == stdin - && ISATTY (instream)) - { - char *history_value; - int expanded; - - *p = '\0'; /* Insert null now. */ - expanded = history_expand (linebuffer, &history_value); - if (expanded) - { - /* Print the changes. */ - printf ("%s\n", history_value); - - /* If there was an error, call this function again. */ - if (expanded < 0) - { - free (history_value); - return command_line_input (prrompt, repeat); - } - if (strlen (history_value) > linelength) - { - linelength = strlen (history_value) + 1; - linebuffer = (char *) xrealloc (linebuffer, linelength); - } - strcpy (linebuffer, history_value); - p = linebuffer + strlen(linebuffer); - free (history_value); - } - } - - /* If we just got an empty line, and that is supposed - to repeat the previous command, return the value in the - global buffer. */ - if (repeat) - { - if (p == linebuffer) - return line; - p1 = linebuffer; - while (*p1 == ' ' || *p1 == '\t') - p1++; - if (!*p1) - return line; - } - - *p = 0; - - /* Add line to history if appropriate. */ - if (instream == stdin - && ISATTY (stdin) && *linebuffer) - add_history (linebuffer); - - /* Note: lines consisting soley of comments are added to the command - history. This is useful when you type a command, and then - realize you don't want to execute it quite yet. You can comment - out the command and then later fetch it from the value history - and remove the '#'. The kill ring is probably better, but some - people are in the habit of commenting things out. */ - p1 = linebuffer; - while ((c = *p1++) != '\0') - { - if (c == '"') - while ((c = *p1++) != '"') - { - /* Make sure an escaped '"' doesn't make us think the string - is ended. */ - if (c == '\\') - parse_escape (&p1); - if (c == '\0') - break; - } - else if (c == '\'') - while ((c = *p1++) != '\'') - { - /* Make sure an escaped '\'' doesn't make us think the string - is ended. */ - if (c == '\\') - parse_escape (&p1); - if (c == '\0') - break; - } - else if (c == '#') - { - /* Found a comment. */ - p1[-1] = '\0'; - break; - } - } - - /* Save into global buffer if appropriate. */ - if (repeat) - { - if (linelength > linesize) - { - line = xrealloc (line, linelength); - linesize = linelength; - } - strcpy (line, linebuffer); - return line; - } - - return linebuffer; -} - -/* Read lines from the input stream - and accumulate them in a chain of struct command_line's - which is then returned. */ - -struct command_line * -read_command_lines () -{ - struct command_line *first = 0; - register struct command_line *next, *tail = 0; - register char *p, *p1; - struct cleanup *old_chain = 0; - - while (1) - { - dont_repeat (); - p = command_line_input ((char *) NULL, instream == stdin); - if (p == NULL) - /* Treat end of file like "end". */ - break; - - /* Remove leading and trailing blanks. */ - while (*p == ' ' || *p == '\t') p++; - p1 = p + strlen (p); - while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t')) p1--; - - /* Is this "end"? */ - if (p1 - p == 3 && !strncmp (p, "end", 3)) - break; - - /* No => add this line to the chain of command lines. */ - next = (struct command_line *) xmalloc (sizeof (struct command_line)); - next->line = savestring (p, p1 - p); - next->next = 0; - if (tail) - { - tail->next = next; - } - else - { - /* We just read the first line. - From now on, arrange to throw away the lines we have - if we quit or get an error while inside this function. */ - first = next; - old_chain = make_cleanup (free_command_lines, &first); - } - tail = next; - } - - dont_repeat (); - - /* Now we are about to return the chain to our caller, - so freeing it becomes his responsibility. */ - if (first) - discard_cleanups (old_chain); - return first; -} - -/* Free a chain of struct command_line's. */ - -void -free_command_lines (lptr) - struct command_line **lptr; -{ - register struct command_line *l = *lptr; - register struct command_line *next; - - while (l) - { - next = l->next; - free (l->line); - free ((PTR)l); - l = next; - } -} - -/* Add an element to the list of info subcommands. */ - -void -add_info (name, fun, doc) - char *name; - void (*fun) PARAMS ((char *, int)); - char *doc; -{ - add_cmd (name, no_class, fun, doc, &infolist); -} - -/* Add an alias to the list of info subcommands. */ - -void -add_info_alias (name, oldname, abbrev_flag) - char *name; - char *oldname; - int abbrev_flag; -{ - add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist); -} - -/* The "info" command is defined as a prefix, with allow_unknown = 0. - Therefore, its own definition is called only for "info" with no args. */ - -/* ARGSUSED */ -static void -info_command (arg, from_tty) - char *arg; - int from_tty; -{ - printf ("\"info\" must be followed by the name of an info command.\n"); - help_list (infolist, "info ", -1, stdout); -} - -/* The "show" command with no arguments shows all the settings. */ - -/* ARGSUSED */ -static void -show_command (arg, from_tty) - char *arg; - int from_tty; -{ - cmd_show_list (showlist, from_tty, ""); -} - -/* Add an element to the list of commands. */ - -void -add_com (name, class, fun, doc) - char *name; - enum command_class class; - void (*fun) PARAMS ((char *, int)); - char *doc; -{ - add_cmd (name, class, fun, doc, &cmdlist); -} - -/* Add an alias or abbreviation command to the list of commands. */ - -void -add_com_alias (name, oldname, class, abbrev_flag) - char *name; - char *oldname; - enum command_class class; - int abbrev_flag; -{ - add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist); -} - -void -error_no_arg (why) - char *why; -{ - error ("Argument required (%s).", why); -} - -/* ARGSUSED */ -static void -help_command (command, from_tty) - char *command; - int from_tty; /* Ignored */ -{ - help_cmd (command, stdout); -} - -static void -validate_comname (comname) - char *comname; -{ - register char *p; - - if (comname == 0) - error_no_arg ("name of command to define"); - - p = comname; - while (*p) - { - if (!isalnum(*p) && *p != '-') - error ("Junk in argument list: \"%s\"", p); - p++; - } -} - -/* This is just a placeholder in the command data structures. */ -static void -user_defined_command (ignore, from_tty) - char *ignore; - int from_tty; -{ -} - -static void -define_command (comname, from_tty) - char *comname; - int from_tty; -{ - register struct command_line *cmds; - register struct cmd_list_element *c, *newc, *hookc = 0; - char *tem = comname; -#define HOOK_STRING "hook-" -#define HOOK_LEN 5 - - validate_comname (comname); - - /* Look it up, and verify that we got an exact match. */ - c = lookup_cmd (&tem, cmdlist, "", -1, 1); - if (c && !STREQ (comname, c->name)) - c = 0; - - if (c) - { - if (c->class == class_user || c->class == class_alias) - tem = "Redefine command \"%s\"? "; - else - tem = "Really redefine built-in command \"%s\"? "; - if (!query (tem, c->name)) - error ("Command \"%s\" not redefined.", c->name); - } - - /* If this new command is a hook, then mark the command which it - is hooking. Note that we allow hooking `help' commands, so that - we can hook the `stop' pseudo-command. */ - - if (!strncmp (comname, HOOK_STRING, HOOK_LEN)) - { - /* Look up cmd it hooks, and verify that we got an exact match. */ - tem = comname+HOOK_LEN; - hookc = lookup_cmd (&tem, cmdlist, "", -1, 0); - if (hookc && !STREQ (comname+HOOK_LEN, hookc->name)) - hookc = 0; - if (!hookc) - { - warning ("Your new `%s' command does not hook any existing command.", - comname); - if (!query ("Proceed? ", (char *)0)) - error ("Not confirmed."); - } - } - - comname = savestring (comname, strlen (comname)); - - /* If the rest of the commands will be case insensitive, this one - should behave in the same manner. */ - for (tem = comname; *tem; tem++) - if (isupper(*tem)) *tem = tolower(*tem); - - if (from_tty) - { - printf ("Type commands for definition of \"%s\".\n\ -End with a line saying just \"end\".\n", comname); - fflush (stdout); - } - - cmds = read_command_lines (); - - if (c && c->class == class_user) - free_command_lines (&c->user_commands); - - newc = add_cmd (comname, class_user, user_defined_command, - (c && c->class == class_user) - ? c->doc : savestring ("User-defined.", 13), &cmdlist); - newc->user_commands = cmds; - - /* If this new command is a hook, then mark both commands as being - tied. */ - if (hookc) - { - hookc->hook = newc; /* Target gets hooked. */ - newc->hookee = hookc; /* We are marked as hooking target cmd. */ - } -} - -static void -document_command (comname, from_tty) - char *comname; - int from_tty; -{ - struct command_line *doclines; - register struct cmd_list_element *c; - char *tem = comname; - - validate_comname (comname); - - c = lookup_cmd (&tem, cmdlist, "", 0, 1); - - if (c->class != class_user) - error ("Command \"%s\" is built-in.", comname); - - if (from_tty) - printf ("Type documentation for \"%s\".\n\ -End with a line saying just \"end\".\n", comname); - - doclines = read_command_lines (); - - if (c->doc) free (c->doc); - - { - register struct command_line *cl1; - register int len = 0; - - for (cl1 = doclines; cl1; cl1 = cl1->next) - len += strlen (cl1->line) + 1; - - c->doc = (char *) xmalloc (len + 1); - *c->doc = 0; - - for (cl1 = doclines; cl1; cl1 = cl1->next) - { - strcat (c->doc, cl1->line); - if (cl1->next) - strcat (c->doc, "\n"); - } - } - - free_command_lines (&doclines); -} - -static void -print_gnu_advertisement() -{ - printf ("\ -GDB is free software and you are welcome to distribute copies of it\n\ - under certain conditions; type \"show copying\" to see the conditions.\n\ -There is absolutely no warranty for GDB; type \"show warranty\" for details.\n\ -"); -} - -static void -print_gdb_version (stream) - FILE *stream; -{ - fprintf_filtered (stream, "\ -GDB %s (%s", version, host_canonical); - - if (strcmp(host_canonical, target_canonical)) - fprintf_filtered (stream, " --target %s", target_canonical); - - fprintf_filtered (stream, "), "); - wrap_here(""); - fprintf_filtered (stream, "Copyright 1993 Free Software Foundation, Inc."); -} - -/* ARGSUSED */ -static void -show_version (args, from_tty) - char *args; - int from_tty; -{ - immediate_quit++; - print_gnu_advertisement (); - print_gdb_version (stdout); - printf_filtered ("\n"); - immediate_quit--; -} - -/* xgdb calls this to reprint the usual GDB prompt. */ - -void -print_prompt () -{ - printf ("%s", prompt); - fflush (stdout); -} - -static void -quit_command (args, from_tty) - char *args; - int from_tty; -{ - if (inferior_pid != 0 && target_has_execution) - { - if (attach_flag) - { - if (query ("The program is running. Quit anyway (and detach it)? ")) - target_detach (args, from_tty); - else - error ("Not confirmed."); - } - else - { - if (query ("The program is running. Quit anyway (and kill it)? ")) - target_kill (); - else - error ("Not confirmed."); - } - } - /* Save the history information if it is appropriate to do so. */ - if (write_history_p && history_filename) - write_history (history_filename); - exit (0); -} - -/* Returns whether GDB is running on a terminal and whether the user - desires that questions be asked of them on that terminal. */ - int -input_from_terminal_p () +proc_wait (pid, status) + int pid; + int *status; { - return gdb_has_a_terminal () && (instream == stdin) & caution; -} - -/* ARGSUSED */ -static void -pwd_command (args, from_tty) - char *args; - int from_tty; -{ - if (args) error ("The \"pwd\" command does not take an argument: %s", args); - getcwd (dirbuf, sizeof (dirbuf)); - - if (!STREQ (dirbuf, current_directory)) - printf ("Working directory %s\n (canonically %s).\n", - current_directory, dirbuf); - else - printf ("Working directory %s.\n", current_directory); -} - -static void -cd_command (dir, from_tty) - char *dir; - int from_tty; -{ - int len; - /* Found something other than leading repetitions of "/..". */ - int found_real_path; - char *p; - - /* If the new directory is absolute, repeat is a no-op; if relative, - repeat might be useful but is more likely to be a mistake. */ - dont_repeat (); - - if (dir == 0) - error_no_arg ("new working directory"); - - dir = tilde_expand (dir); - make_cleanup (free, dir); - - if (chdir (dir) < 0) - perror_with_name (dir); - - len = strlen (dir); - dir = savestring (dir, len - (len > 1 && dir[len-1] == '/')); - if (dir[0] == '/') - current_directory = dir; - else - { - if (current_directory[0] == '/' && current_directory[1] == '\0') - current_directory = concat (current_directory, dir, NULL); - else - current_directory = concat (current_directory, "/", dir, NULL); - free (dir); - } - - /* Now simplify any occurrences of `.' and `..' in the pathname. */ - - found_real_path = 0; - for (p = current_directory; *p;) - { - if (p[0] == '/' && p[1] == '.' && (p[2] == 0 || p[2] == '/')) - strcpy (p, p + 2); - else if (p[0] == '/' && p[1] == '.' && p[2] == '.' - && (p[3] == 0 || p[3] == '/')) - { - if (found_real_path) - { - /* Search backwards for the directory just before the "/.." - and obliterate it and the "/..". */ - char *q = p; - while (q != current_directory && q[-1] != '/') - --q; - - if (q == current_directory) - /* current_directory is - a relative pathname ("can't happen"--leave it alone). */ - ++p; - else - { - strcpy (q - 1, p + 3); - p = q - 1; - } - } - else - /* We are dealing with leading repetitions of "/..", for example - "/../..", which is the Mach super-root. */ - p += 3; - } - else - { - found_real_path = 1; - ++p; - } - } - - forget_cached_source_info (); - - if (from_tty) - pwd_command ((char *) 0, 1); -} - -/* ARGSUSED */ -static void -source_command (args, from_tty) - char *args; - int from_tty; -{ - FILE *stream; - struct cleanup *cleanups; - char *file = args; - - if (file == NULL) - { - error ("source command requires pathname of file to source."); - } - - file = tilde_expand (file); - make_cleanup (free, file); - - stream = fopen (file, FOPEN_RT); - if (stream == 0) - perror_with_name (file); - - cleanups = make_cleanup (fclose, stream); - - read_command_file (stream); - - do_cleanups (cleanups); -} - -/* ARGSUSED */ -static void -echo_command (text, from_tty) - char *text; - int from_tty; -{ - char *p = text; - register int c; - - if (text) - while ((c = *p++) != '\0') - { - if (c == '\\') - { - /* \ at end of argument is used after spaces - so they won't be lost. */ - if (*p == 0) - return; - - c = parse_escape (&p); - if (c >= 0) - printf_filtered ("%c", c); - } - else - printf_filtered ("%c", c); - } - - /* Force this output to appear now. */ - wrap_here (""); - fflush (stdout); -} - - -/* Functions to manipulate command line editing control variables. */ - -/* Number of commands to print in each call to show_commands. */ -#define Hist_print 10 -static void -show_commands (args, from_tty) - char *args; - int from_tty; -{ - /* Index for history commands. Relative to history_base. */ - int offset; - - /* Number of the history entry which we are planning to display next. - Relative to history_base. */ - static int num = 0; - - /* The first command in the history which doesn't exist (i.e. one more - than the number of the last command). Relative to history_base. */ - int hist_len; - - extern struct _hist_entry *history_get PARAMS ((int)); - extern int history_base; - - /* Print out some of the commands from the command history. */ - /* First determine the length of the history list. */ - hist_len = history_size; - for (offset = 0; offset < history_size; offset++) - { - if (!history_get (history_base + offset)) - { - hist_len = offset; - break; - } - } - - if (args) - { - if (args[0] == '+' && args[1] == '\0') - /* "info editing +" should print from the stored position. */ - ; - else - /* "info editing " should print around command number . */ - num = (parse_and_eval_address (args) - history_base) - Hist_print / 2; - } - /* "show commands" means print the last Hist_print commands. */ - else - { - num = hist_len - Hist_print; - } - - if (num < 0) - num = 0; - - /* If there are at least Hist_print commands, we want to display the last - Hist_print rather than, say, the last 6. */ - if (hist_len - num < Hist_print) - { - num = hist_len - Hist_print; - if (num < 0) - num = 0; - } - - for (offset = num; offset < num + Hist_print && offset < hist_len; offset++) - { - printf_filtered ("%5d %s\n", history_base + offset, - (history_get (history_base + offset))->line); - } - - /* The next command we want to display is the next one that we haven't - displayed yet. */ - num += Hist_print; - - /* If the user repeats this command with return, it should do what - "show commands +" does. This is unnecessary if arg is null, - because "show commands +" is not useful after "show commands". */ - if (from_tty && args) - { - args[0] = '+'; - args[1] = '\0'; - } -} - -/* Called by do_setshow_command. */ -/* ARGSUSED */ -static void -set_history_size_command (args, from_tty, c) - char *args; - int from_tty; - struct cmd_list_element *c; -{ - if (history_size == INT_MAX) - unstifle_history (); - else if (history_size >= 0) - stifle_history (history_size); - else - { - history_size = INT_MAX; - error ("History size must be non-negative"); - } -} - -/* ARGSUSED */ -static void -set_history (args, from_tty) - char *args; - int from_tty; -{ - printf ("\"set history\" must be followed by the name of a history subcommand.\n"); - help_list (sethistlist, "set history ", -1, stdout); -} - -/* ARGSUSED */ -static void -show_history (args, from_tty) - char *args; - int from_tty; -{ - cmd_show_list (showhistlist, from_tty, ""); -} - -int info_verbose = 0; /* Default verbose msgs off */ - -/* Called by do_setshow_command. An elaborate joke. */ -/* ARGSUSED */ -static void -set_verbose (args, from_tty, c) - char *args; - int from_tty; - struct cmd_list_element *c; -{ - char *cmdname = "verbose"; - struct cmd_list_element *showcmd; - - showcmd = lookup_cmd_1 (&cmdname, showlist, NULL, 1); - - if (info_verbose) - { - c->doc = "Set verbose printing of informational messages."; - showcmd->doc = "Show verbose printing of informational messages."; - } - else - { - c->doc = "Set verbosity."; - showcmd->doc = "Show verbosity."; - } -} - -static void -float_handler (signo) -int signo; -{ - /* This message is based on ANSI C, section 4.7. Note that integer - divide by zero causes this, so "float" is a misnomer. */ - signal (SIGFPE, float_handler); - error ("Erroneous arithmetic operation."); -} - -/* Return whether we are running a batch file or from terminal. */ -int -batch_mode () -{ - return !(instream == stdin && ISATTY (stdin)); -} - - -static void -init_cmd_lists () -{ - cmdlist = NULL; - infolist = NULL; - enablelist = NULL; - disablelist = NULL; - deletelist = NULL; - enablebreaklist = NULL; - setlist = NULL; - unsetlist = NULL; - showlist = NULL; - sethistlist = NULL; - showhistlist = NULL; - unsethistlist = NULL; -#if MAINTENANCE_CMDS - maintenancelist = NULL; - maintenanceinfolist = NULL; - maintenanceprintlist = NULL; +#ifndef __GO32__ + return wait (status); #endif - setprintlist = NULL; - showprintlist = NULL; - setchecklist = NULL; - showchecklist = NULL; } -/* Init the history buffer. Note that we are called after the init file(s) - * have been read so that the user can change the history file via his - * .gdbinit file (for instance). The GDBHISTFILE environment variable - * overrides all of this. - */ - -static void -init_history() +void +proc_remove_foreign (pid) + int pid; { - char *tmpenv; - - tmpenv = getenv ("HISTSIZE"); - if (tmpenv) - history_size = atoi (tmpenv); - else if (!history_size) - history_size = 256; - - stifle_history (history_size); - - tmpenv = getenv ("GDBHISTFILE"); - if (tmpenv) - history_filename = savestring (tmpenv, strlen(tmpenv)); - else if (!history_filename) { - /* We include the current directory so that if the user changes - directories the file written will be the same as the one - that was read. */ - history_filename = concat (current_directory, "/.gdb_history", NULL); - } - read_history (history_filename); } -static void -init_main () +void +fputs_unfiltered (linebuffer, stream) + const char *linebuffer; + FILE *stream; { - struct cmd_list_element *c; - -#ifdef DEFAULT_PROMPT - prompt = savestring (DEFAULT_PROMPT, strlen(DEFAULT_PROMPT)); -#else - prompt = savestring ("(gdb) ", 6); -#endif - - /* Set the important stuff up for command editing. */ - command_editing_p = 1; - history_expansion_p = 0; - write_history_p = 0; - - /* Setup important stuff for command line editing. */ - rl_completion_entry_function = (int (*)()) symbol_completion_function; - rl_completer_word_break_characters = gdb_completer_word_break_characters; - rl_completer_quote_characters = gdb_completer_quote_characters; - rl_readline_name = "gdb"; - - /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ - - add_cmd ("internals", class_maintenance, NO_FUNCTION, - "Maintenance commands.\n\ -Some gdb commands are provided just for use by gdb maintainers.\n\ -These commands are subject to frequent change, and may not be as\n\ -well documented as user commands.", - &cmdlist); - add_cmd ("obscure", class_obscure, NO_FUNCTION, "Obscure features.", &cmdlist); - add_cmd ("aliases", class_alias, NO_FUNCTION, "Aliases of other commands.", &cmdlist); - add_cmd ("user-defined", class_user, NO_FUNCTION, "User-defined commands.\n\ -The commands in this class are those defined by the user.\n\ -Use the \"define\" command to define a command.", &cmdlist); - add_cmd ("support", class_support, NO_FUNCTION, "Support facilities.", &cmdlist); - add_cmd ("status", class_info, NO_FUNCTION, "Status inquiries.", &cmdlist); - add_cmd ("files", class_files, NO_FUNCTION, "Specifying and examining files.", &cmdlist); - add_cmd ("breakpoints", class_breakpoint, NO_FUNCTION, "Making program stop at certain points.", &cmdlist); - add_cmd ("data", class_vars, NO_FUNCTION, "Examining data.", &cmdlist); - add_cmd ("stack", class_stack, NO_FUNCTION, "Examining the stack.\n\ -The stack is made up of stack frames. Gdb assigns numbers to stack frames\n\ -counting from zero for the innermost (currently executing) frame.\n\n\ -At any time gdb identifies one frame as the \"selected\" frame.\n\ -Variable lookups are done with respect to the selected frame.\n\ -When the program being debugged stops, gdb selects the innermost frame.\n\ -The commands below can be used to select other frames by number or address.", - &cmdlist); - add_cmd ("running", class_run, NO_FUNCTION, "Running the program.", &cmdlist); - - add_com ("pwd", class_files, pwd_command, - "Print working directory. This is used for your program as well."); - c = add_cmd ("cd", class_files, cd_command, - "Set working directory to DIR for debugger and program being debugged.\n\ -The change does not take effect for the program being debugged\n\ -until the next time it is started.", &cmdlist); - c->completer = filename_completer; - - add_show_from_set - (add_set_cmd ("prompt", class_support, var_string, (char *)&prompt, - "Set gdb's prompt", - &setlist), - &showlist); - - add_com ("echo", class_support, echo_command, - "Print a constant string. Give string as argument.\n\ -C escape sequences may be used in the argument.\n\ -No newline is added at the end of the argument;\n\ -use \"\\n\" if you want a newline to be printed.\n\ -Since leading and trailing whitespace are ignored in command arguments,\n\ -if you want to print some you must use \"\\\" before leading whitespace\n\ -to be printed or after trailing whitespace."); - add_com ("document", class_support, document_command, - "Document a user-defined command.\n\ -Give command name as argument. Give documentation on following lines.\n\ -End with a line of just \"end\"."); - add_com ("define", class_support, define_command, - "Define a new command name. Command name is argument.\n\ -Definition appears on following lines, one command per line.\n\ -End with a line of just \"end\".\n\ -Use the \"document\" command to give documentation for the new command.\n\ -Commands defined in this way do not take arguments."); - -#ifdef __STDC__ - c = add_cmd ("source", class_support, source_command, - "Read commands from a file named FILE.\n\ -Note that the file \"" GDBINIT_FILENAME "\" is read automatically in this way\n\ -when gdb is started.", &cmdlist); -#else - /* Punt file name, we can't help it easily. */ - c = add_cmd ("source", class_support, source_command, - "Read commands from a file named FILE.\n\ -Note that the file \".gdbinit\" is read automatically in this way\n\ -when gdb is started.", &cmdlist); -#endif - c->completer = filename_completer; - - add_com ("quit", class_support, quit_command, "Exit gdb."); - add_com ("help", class_support, help_command, "Print list of commands."); - add_com_alias ("q", "quit", class_support, 1); - add_com_alias ("h", "help", class_support, 1); - - - c = add_set_cmd ("verbose", class_support, var_boolean, (char *)&info_verbose, - "Set ", - &setlist), - add_show_from_set (c, &showlist); - c->function.sfunc = set_verbose; - set_verbose (NULL, 0, c); - - add_show_from_set - (add_set_cmd ("editing", class_support, var_boolean, (char *)&command_editing_p, - "Set editing of command lines as they are typed.\n\ -Use \"on\" to enable to enable the editing, and \"off\" to disable it.\n\ -Without an argument, command line editing is enabled. To edit, use\n\ -EMACS-like or VI-like commands like control-P or ESC.", &setlist), - &showlist); - - add_prefix_cmd ("history", class_support, set_history, - "Generic command for setting command history parameters.", - &sethistlist, "set history ", 0, &setlist); - add_prefix_cmd ("history", class_support, show_history, - "Generic command for showing command history parameters.", - &showhistlist, "show history ", 0, &showlist); - - add_show_from_set - (add_set_cmd ("expansion", no_class, var_boolean, (char *)&history_expansion_p, - "Set history expansion on command input.\n\ -Without an argument, history expansion is enabled.", &sethistlist), - &showhistlist); - - add_show_from_set - (add_set_cmd ("save", no_class, var_boolean, (char *)&write_history_p, - "Set saving of the history record on exit.\n\ -Use \"on\" to enable to enable the saving, and \"off\" to disable it.\n\ -Without an argument, saving is enabled.", &sethistlist), - &showhistlist); - - c = add_set_cmd ("size", no_class, var_integer, (char *)&history_size, - "Set the size of the command history, \n\ -ie. the number of previous commands to keep a record of.", &sethistlist); - add_show_from_set (c, &showhistlist); - c->function.sfunc = set_history_size_command; - - add_show_from_set - (add_set_cmd ("filename", no_class, var_filename, (char *)&history_filename, - "Set the filename in which to record the command history\n\ - (the list of previous commands of which a record is kept).", &sethistlist), - &showhistlist); - - add_show_from_set - (add_set_cmd ("confirm", class_support, var_boolean, - (char *)&caution, - "Set whether to confirm potentially dangerous operations.", - &setlist), - &showlist); - - add_prefix_cmd ("info", class_info, info_command, - "Generic command for showing things about the program being debugged.", - &infolist, "info ", 0, &cmdlist); - add_com_alias ("i", "info", class_info, 1); - - add_prefix_cmd ("show", class_info, show_command, - "Generic command for showing things about the debugger.", - &showlist, "show ", 0, &cmdlist); - /* Another way to get at the same thing. */ - add_info ("set", show_command, "Show all GDB settings."); - - add_cmd ("commands", no_class, show_commands, - "Show the the history of commands you typed.\n\ -You can supply a command number to start with, or a `+' to start after\n\ -the previous command number shown.", - &showlist); - - add_cmd ("version", no_class, show_version, - "Show what version of GDB this is.", &showlist); - - add_show_from_set ( - add_set_cmd ("remotedebug", no_class, var_boolean, (char *)&remote_debug, - "Set debugging of remote protocol.\n\ -When enabled, each packet sent or received with the remote target\n\ -is displayed.", &setlist), - &showlist); + fputs (linebuffer, stream); } diff --git a/gnu/usr.bin/gdb/gdb/maint.c b/gnu/usr.bin/gdb/gdb/maint.c index b5334512ab48..ce3950664a54 100644 --- a/gnu/usr.bin/gdb/gdb/maint.c +++ b/gnu/usr.bin/gdb/gdb/maint.c @@ -1,5 +1,5 @@ /* Support for GDB maintenance commands. - Copyright (C) 1992 Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. This file is part of GDB. @@ -30,6 +30,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gdbtypes.h" #include "demangle.h" #include "gdbcore.h" +#include "expression.h" /* For language.h */ +#include "language.h" static void maintenance_command PARAMS ((char *, int)); @@ -59,8 +61,8 @@ maintenance_command (args, from_tty) char *args; int from_tty; { - printf ("\"maintenance\" must be followed by the name of a maintenance command.\n"); - help_list (maintenancelist, "maintenance ", -1, stdout); + printf_unfiltered ("\"maintenance\" must be followed by the name of a maintenance command.\n"); + help_list (maintenancelist, "maintenance ", -1, gdb_stdout); } @@ -94,19 +96,19 @@ maintenance_demangle (args, from_tty) if (args == NULL || *args == '\0') { - printf ("\"maintenance demangle\" takes an argument to demangle.\n"); + printf_unfiltered ("\"maintenance demangle\" takes an argument to demangle.\n"); } else { demangled = cplus_demangle (args, DMGL_ANSI | DMGL_PARAMS); if (demangled != NULL) { - printf ("%s\n", demangled); + printf_unfiltered ("%s\n", demangled); free (demangled); } else { - printf ("Can't demangle \"%s\"\n", args); + printf_unfiltered ("Can't demangle \"%s\"\n", args); } } } @@ -121,8 +123,8 @@ maintenance_info_command (arg, from_tty) char *arg; int from_tty; { - printf ("\"maintenance info\" must be followed by the name of an info command.\n"); - help_list (maintenanceinfolist, "maintenance info ", -1, stdout); + printf_unfiltered ("\"maintenance info\" must be followed by the name of an info command.\n"); + help_list (maintenanceinfolist, "maintenance info ", -1, gdb_stdout); } static void @@ -135,6 +137,7 @@ print_section_table (abfd, asect, ignore) flags = bfd_get_section_flags (abfd, asect); + /* FIXME-32x64: Need print_address_numeric with field width. */ printf_filtered (" %s", local_hex_string_custom ((unsigned long) bfd_section_vma (abfd, asect), "08l")); @@ -168,8 +171,8 @@ print_section_table (abfd, asect, ignore) printf_filtered (" HAS_CONTENTS"); if (flags & SEC_NEVER_LOAD) printf_filtered (" NEVER_LOAD"); - if (flags & SEC_SHARED_LIBRARY) - printf_filtered (" SHARED_LIBRARY"); + if (flags & SEC_COFF_SHARED_LIBRARY) + printf_filtered (" COFF_SHARED_LIBRARY"); if (flags & SEC_IS_COMMON) printf_filtered (" IS_COMMON"); @@ -211,31 +214,16 @@ maintenance_print_command (arg, from_tty) char *arg; int from_tty; { - printf ("\"maintenance print\" must be followed by the name of a print command.\n"); - help_list (maintenanceprintlist, "maintenance print ", -1, stdout); + printf_unfiltered ("\"maintenance print\" must be followed by the name of a print command.\n"); + help_list (maintenanceprintlist, "maintenance print ", -1, gdb_stdout); } -/* - -GLOBAL FUNCTION - - _initialize_maint_cmds -- initialize the process file system stuff - -SYNOPSIS - - void _initialize_maint_cmds (void) - -DESCRIPTION - - Do required initializations during gdb startup for using the - /proc file system interface. - -*/ - +#endif /* MAINTENANCE_CMDS */ void _initialize_maint_cmds () { +#if MAINTENANCE_CMDS /* Entire file goes away if not including maint cmds */ add_prefix_cmd ("maintenance", class_maintenance, maintenance_command, "Commands for use by GDB maintainers.\n\ Includes commands to dump specific internal GDB structures in\n\ @@ -300,6 +288,8 @@ If a SOURCE file is specified, dump only that file's partial symbols.", "Print dump of current object file definitions.", &maintenanceprintlist); -} - + add_cmd ("check-symtabs", class_maintenance, maintenance_check_symtabs, + "Check consistency of psymtabs and symtabs.", + &maintenancelist); #endif /* MAINTENANCE_CMDS */ +} diff --git a/gnu/usr.bin/gdb/gdb/minsyms.c b/gnu/usr.bin/gdb/gdb/minsyms.c index dbb4e797d970..fde97e9e6cfb 100644 --- a/gnu/usr.bin/gdb/gdb/minsyms.c +++ b/gnu/usr.bin/gdb/gdb/minsyms.c @@ -1,5 +1,5 @@ /* GDB routines for manipulating the minimal symbol tables. - Copyright 1992 Free Software Foundation, Inc. + Copyright 1992, 1993, 1994 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. This file is part of GDB. @@ -38,11 +38,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" +#include #include "symtab.h" #include "bfd.h" #include "symfile.h" #include "objfiles.h" #include "demangle.h" +#include "gdb-stabs.h" /* Accumulate the minimal symbols for each objfile in bunches of BUNCH_SIZE. At the end, copy them all into one newly allocated location on an objfile's @@ -96,9 +98,7 @@ lookup_minimal_symbol (name, objf) struct minimal_symbol *msymbol; struct minimal_symbol *found_symbol = NULL; struct minimal_symbol *found_file_symbol = NULL; -#ifdef IBM6000_TARGET struct minimal_symbol *trampoline_symbol = NULL; -#endif for (objfile = object_files; objfile != NULL && found_symbol == NULL; @@ -124,34 +124,17 @@ lookup_minimal_symbol (name, objf) found_file_symbol = msymbol; break; - case mst_unknown: -#ifdef IBM6000_TARGET - /* I *think* all platforms using shared - libraries (and trampoline code) will suffer - this problem. Consider a case where there are - 5 shared libraries, each referencing `foo' - with a trampoline entry. When someone wants - to put a breakpoint on `foo' and the only - info we have is minimal symbol vector, we - want to use the real `foo', rather than one - of those trampoline entries. MGO */ + case mst_solib_trampoline: /* If a trampoline symbol is found, we prefer to keep looking for the *real* symbol. If the - actual symbol not found, then we'll use the - trampoline entry. Sorry for the machine - dependent code here, but I hope this will - benefit other platforms as well. For - trampoline entries, we used mst_unknown - earlier. Perhaps we should define a - `mst_trampoline' type?? */ - + actual symbol is not found, then we'll use the + trampoline entry. */ if (trampoline_symbol == NULL) trampoline_symbol = msymbol; break; -#else - /* FALLTHROUGH */ -#endif + + case mst_unknown: default: found_symbol = msymbol; break; @@ -168,11 +151,9 @@ lookup_minimal_symbol (name, objf) if (found_file_symbol) return found_file_symbol; - /* Symbols for IBM shared library trampolines are next best. */ -#ifdef IBM6000_TARGET + /* Symbols for shared library trampolines are next best. */ if (trampoline_symbol) return trampoline_symbol; -#endif return NULL; } @@ -292,47 +273,71 @@ init_minimal_symbol_collection () } void -prim_record_minimal_symbol (name, address, ms_type) +prim_record_minimal_symbol (name, address, ms_type, objfile) const char *name; CORE_ADDR address; enum minimal_symbol_type ms_type; + struct objfile *objfile; { - register struct msym_bunch *new; - register struct minimal_symbol *msymbol; + int section; - if (msym_bunch_index == BUNCH_SIZE) + switch (ms_type) { - new = (struct msym_bunch *) xmalloc (sizeof (struct msym_bunch)); - msym_bunch_index = 0; - new -> next = msym_bunch; - msym_bunch = new; + case mst_text: + case mst_file_text: + case mst_solib_trampoline: + section = SECT_OFF_TEXT; + break; + case mst_data: + case mst_file_data: + section = SECT_OFF_DATA; + break; + case mst_bss: + case mst_file_bss: + section = SECT_OFF_BSS; + break; + default: + section = -1; } - msymbol = &msym_bunch -> contents[msym_bunch_index]; - SYMBOL_NAME (msymbol) = (char *) name; - SYMBOL_INIT_LANGUAGE_SPECIFIC (msymbol, language_unknown); - SYMBOL_VALUE_ADDRESS (msymbol) = address; - SYMBOL_SECTION (msymbol) = -1; - MSYMBOL_TYPE (msymbol) = ms_type; - /* FIXME: This info, if it remains, needs its own field. */ - MSYMBOL_INFO (msymbol) = NULL; /* FIXME! */ - msym_bunch_index++; - msym_count++; + + prim_record_minimal_symbol_and_info (name, address, ms_type, + NULL, section, objfile); } -/* FIXME: Why don't we just combine this function with the one above - and pass it a NULL info pointer value if info is not needed? */ - void -prim_record_minimal_symbol_and_info (name, address, ms_type, info, section) +prim_record_minimal_symbol_and_info (name, address, ms_type, info, section, + objfile) const char *name; CORE_ADDR address; enum minimal_symbol_type ms_type; char *info; int section; + struct objfile *objfile; { register struct msym_bunch *new; register struct minimal_symbol *msymbol; + if (ms_type == mst_file_text) + { + /* Don't put gcc_compiled, __gnu_compiled_cplus, and friends into + the minimal symbols, because if there is also another symbol + at the same address (e.g. the first function of the file), + lookup_minimal_symbol_by_pc would have no way of getting the + right one. */ + if (name[0] == 'g' + && (strcmp (name, GCC_COMPILED_FLAG_SYMBOL) == 0 + || strcmp (name, GCC2_COMPILED_FLAG_SYMBOL) == 0)) + return; + + { + const char *tempstring = name; + if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd)) + ++tempstring; + if (STREQN (tempstring, "__gnu_compiled", 14)) + return; + } + } + if (msym_bunch_index == BUNCH_SIZE) { new = (struct msym_bunch *) xmalloc (sizeof (struct msym_bunch)); @@ -345,6 +350,7 @@ prim_record_minimal_symbol_and_info (name, address, ms_type, info, section) SYMBOL_INIT_LANGUAGE_SPECIFIC (msymbol, language_unknown); SYMBOL_VALUE_ADDRESS (msymbol) = address; SYMBOL_SECTION (msymbol) = section; + MSYMBOL_TYPE (msymbol) = ms_type; /* FIXME: This info, if it remains, needs its own field. */ MSYMBOL_INFO (msymbol) = info; /* FIXME! */ @@ -595,3 +601,48 @@ install_minimal_symbols (objfile) } } +/* Check if PC is in a shared library trampoline code stub. + Return minimal symbol for the trampoline entry or NULL if PC is not + in a trampoline code stub. */ + +struct minimal_symbol * +lookup_solib_trampoline_symbol_by_pc (pc) + CORE_ADDR pc; +{ + struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc); + + if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_solib_trampoline) + return msymbol; + return NULL; +} + +/* If PC is in a shared library trampoline code stub, return the + address of the `real' function belonging to the stub. + Return 0 if PC is not in a trampoline code stub or if the real + function is not found in the minimal symbol table. + + We may fail to find the right function if a function with the + same name is defined in more than one shared library, but this + is considered bad programming style. We could return 0 if we find + a duplicate function in case this matters someday. */ + +CORE_ADDR +find_solib_trampoline_target (pc) + CORE_ADDR pc; +{ + struct objfile *objfile; + struct minimal_symbol *msymbol; + struct minimal_symbol *tsymbol = lookup_solib_trampoline_symbol_by_pc (pc); + + if (tsymbol != NULL) + { + ALL_MSYMBOLS (objfile, msymbol) + { + if (MSYMBOL_TYPE (msymbol) == mst_text + && STREQ (SYMBOL_NAME (msymbol), SYMBOL_NAME (tsymbol))) + return SYMBOL_VALUE_ADDRESS (msymbol); + } + } + return 0; +} + diff --git a/gnu/usr.bin/gdb/gdb/mipsread.c b/gnu/usr.bin/gdb/gdb/mipsread.c index 199092bb5c39..8c45a949515b 100644 --- a/gnu/usr.bin/gdb/gdb/mipsread.c +++ b/gnu/usr.bin/gdb/gdb/mipsread.c @@ -1,6 +1,6 @@ /* Read a symbol table in MIPS' format (Third-Eye). - Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993 Free Software - Foundation, Inc. + Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU. Major work by Per Bothner, John Gilmore and Ian Lance Taylor at Cygnus Support. @@ -20,356 +20,52 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* This module provides three functions: mipscoff_symfile_init, - which initializes to read a symbol file; mipscoff_new_init, which - discards existing cached information when all symbols are being - discarded; and mipscoff_symfile_read, which reads a symbol table - from a file. - - mipscoff_symfile_read only does the minimum work necessary for letting the - user "name" things symbolically; it does not read the entire symtab. - Instead, it reads the external and static symbols and puts them in partial - symbol tables. When more extensive information is requested of a - file, the corresponding partial symbol table is mutated into a full - fledged symbol table by going back and reading the symbols - for real. mipscoff_psymtab_to_symtab() is called indirectly through - a pointer in the psymtab to do this. - - ECOFF symbol tables are mostly written in the byte order of the - target machine. However, one section of the table (the auxiliary - symbol information) is written in the host byte order. There is a - bit in the other symbol info which describes which host byte order - was used. ECOFF thereby takes the trophy from Intel `b.out' for - the most brain-dead adaptation of a file format to byte order. - - This module can read all four of the known byte-order combinations, - on any type of host. */ +/* Read symbols from an ECOFF file. Most of the work is done in + mdebugread.c. */ #include "defs.h" +#include +#include "bfd.h" #include "symtab.h" -#include "gdbtypes.h" -#include "gdbcore.h" #include "symfile.h" #include "objfiles.h" -#include "obstack.h" #include "buildsym.h" #include "stabsread.h" -#include "complaints.h" - -/* These are needed if the tm.h file does not contain the necessary - mips specific definitions. */ - -#ifndef MIPS_EFI_SYMBOL_NAME -#define MIPS_EFI_SYMBOL_NAME "__GDB_EFI_INFO__" -#include "coff/sym.h" -#include "coff/symconst.h" -typedef struct mips_extra_func_info { - long numargs; - PDR pdr; -} *mips_extra_func_info_t; -#ifndef RA_REGNUM -#define RA_REGNUM 0 -#endif -#endif - -#ifdef USG -#include -#endif - -#include -#include -#include -#include - #include "gdb-stabs.h" -#include "bfd.h" - +#include "coff/sym.h" #include "coff/internal.h" -#include "coff/ecoff.h" /* COFF-like aspects of ecoff files */ - -/* FIXME: coff/internal.h and aout/aout64.h both define N_ABS. We - want the definition from aout/aout64.h. */ -#undef N_ABS - -#include "libaout.h" /* Private BFD a.out information. */ -#include "aout/aout64.h" -#include "aout/stab_gnu.h" /* STABS information */ - -/* FIXME: libcoff.h and libaout.h both define a couple of macros. We - don't use them. */ -#undef exec_hdr -#undef obj_sym_filepos - +#include "coff/ecoff.h" #include "libcoff.h" /* Private BFD COFF information. */ #include "libecoff.h" /* Private BFD ECOFF information. */ - -#include "expression.h" -#include "language.h" /* Needed inside partial-stab.h */ - -/* Provide a default mapping from a ecoff register number to a gdb REGNUM. */ -#ifndef ECOFF_REG_TO_REGNUM -#define ECOFF_REG_TO_REGNUM(num) (num) -#endif - -/* Information is passed among various mipsread routines for accessing - symbol files. A pointer to this structure is kept in the sym_private - field of the objfile struct. */ - -struct ecoff_symfile_info { - struct mips_pending **pending_list; -}; -#define ECOFF_SYMFILE_INFO(o) ((struct ecoff_symfile_info *)((o)->sym_private)) -#define ECOFF_PENDING_LIST(o) (ECOFF_SYMFILE_INFO(o)->pending_list) - - -/* Each partial symbol table entry contains a pointer to private data - for the read_symtab() function to use when expanding a partial - symbol table entry to a full symbol table entry. - - For mipsread this structure contains the index of the FDR that this - psymtab represents and a pointer to the BFD that the psymtab was - created from. */ - -#define PST_PRIVATE(p) ((struct symloc *)(p)->read_symtab_private) -#define FDR_IDX(p) (PST_PRIVATE(p)->fdr_idx) -#define CUR_BFD(p) (PST_PRIVATE(p)->cur_bfd) - -struct symloc -{ - int fdr_idx; - bfd *cur_bfd; - EXTR *extern_tab; /* Pointer to external symbols for this file. */ - int extern_count; /* Size of extern_tab. */ - enum language pst_language; -}; - -/* Things we import explicitly from other modules */ - -extern int info_verbose; - -/* Various complaints about symbol reading that don't abort the process */ - -struct complaint bad_file_number_complaint = -{"bad file number %d", 0, 0}; - -struct complaint index_complaint = -{"bad aux index at symbol %s", 0, 0}; - -struct complaint aux_index_complaint = -{"bad proc end in aux found from symbol %s", 0, 0}; - -struct complaint block_index_complaint = -{"bad aux index at block symbol %s", 0, 0}; - -struct complaint unknown_ext_complaint = -{"unknown external symbol %s", 0, 0}; - -struct complaint unknown_sym_complaint = -{"unknown local symbol %s", 0, 0}; - -struct complaint unknown_st_complaint = -{"with type %d", 0, 0}; - -struct complaint block_overflow_complaint = -{"block containing %s overfilled", 0, 0}; - -struct complaint basic_type_complaint = -{"cannot map MIPS basic type 0x%x for %s", 0, 0}; - -struct complaint unknown_type_qual_complaint = -{"unknown type qualifier 0x%x", 0, 0}; - -struct complaint array_index_type_complaint = -{"illegal array index type for %s, assuming int", 0, 0}; - -struct complaint bad_tag_guess_complaint = -{"guessed tag type of %s incorrectly", 0, 0}; - -struct complaint block_member_complaint = -{"declaration block contains unhandled symbol type %d", 0, 0}; - -struct complaint stEnd_complaint = -{"stEnd with storage class %d not handled", 0, 0}; - -struct complaint unknown_mips_symtype_complaint = -{"unknown symbol type 0x%x", 0, 0}; - -struct complaint stab_unknown_complaint = -{"unknown stabs symbol %s", 0, 0}; - -struct complaint pdr_for_nonsymbol_complaint = -{"PDR for %s, but no symbol", 0, 0}; - -struct complaint pdr_static_symbol_complaint = -{"can't handle PDR for static proc at 0x%lx", 0, 0}; - -struct complaint bad_setjmp_pdr_complaint = -{"fixing bad setjmp PDR from libc", 0, 0}; - -struct complaint bad_fbitfield_complaint = -{"can't handle TIR fBitfield for %s", 0, 0}; - -struct complaint bad_continued_complaint = -{"illegal TIR continued for %s", 0, 0}; - -struct complaint bad_rfd_entry_complaint = -{"bad rfd entry for %s: file %d, index %d", 0, 0}; - -struct complaint unexpected_type_code_complaint = -{"unexpected type code for %s", 0, 0}; - -struct complaint unable_to_cross_ref_complaint = -{"unable to cross ref btTypedef for %s", 0, 0}; - -struct complaint illegal_forward_tq0_complaint = -{"illegal tq0 in forward typedef for %s", 0, 0}; - -struct complaint illegal_forward_bt_complaint = -{"illegal bt %d in forward typedef for %s", 0, 0}; - -struct complaint bad_linetable_guess_complaint = -{"guessed size of linetable for %s incorrectly", 0, 0}; - -/* Macros and extra defs */ - -/* Puns: hard to find whether -g was used and how */ - -#define MIN_GLEVEL GLEVEL_0 -#define compare_glevel(a,b) \ - (((a) == GLEVEL_3) ? ((b) < GLEVEL_3) : \ - ((b) == GLEVEL_3) ? -1 : (int)((b) - (a))) - -/* Things that really are local to this module */ - -/* Remember what we deduced to be the source language of this psymtab. */ - -static enum language psymtab_language = language_unknown; - -/* Current BFD. */ - -static bfd *cur_bfd; - -/* Pointer to current file decriptor record, and its index */ - -static FDR *cur_fdr; -static int cur_fd; - -/* Index of current symbol */ - -static int cur_sdx; - -/* Note how much "debuggable" this image is. We would like - to see at least one FDR with full symbols */ - -static max_gdbinfo; -static max_glevel; - -/* When examining .o files, report on undefined symbols */ - -static int n_undef_symbols, n_undef_labels, n_undef_vars, n_undef_procs; - -/* Pseudo symbol to use when putting stabs into the symbol table. */ - -static char stabs_symbol[] = STABS_SYMBOL; - -/* Extra builtin types */ - -struct type *builtin_type_complex; -struct type *builtin_type_double_complex; -struct type *builtin_type_fixed_dec; -struct type *builtin_type_float_dec; -struct type *builtin_type_string; - -/* Forward declarations */ +#include "elf/common.h" +#include "elf/mips.h" static void -read_mips_symtab PARAMS ((struct objfile *, struct section_offsets *)); +mipscoff_new_init PARAMS ((struct objfile *)); static void -read_the_mips_symtab PARAMS ((bfd *)); - -static int -upgrade_type PARAMS ((int, struct type **, int, union aux_ext *, int, char *)); +mipscoff_symfile_init PARAMS ((struct objfile *)); static void -parse_partial_symbols PARAMS ((struct objfile *, - struct section_offsets *)); - -static int -cross_ref PARAMS ((int, union aux_ext *, struct type **, enum type_code, - char **, int, char *)); +mipscoff_symfile_read PARAMS ((struct objfile *, struct section_offsets *, + int)); static void -fixup_sigtramp PARAMS ((void)); +mipscoff_symfile_finish PARAMS ((struct objfile *)); -static struct symbol * -new_symbol PARAMS ((char *)); - -static struct type * -new_type PARAMS ((char *)); - -static struct block * -new_block PARAMS ((int)); - -static struct symtab * -new_symtab PARAMS ((char *, int, int, struct objfile *)); - -static struct linetable * -new_linetable PARAMS ((int)); - -static struct blockvector * -new_bvect PARAMS ((int)); - -static int -parse_symbol PARAMS ((SYMR *, union aux_ext *, char *, int)); - -static struct type * -parse_type PARAMS ((int, union aux_ext *, unsigned int, int *, int, char *)); - -static struct symbol * -mylookup_symbol PARAMS ((char *, struct block *, enum namespace, - enum address_class)); - -static struct block * -shrink_block PARAMS ((struct block *, struct symtab *)); - -static PTR -xzalloc PARAMS ((unsigned int)); +static struct section_offsets * +mipscoff_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR)); static void -sort_blocks PARAMS ((struct symtab *)); +read_alphacoff_dynamic_symtab PARAMS ((struct section_offsets *, + struct objfile *objfile)); -static int -compare_blocks PARAMS ((const void *, const void *)); +/* Initialize anything that needs initializing when a completely new + symbol file is specified (not just adding some symbols from another + file, e.g. a shared library). */ -static struct partial_symtab * -new_psymtab PARAMS ((char *, struct objfile *)); - -static void -psymtab_to_symtab_1 PARAMS ((struct partial_symtab *, char *)); - -static void -add_block PARAMS ((struct block *, struct symtab *)); - -static void -add_symbol PARAMS ((struct symbol *, struct block *)); - -static int -add_line PARAMS ((struct linetable *, int, CORE_ADDR, int)); - -static struct linetable * -shrink_linetable PARAMS ((struct linetable *)); - -static char * -mips_next_symbol_text PARAMS ((void)); - -/* Things we export to other modules */ - -/* Address bounds for the signal trampoline in inferior, if any */ -/* FIXME: Nothing really seems to use this. Why is it here? */ - -CORE_ADDR sigtramp_address, sigtramp_end; +extern CORE_ADDR sigtramp_address; static void mipscoff_new_init (ignore) @@ -380,24 +76,23 @@ mipscoff_new_init (ignore) buildsym_new_init (); } +/* Initialize to read a symbol file (nothing to do). */ + static void mipscoff_symfile_init (objfile) struct objfile *objfile; { - if (objfile->sym_private != NULL) - { - mfree (objfile->md, objfile->sym_private); - } - objfile->sym_private = (PTR) - xmmalloc (objfile->md, sizeof (struct ecoff_symfile_info)); } +/* Read a symbol file from a file. */ + static void mipscoff_symfile_read (objfile, section_offsets, mainline) struct objfile *objfile; struct section_offsets *section_offsets; int mainline; { + bfd *abfd = objfile->obfd; struct cleanup * back_to; init_minimal_symbol_collection (); @@ -406,7 +101,17 @@ mipscoff_symfile_read (objfile, section_offsets, mainline) /* Now that the executable file is positioned at symbol table, process it and define symbols accordingly. */ - read_mips_symtab (objfile, section_offsets); + if (!((*ecoff_backend (abfd)->debug_swap.read_debug_info) + (abfd, (asection *) NULL, &ecoff_data (abfd)->debug_info))) + error ("Error reading symbol table: %s", bfd_errmsg (bfd_get_error ())); + + mdebug_build_psymtabs (objfile, &ecoff_backend (abfd)->debug_swap, + &ecoff_data (abfd)->debug_info, section_offsets); + + /* Add the dynamic symbols if we are reading the main symbol table. */ + + if (mainline) + read_alphacoff_dynamic_symtab (section_offsets, objfile); /* Install any minimal symbols that have been collected as the current minimal symbols for this objfile. */ @@ -416,3174 +121,18 @@ mipscoff_symfile_read (objfile, section_offsets, mainline) do_cleanups (back_to); } -/* Perform any local cleanups required when we are done with a particular - objfile. I.E, we are in the process of discarding all symbol information - for an objfile, freeing up all memory held for it, and unlinking the - objfile struct from the global list of known objfiles. */ +/* Perform any local cleanups required when we are done with a + particular objfile. */ static void mipscoff_symfile_finish (objfile) struct objfile *objfile; { - if (objfile->sym_private != NULL) - { - mfree (objfile->md, objfile->sym_private); - } - - cur_bfd = 0; } -/* Allocate zeroed memory */ - -static PTR -xzalloc (size) - unsigned int size; -{ - PTR p = xmalloc (size); - - memset (p, 0, size); - return p; -} - -/* Exported procedure: Builds a symtab from the PST partial one. - Restores the environment in effect when PST was created, delegates - most of the work to an ancillary procedure, and sorts - and reorders the symtab list at the end */ - -static void -mipscoff_psymtab_to_symtab (pst) - struct partial_symtab *pst; -{ - - if (!pst) - return; - - if (info_verbose) - { - printf_filtered ("Reading in symbols for %s...", pst->filename); - fflush (stdout); - } - - next_symbol_text_func = mips_next_symbol_text; - - psymtab_to_symtab_1 (pst, pst->filename); - - /* Match with global symbols. This only needs to be done once, - after all of the symtabs and dependencies have been read in. */ - scan_file_globals (pst->objfile); - - if (info_verbose) - printf_filtered ("done.\n"); -} - -/* Exported procedure: Is PC in the signal trampoline code */ - -int -in_sigtramp (pc, ignore) - CORE_ADDR pc; - char *ignore; /* function name */ -{ - if (sigtramp_address == 0) - fixup_sigtramp (); - return (pc >= sigtramp_address && pc < sigtramp_end); -} - -/* File-level interface functions */ - -/* Read the symtab information from file ABFD into memory. */ - -static void -read_the_mips_symtab (abfd) - bfd *abfd; -{ - if (ecoff_slurp_symbolic_info (abfd) == false) - error ("Error reading symbol table: %s", bfd_errmsg (bfd_error)); -} - -/* Find a file descriptor given its index RF relative to a file CF */ - -static FDR * -get_rfd (cf, rf) - int cf, rf; -{ - FDR *fdrs; - register FDR *f; - RFDT rfd; - - fdrs = ecoff_data (cur_bfd)->fdr; - f = fdrs + cf; - /* Object files do not have the RFD table, all refs are absolute */ - if (f->rfdBase == 0) - return fdrs + rf; - (*ecoff_backend (cur_bfd)->swap_rfd_in) - (cur_bfd, - ((char *) ecoff_data (cur_bfd)->external_rfd - + (f->rfdBase + rf) * ecoff_backend (cur_bfd)->external_rfd_size), - &rfd); - return fdrs + rfd; -} - -/* Return a safer print NAME for a file descriptor */ - -static char * -fdr_name (f) - FDR *f; -{ - if (f->rss == -1) - return ""; - if (f->rss == 0) - return ""; - return ecoff_data (cur_bfd)->ss + f->issBase + f->rss; -} - - -/* Read in and parse the symtab of the file OBJFILE. Symbols from - different sections are relocated via the SECTION_OFFSETS. */ - -static void -read_mips_symtab (objfile, section_offsets) - struct objfile *objfile; - struct section_offsets *section_offsets; -{ - cur_bfd = objfile->obfd; - - read_the_mips_symtab (objfile->obfd); - - parse_partial_symbols (objfile, section_offsets); - -#if 0 - /* Check to make sure file was compiled with -g. If not, warn the - user of this limitation. */ - if (compare_glevel (max_glevel, GLEVEL_2) < 0) - { - if (max_gdbinfo == 0) - printf ("\n%s not compiled with -g, debugging support is limited.\n", - objfile->name); - printf ("You should compile with -g2 or -g3 for best debugging support.\n"); - fflush (stdout); - } -#endif -} - -/* Local utilities */ - -/* Map of FDR indexes to partial symtabs */ - -struct pst_map -{ - struct partial_symtab *pst; /* the psymtab proper */ - long n_globals; /* exported globals (external symbols) */ - long globals_offset; /* cumulative */ -}; - - -/* Utility stack, used to nest procedures and blocks properly. - It is a doubly linked list, to avoid too many alloc/free. - Since we might need it quite a few times it is NOT deallocated - after use. */ - -static struct parse_stack -{ - struct parse_stack *next, *prev; - struct symtab *cur_st; /* Current symtab. */ - struct block *cur_block; /* Block in it. */ - int blocktype; /* What are we parsing. */ - int maxsyms; /* Max symbols in this block. */ - struct type *cur_type; /* Type we parse fields for. */ - int cur_field; /* Field number in cur_type. */ - CORE_ADDR procadr; /* Start addres of this procedure */ - int numargs; /* Its argument count */ -} - - *top_stack; /* Top stack ptr */ - - -/* Enter a new lexical context */ - -static void -push_parse_stack () -{ - struct parse_stack *new; - - /* Reuse frames if possible */ - if (top_stack && top_stack->prev) - new = top_stack->prev; - else - new = (struct parse_stack *) xzalloc (sizeof (struct parse_stack)); - /* Initialize new frame with previous content */ - if (top_stack) - { - register struct parse_stack *prev = new->prev; - - *new = *top_stack; - top_stack->prev = new; - new->prev = prev; - new->next = top_stack; - } - top_stack = new; -} - -/* Exit a lexical context */ - -static void -pop_parse_stack () -{ - if (!top_stack) - return; - if (top_stack->next) - top_stack = top_stack->next; -} - - -/* Cross-references might be to things we haven't looked at - yet, e.g. type references. To avoid too many type - duplications we keep a quick fixup table, an array - of lists of references indexed by file descriptor */ - -struct mips_pending -{ - struct mips_pending *next; /* link */ - char *s; /* the unswapped symbol */ - struct type *t; /* its partial type descriptor */ -}; - - -/* Check whether we already saw symbol SH in file FH */ - -static struct mips_pending * -is_pending_symbol (fh, sh) - FDR *fh; - char *sh; -{ - int f_idx = fh - ecoff_data (cur_bfd)->fdr; - register struct mips_pending *p; - struct mips_pending **pending_list = ECOFF_PENDING_LIST (current_objfile); - - /* Linear search is ok, list is typically no more than 10 deep */ - for (p = pending_list[f_idx]; p; p = p->next) - if (p->s == sh) - break; - return p; -} - -/* Add a new symbol SH of type T */ - -static void -add_pending (fh, sh, t) - FDR *fh; - char *sh; - struct type *t; -{ - int f_idx = fh - ecoff_data (cur_bfd)->fdr; - struct mips_pending *p = is_pending_symbol (fh, sh); - - /* Make sure we do not make duplicates */ - if (!p) - { - struct mips_pending **pending_list = ECOFF_PENDING_LIST (current_objfile); - - p = ((struct mips_pending *) - obstack_alloc (¤t_objfile->psymbol_obstack, - sizeof (struct mips_pending))); - p->s = sh; - p->t = t; - p->next = pending_list[f_idx]; - pending_list[f_idx] = p; - } -} - - -/* Parsing Routines proper. */ - -/* Parse a single symbol. Mostly just make up a GDB symbol for it. - For blocks, procedures and types we open a new lexical context. - This is basically just a big switch on the symbol's type. Argument - AX is the base pointer of aux symbols for this file (fh->iauxBase). - EXT_SH points to the unswapped symbol, which is needed for struct, - union, etc., types; it is NULL for an EXTR. BIGEND says whether - aux symbols are big-endian or little-endian. Return count of - SYMR's handled (normally one). */ - -static int -parse_symbol (sh, ax, ext_sh, bigend) - SYMR *sh; - union aux_ext *ax; - char *ext_sh; - int bigend; -{ - const bfd_size_type external_sym_size - = ecoff_backend (cur_bfd)->external_sym_size; - void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) = - ecoff_backend (cur_bfd)->swap_sym_in; - char *name; - struct symbol *s; - struct block *b; - struct mips_pending *pend; - struct type *t; - struct field *f; - int count = 1; - enum address_class class; - TIR tir; - long svalue = sh->value; - int bitsize; - - if (ext_sh == (char *) NULL) - name = ecoff_data (cur_bfd)->ssext + sh->iss; - else - name = ecoff_data (cur_bfd)->ss + cur_fdr->issBase + sh->iss; - - switch (sh->st) - { - case stNil: - break; - - case stGlobal: /* external symbol, goes into global block */ - class = LOC_STATIC; - b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (top_stack->cur_st), - GLOBAL_BLOCK); - s = new_symbol (name); - SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value; - goto data; - - case stStatic: /* static data, goes into current block. */ - class = LOC_STATIC; - b = top_stack->cur_block; - s = new_symbol (name); - if (sh->sc == scCommon) - { - /* It is a FORTRAN common block. At least for SGI Fortran the - address is not in the symbol; we need to fix it later in - scan_file_globals. */ - int bucket = hashname (SYMBOL_NAME (s)); - SYMBOL_VALUE_CHAIN (s) = global_sym_chain[bucket]; - global_sym_chain[bucket] = s; - } - else - SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value; - goto data; - - case stLocal: /* local variable, goes into current block */ - if (sh->sc == scRegister) - { - class = LOC_REGISTER; - svalue = ECOFF_REG_TO_REGNUM (svalue); - } - else - class = LOC_LOCAL; - b = top_stack->cur_block; - s = new_symbol (name); - SYMBOL_VALUE (s) = svalue; - - data: /* Common code for symbols describing data */ - SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; - SYMBOL_CLASS (s) = class; - add_symbol (s, b); - - /* Type could be missing in a number of cases */ - if (sh->sc == scUndefined || sh->sc == scNil || - sh->index == 0xfffff) - SYMBOL_TYPE (s) = builtin_type_int; /* undefined? */ - else - SYMBOL_TYPE (s) = parse_type (cur_fd, ax, sh->index, 0, bigend, name); - /* Value of a data symbol is its memory address */ - break; - - case stParam: /* arg to procedure, goes into current block */ - max_gdbinfo++; - top_stack->numargs++; - - /* Special GNU C++ name. */ - if (name[0] == CPLUS_MARKER && name[1] == 't' && name[2] == 0) - name = "this"; /* FIXME, not alloc'd in obstack */ - s = new_symbol (name); - - SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; - switch (sh->sc) - { - case scRegister: - /* Pass by value in register. */ - SYMBOL_CLASS(s) = LOC_REGPARM; - svalue = ECOFF_REG_TO_REGNUM (svalue); - break; - case scVar: - /* Pass by reference on stack. */ - SYMBOL_CLASS(s) = LOC_REF_ARG; - break; - case scVarRegister: - /* Pass by reference in register. */ - SYMBOL_CLASS(s) = LOC_REGPARM_ADDR; - svalue = ECOFF_REG_TO_REGNUM (svalue); - break; - default: - /* Pass by value on stack. */ - SYMBOL_CLASS(s) = LOC_ARG; - break; - } - SYMBOL_VALUE (s) = svalue; - SYMBOL_TYPE (s) = parse_type (cur_fd, ax, sh->index, 0, bigend, name); - add_symbol (s, top_stack->cur_block); -#if 0 - /* FIXME: This has not been tested. See dbxread.c */ - /* Add the type of this parameter to the function/procedure - type of this block. */ - add_param_to_type (&top_stack->cur_block->function->type, s); -#endif - break; - - case stLabel: /* label, goes into current block */ - s = new_symbol (name); - SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; /* so that it can be used */ - SYMBOL_CLASS (s) = LOC_LABEL; /* but not misused */ - SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value; - SYMBOL_TYPE (s) = builtin_type_int; - add_symbol (s, top_stack->cur_block); - break; - - case stProc: /* Procedure, usually goes into global block */ - case stStaticProc: /* Static procedure, goes into current block */ - s = new_symbol (name); - SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; - SYMBOL_CLASS (s) = LOC_BLOCK; - /* Type of the return value */ - if (sh->sc == scUndefined || sh->sc == scNil) - t = builtin_type_int; - else - t = parse_type (cur_fd, ax, sh->index + 1, 0, bigend, name); - b = top_stack->cur_block; - if (sh->st == stProc) - { - struct blockvector *bv = BLOCKVECTOR (top_stack->cur_st); - /* The next test should normally be true, - but provides a hook for nested functions - (which we don't want to make global). */ - if (b == BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) - b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); - } - add_symbol (s, b); - - /* Make a type for the procedure itself */ -#if 0 - /* FIXME: This has not been tested yet! See dbxread.c */ - /* Generate a template for the type of this function. The - types of the arguments will be added as we read the symbol - table. */ - memcpy (lookup_function_type (t), SYMBOL_TYPE (s), sizeof (struct type)); -#else - SYMBOL_TYPE (s) = lookup_function_type (t); -#endif - - /* Create and enter a new lexical context */ - b = new_block (top_stack->maxsyms); - SYMBOL_BLOCK_VALUE (s) = b; - BLOCK_FUNCTION (b) = s; - BLOCK_START (b) = BLOCK_END (b) = sh->value; - BLOCK_SUPERBLOCK (b) = top_stack->cur_block; - add_block (b, top_stack->cur_st); - - /* Not if we only have partial info */ - if (sh->sc == scUndefined || sh->sc == scNil) - break; - - push_parse_stack (); - top_stack->cur_block = b; - top_stack->blocktype = sh->st; - top_stack->cur_type = SYMBOL_TYPE (s); - top_stack->cur_field = -1; - top_stack->procadr = sh->value; - top_stack->numargs = 0; - break; - - /* Beginning of code for structure, union, and enum definitions. - They all share a common set of local variables, defined here. */ - { - enum type_code type_code; - char *ext_tsym; - int nfields; - long max_value; - struct field *f; - - case stStruct: /* Start a block defining a struct type */ - type_code = TYPE_CODE_STRUCT; - goto structured_common; - - case stUnion: /* Start a block defining a union type */ - type_code = TYPE_CODE_UNION; - goto structured_common; - - case stEnum: /* Start a block defining an enum type */ - type_code = TYPE_CODE_ENUM; - goto structured_common; - - case stBlock: /* Either a lexical block, or some type */ - if (sh->sc != scInfo && sh->sc != scCommon) - goto case_stBlock_code; /* Lexical block */ - - type_code = TYPE_CODE_UNDEF; /* We have a type. */ - - /* Common code for handling struct, union, enum, and/or as-yet- - unknown-type blocks of info about structured data. `type_code' - has been set to the proper TYPE_CODE, if we know it. */ - structured_common: - push_parse_stack (); - top_stack->blocktype = stBlock; - - /* First count the number of fields and the highest value. */ - nfields = 0; - max_value = 0; - for (ext_tsym = ext_sh + external_sym_size; - ; - ext_tsym += external_sym_size) - { - SYMR tsym; - - (*swap_sym_in) (cur_bfd, ext_tsym, &tsym); - - switch (tsym.st) - { - case stEnd: - goto end_of_fields; - - case stMember: - if (nfields == 0 && type_code == TYPE_CODE_UNDEF) - /* If the type of the member is Nil (or Void), - without qualifiers, assume the tag is an - enumeration. */ - if (tsym.index == indexNil) - type_code = TYPE_CODE_ENUM; - else - { - ecoff_swap_tir_in (bigend, - &ax[tsym.index].a_ti, - &tir); - if ((tir.bt == btNil || tir.bt == btVoid) - && tir.tq0 == tqNil) - type_code = TYPE_CODE_ENUM; - } - nfields++; - if (tsym.value > max_value) - max_value = tsym.value; - break; - - case stBlock: - case stUnion: - case stEnum: - case stStruct: - { -#if 0 - /* This is a no-op; is it trying to tell us something - we should be checking? */ - if (tsym.sc == scVariant); /*UNIMPLEMENTED*/ -#endif - if (tsym.index != 0) - { - /* This is something like a struct within a - struct. Skip over the fields of the inner - struct. The -1 is because the for loop will - increment ext_tsym. */ - ext_tsym = ((char *) ecoff_data (cur_bfd)->external_sym - + ((cur_fdr->isymBase + tsym.index - 1) - * external_sym_size)); - } - } - break; - - case stTypedef: - /* mips cc puts out a typedef for struct x if it is not yet - defined when it encounters - struct y { struct x *xp; }; - Just ignore it. */ - break; - - default: - complain (&block_member_complaint, tsym.st); - } - } - end_of_fields:; - - /* In an stBlock, there is no way to distinguish structs, - unions, and enums at this point. This is a bug in the - original design (that has been fixed with the recent - addition of the stStruct, stUnion, and stEnum symbol - types.) The way you can tell is if/when you see a variable - or field of that type. In that case the variable's type - (in the AUX table) says if the type is struct, union, or - enum, and points back to the stBlock here. So you can - patch the tag kind up later - but only if there actually is - a variable or field of that type. - - So until we know for sure, we will guess at this point. - The heuristic is: - If the first member has index==indexNil or a void type, - assume we have an enumeration. - Otherwise, if there is more than one member, and all - the members have offset 0, assume we have a union. - Otherwise, assume we have a struct. - - The heuristic could guess wrong in the case of of an - enumeration with no members or a union with one (or zero) - members, or when all except the last field of a struct have - width zero. These are uncommon and/or illegal situations, - and in any case guessing wrong probably doesn't matter - much. - - But if we later do find out we were wrong, we fixup the tag - kind. Members of an enumeration must be handled - differently from struct/union fields, and that is harder to - patch up, but luckily we shouldn't need to. (If there are - any enumeration members, we can tell for sure it's an enum - here.) */ - - if (type_code == TYPE_CODE_UNDEF) - if (nfields > 1 && max_value == 0) - type_code = TYPE_CODE_UNION; - else - type_code = TYPE_CODE_STRUCT; - - /* Create a new type or use the pending type. */ - pend = is_pending_symbol (cur_fdr, ext_sh); - if (pend == (struct mips_pending *) NULL) - { - t = new_type (NULL); - add_pending (cur_fdr, ext_sh, t); - } - else - t = pend->t; - - /* Alpha cc unnamed structs do not get a tag name. */ - if (sh->iss == 0) - TYPE_TAG_NAME (t) = NULL; - else - TYPE_TAG_NAME (t) = obconcat (¤t_objfile->symbol_obstack, - "", "", name); - - TYPE_CODE (t) = type_code; - TYPE_LENGTH (t) = sh->value; - TYPE_NFIELDS (t) = nfields; - TYPE_FIELDS (t) = f = ((struct field *) - TYPE_ALLOC (t, - nfields * sizeof (struct field))); - - if (type_code == TYPE_CODE_ENUM) - { - /* This is a non-empty enum. */ - for (ext_tsym = ext_sh + external_sym_size; - ; - ext_tsym += external_sym_size) - { - SYMR tsym; - struct symbol *enum_sym; - - (*swap_sym_in) (cur_bfd, ext_tsym, &tsym); - - if (tsym.st != stMember) - break; - - f->bitpos = tsym.value; - f->type = t; - f->name = (ecoff_data (cur_bfd)->ss - + cur_fdr->issBase - + tsym.iss); - f->bitsize = 0; - - enum_sym = ((struct symbol *) - obstack_alloc (¤t_objfile->symbol_obstack, - sizeof (struct symbol))); - memset ((PTR) enum_sym, 0, sizeof (struct symbol)); - SYMBOL_NAME (enum_sym) = f->name; - SYMBOL_CLASS (enum_sym) = LOC_CONST; - SYMBOL_TYPE (enum_sym) = t; - SYMBOL_NAMESPACE (enum_sym) = VAR_NAMESPACE; - SYMBOL_VALUE (enum_sym) = tsym.value; - add_symbol (enum_sym, top_stack->cur_block); - - /* Skip the stMembers that we've handled. */ - count++; - f++; - } - } - /* make this the current type */ - top_stack->cur_type = t; - top_stack->cur_field = 0; - - /* Do not create a symbol for alpha cc unnamed structs. */ - if (sh->iss == 0) - break; - s = new_symbol (name); - SYMBOL_NAMESPACE (s) = STRUCT_NAMESPACE; - SYMBOL_CLASS (s) = LOC_TYPEDEF; - SYMBOL_VALUE (s) = 0; - SYMBOL_TYPE (s) = t; - - /* gcc puts out an empty struct for an opaque struct definitions. */ - if (TYPE_NFIELDS (t) == 0) - { - TYPE_FLAGS (t) |= TYPE_FLAG_STUB; - SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; - } - add_symbol (s, top_stack->cur_block); - break; - - /* End of local variables shared by struct, union, enum, and - block (as yet unknown struct/union/enum) processing. */ - } - - case_stBlock_code: - /* beginnning of (code) block. Value of symbol - is the displacement from procedure start */ - push_parse_stack (); - top_stack->blocktype = stBlock; - b = new_block (top_stack->maxsyms); - BLOCK_START (b) = sh->value + top_stack->procadr; - BLOCK_SUPERBLOCK (b) = top_stack->cur_block; - top_stack->cur_block = b; - add_block (b, top_stack->cur_st); - break; - - case stEnd: /* end (of anything) */ - if (sh->sc == scInfo || sh->sc == scCommon) - { - /* Finished with type */ - top_stack->cur_type = 0; - } - else if (sh->sc == scText && - (top_stack->blocktype == stProc || - top_stack->blocktype == stStaticProc)) - { - /* Finished with procedure */ - struct blockvector *bv = BLOCKVECTOR (top_stack->cur_st); - struct mips_extra_func_info *e; - struct block *b; - int i; - - BLOCK_END (top_stack->cur_block) += sh->value; /* size */ - - /* Make up special symbol to contain procedure specific info */ - s = new_symbol (MIPS_EFI_SYMBOL_NAME); - SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE; - SYMBOL_CLASS (s) = LOC_CONST; - SYMBOL_TYPE (s) = builtin_type_void; - e = ((struct mips_extra_func_info *) - obstack_alloc (¤t_objfile->symbol_obstack, - sizeof (struct mips_extra_func_info))); - SYMBOL_VALUE (s) = (long) e; - e->numargs = top_stack->numargs; - add_symbol (s, top_stack->cur_block); - - /* Reallocate symbols, saving memory */ - b = shrink_block (top_stack->cur_block, top_stack->cur_st); - - /* f77 emits proc-level with address bounds==[0,0], - So look for such child blocks, and patch them. */ - for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); i++) - { - struct block *b_bad = BLOCKVECTOR_BLOCK (bv, i); - if (BLOCK_SUPERBLOCK (b_bad) == b - && BLOCK_START (b_bad) == top_stack->procadr - && BLOCK_END (b_bad) == top_stack->procadr) - { - BLOCK_START (b_bad) = BLOCK_START (b); - BLOCK_END (b_bad) = BLOCK_END (b); - } - } - } - else if (sh->sc == scText && top_stack->blocktype == stBlock) - { - /* End of (code) block. The value of the symbol is the - displacement from the procedure`s start address of the - end of this block. */ - BLOCK_END (top_stack->cur_block) = sh->value + top_stack->procadr; - shrink_block (top_stack->cur_block, top_stack->cur_st); - } - else if (sh->sc == scText && top_stack->blocktype == stFile) - { - /* End of file. Pop parse stack and ignore. Higher - level code deals with this. */ - ; - } - else - complain (&stEnd_complaint, sh->sc); - - pop_parse_stack (); /* restore previous lexical context */ - break; - - case stMember: /* member of struct or union */ - f = &TYPE_FIELDS (top_stack->cur_type)[top_stack->cur_field++]; - f->name = name; - f->bitpos = sh->value; - bitsize = 0; - f->type = parse_type (cur_fd, ax, sh->index, &bitsize, bigend, name); - f->bitsize = bitsize; - break; - - case stTypedef: /* type definition */ - /* Typedefs for forward declarations and opaque structs from alpha cc - are handled by cross_ref, skip them. */ - if (sh->iss == 0) - break; - - /* Parse the type or use the pending type. */ - pend = is_pending_symbol (cur_fdr, ext_sh); - if (pend == (struct mips_pending *) NULL) - { - t = parse_type (cur_fd, ax, sh->index, (int *)NULL, bigend, name); - add_pending (cur_fdr, ext_sh, t); - } - else - t = pend->t; - - /* mips cc puts out a typedef with the name of the struct for forward - declarations. These should not go into the symbol table and - TYPE_NAME should not be set for them. - They can't be distinguished from an intentional typedef to - the same name however: - x.h: - struct x { int ix; int jx; }; - struct xx; - x.c: - typedef struct x x; - struct xx {int ixx; int jxx; }; - generates a cross referencing stTypedef for x and xx. - The user visible effect of this is that the type of a pointer - to struct foo sometimes is given as `foo *' instead of `struct foo *'. - The problem is fixed with alpha cc. */ - - s = new_symbol (name); - SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; - SYMBOL_CLASS (s) = LOC_TYPEDEF; - SYMBOL_BLOCK_VALUE (s) = top_stack->cur_block; - SYMBOL_TYPE (s) = t; - add_symbol (s, top_stack->cur_block); - - /* Incomplete definitions of structs should not get a name. */ - if (TYPE_NAME (SYMBOL_TYPE (s)) == NULL - && (TYPE_NFIELDS (SYMBOL_TYPE (s)) != 0 - || (TYPE_CODE (SYMBOL_TYPE (s)) != TYPE_CODE_STRUCT - && TYPE_CODE (SYMBOL_TYPE (s)) != TYPE_CODE_UNION))) - { - if (TYPE_CODE (SYMBOL_TYPE (s)) == TYPE_CODE_PTR - || TYPE_CODE (SYMBOL_TYPE (s)) == TYPE_CODE_FUNC) - { - /* If we are giving a name to a type such as "pointer to - foo" or "function returning foo", we better not set - the TYPE_NAME. If the program contains "typedef char - *caddr_t;", we don't want all variables of type char - * to print as caddr_t. This is not just a - consequence of GDB's type management; CC and GCC (at - least through version 2.4) both output variables of - either type char * or caddr_t with the type - refering to the stTypedef symbol for caddr_t. If a future - compiler cleans this up it GDB is not ready for it - yet, but if it becomes ready we somehow need to - disable this check (without breaking the PCC/GCC2.4 - case). - - Sigh. - - Fortunately, this check seems not to be necessary - for anything except pointers or functions. */ - } - else - TYPE_NAME (SYMBOL_TYPE (s)) = SYMBOL_NAME (s); - } - break; - - case stFile: /* file name */ - push_parse_stack (); - top_stack->blocktype = sh->st; - break; - - /* I`ve never seen these for C */ - case stRegReloc: - break; /* register relocation */ - case stForward: - break; /* forwarding address */ - case stConstant: - break; /* constant */ - default: - complain (&unknown_mips_symtype_complaint, sh->st); - break; - } - - return count; -} - -/* Parse the type information provided in the raw AX entries for - the symbol SH. Return the bitfield size in BS, in case. - We must byte-swap the AX entries before we use them; BIGEND says whether - they are big-endian or little-endian (from fh->fBigendian). */ - -static struct type * -parse_type (fd, ax, aux_index, bs, bigend, sym_name) - int fd; - union aux_ext *ax; - unsigned int aux_index; - int *bs; - int bigend; - char *sym_name; -{ - /* Null entries in this map are treated specially */ - static struct type **map_bt[] = - { - &builtin_type_void, /* btNil */ - 0, /* btAdr */ - &builtin_type_char, /* btChar */ - &builtin_type_unsigned_char,/* btUChar */ - &builtin_type_short, /* btShort */ - &builtin_type_unsigned_short, /* btUShort */ - &builtin_type_int, /* btInt */ - &builtin_type_unsigned_int, /* btUInt */ - &builtin_type_long, /* btLong */ - &builtin_type_unsigned_long,/* btULong */ - &builtin_type_float, /* btFloat */ - &builtin_type_double, /* btDouble */ - 0, /* btStruct */ - 0, /* btUnion */ - 0, /* btEnum */ - 0, /* btTypedef */ - 0, /* btRange */ - 0, /* btSet */ - &builtin_type_complex, /* btComplex */ - &builtin_type_double_complex, /* btDComplex */ - 0, /* btIndirect */ - &builtin_type_fixed_dec, /* btFixedDec */ - &builtin_type_float_dec, /* btFloatDec */ - &builtin_type_string, /* btString */ - 0, /* btBit */ - 0, /* btPicture */ - &builtin_type_void, /* btVoid */ - 0, /* DEC C++: Pointer to member */ - 0, /* DEC C++: Virtual function table */ - 0, /* DEC C++: Class (Record) */ - &builtin_type_long, /* btLong64 */ - &builtin_type_unsigned_long, /* btULong64 */ - &builtin_type_long_long, /* btLongLong64 */ - &builtin_type_unsigned_long_long, /* btULongLong64 */ - &builtin_type_unsigned_long, /* btAdr64 */ - &builtin_type_long, /* btInt64 */ - &builtin_type_unsigned_long, /* btUInt64 */ - }; - - TIR t[1]; - struct type *tp = 0; - enum type_code type_code = TYPE_CODE_UNDEF; - - /* Handle corrupt aux indices. */ - if (aux_index >= (ecoff_data (cur_bfd)->fdr + fd)->caux) - { - complain (&index_complaint, sym_name); - return builtin_type_int; - } - ax += aux_index; - - /* Use aux as a type information record, map its basic type. */ - ecoff_swap_tir_in (bigend, &ax->a_ti, t); - if (t->bt >= (sizeof (map_bt) / sizeof (*map_bt))) - { - complain (&basic_type_complaint, t->bt, sym_name); - return builtin_type_int; - } - if (map_bt[t->bt]) - { - tp = *map_bt[t->bt]; - } - else - { - tp = NULL; - /* Cannot use builtin types -- build our own */ - switch (t->bt) - { - case btAdr: - tp = lookup_pointer_type (builtin_type_void); - break; - case btStruct: - type_code = TYPE_CODE_STRUCT; - break; - case btUnion: - type_code = TYPE_CODE_UNION; - break; - case btEnum: - type_code = TYPE_CODE_ENUM; - break; - case btRange: - type_code = TYPE_CODE_RANGE; - break; - case btSet: - type_code = TYPE_CODE_SET; - break; - case btTypedef: - /* alpha cc uses this for typedefs. The true type will be - obtained by crossreferencing below. */ - type_code = TYPE_CODE_ERROR; - break; - default: - complain (&basic_type_complaint, t->bt, sym_name); - return builtin_type_int; - } - } - - /* Move on to next aux */ - ax++; - - if (t->fBitfield) - { - /* Inhibit core dumps with some cfront generated objects that - corrupt the TIR. */ - if (bs == (int *)NULL) - { - complain (&bad_fbitfield_complaint, sym_name); - return builtin_type_int; - } - *bs = AUX_GET_WIDTH (bigend, ax); - ax++; - } - - /* All these types really point to some (common) MIPS type - definition, and only the type-qualifiers fully identify - them. We'll make the same effort at sharing. */ - if (t->bt == btStruct || - t->bt == btUnion || - t->bt == btEnum || - - /* btSet (I think) implies that the name is a tag name, not a typedef - name. This apparently is a MIPS extension for C sets. */ - t->bt == btSet) - { - char *name; - - /* Try to cross reference this type, build new type on failure. */ - ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name); - if (tp == (struct type *) NULL) - tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile); - - /* Make sure that TYPE_CODE(tp) has an expected type code. - Any type may be returned from cross_ref if file indirect entries - are corrupted. */ - if (TYPE_CODE (tp) != TYPE_CODE_STRUCT - && TYPE_CODE (tp) != TYPE_CODE_UNION - && TYPE_CODE (tp) != TYPE_CODE_ENUM) - { - complain (&unexpected_type_code_complaint, sym_name); - } - else - { - - /* Usually, TYPE_CODE(tp) is already type_code. The main - exception is if we guessed wrong re struct/union/enum. - But for struct vs. union a wrong guess is harmless, so - don't complain(). */ - if ((TYPE_CODE (tp) == TYPE_CODE_ENUM - && type_code != TYPE_CODE_ENUM) - || (TYPE_CODE (tp) != TYPE_CODE_ENUM - && type_code == TYPE_CODE_ENUM)) - { - complain (&bad_tag_guess_complaint, sym_name); - } - - if (TYPE_CODE (tp) != type_code) - { - TYPE_CODE (tp) = type_code; - } - - /* Do not set the tag name if it is a compiler generated tag name - (.Fxx or .xxfake or empty) for unnamed struct/union/enums. */ - if (name[0] == '.' || name[0] == '\0') - TYPE_TAG_NAME (tp) = NULL; - else if (TYPE_TAG_NAME (tp) == NULL - || !STREQ (TYPE_TAG_NAME (tp), name)) - TYPE_TAG_NAME (tp) = obsavestring (name, strlen (name), - ¤t_objfile->type_obstack); - } - } - - /* All these types really point to some (common) MIPS type - definition, and only the type-qualifiers fully identify - them. We'll make the same effort at sharing. - FIXME: btIndirect cannot happen here as it is handled by the - switch t->bt above. And we are not doing any guessing on range types. */ - if (t->bt == btIndirect || - t->bt == btRange) - { - char *name; - - /* Try to cross reference this type, build new type on failure. */ - ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name); - if (tp == (struct type *) NULL) - tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile); - - /* Make sure that TYPE_CODE(tp) has an expected type code. - Any type may be returned from cross_ref if file indirect entries - are corrupted. */ - if (TYPE_CODE (tp) != TYPE_CODE_RANGE) - { - complain (&unexpected_type_code_complaint, sym_name); - } - else - { - /* Usually, TYPE_CODE(tp) is already type_code. The main - exception is if we guessed wrong re struct/union/enum. */ - if (TYPE_CODE (tp) != type_code) - { - complain (&bad_tag_guess_complaint, sym_name); - TYPE_CODE (tp) = type_code; - } - if (TYPE_NAME (tp) == NULL || !STREQ (TYPE_NAME (tp), name)) - TYPE_NAME (tp) = obsavestring (name, strlen (name), - ¤t_objfile->type_obstack); - } - } - if (t->bt == btTypedef) - { - char *name; - - /* Try to cross reference this type, it should succeed. */ - ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name); - if (tp == (struct type *) NULL) - { - complain (&unable_to_cross_ref_complaint, sym_name); - tp = builtin_type_int; - } - } - - /* Deal with range types */ - if (t->bt == btRange) - { - TYPE_NFIELDS (tp) = 2; - TYPE_FIELDS (tp) = ((struct field *) - TYPE_ALLOC (tp, 2 * sizeof (struct field))); - TYPE_FIELD_NAME (tp, 0) = obsavestring ("Low", strlen ("Low"), - ¤t_objfile->type_obstack); - TYPE_FIELD_BITPOS (tp, 0) = AUX_GET_DNLOW (bigend, ax); - ax++; - TYPE_FIELD_NAME (tp, 1) = obsavestring ("High", strlen ("High"), - ¤t_objfile->type_obstack); - TYPE_FIELD_BITPOS (tp, 1) = AUX_GET_DNHIGH (bigend, ax); - ax++; - } - - /* Parse all the type qualifiers now. If there are more - than 6 the game will continue in the next aux */ - - while (1) - { -#define PARSE_TQ(tq) \ - if (t->tq != tqNil) \ - ax += upgrade_type(fd, &tp, t->tq, ax, bigend, sym_name); \ - else \ - break; - - PARSE_TQ (tq0); - PARSE_TQ (tq1); - PARSE_TQ (tq2); - PARSE_TQ (tq3); - PARSE_TQ (tq4); - PARSE_TQ (tq5); -#undef PARSE_TQ - - /* mips cc 2.x and gcc never put out continued aux entries. */ - if (!t->continued) - break; - - ecoff_swap_tir_in (bigend, &ax->a_ti, t); - ax++; - } - - /* Complain for illegal continuations due to corrupt aux entries. */ - if (t->continued) - complain (&bad_continued_complaint, sym_name); - - return tp; -} - -/* Make up a complex type from a basic one. Type is passed by - reference in TPP and side-effected as necessary. The type - qualifier TQ says how to handle the aux symbols at AX for - the symbol SX we are currently analyzing. BIGEND says whether - aux symbols are big-endian or little-endian. - Returns the number of aux symbols we parsed. */ - -static int -upgrade_type (fd, tpp, tq, ax, bigend, sym_name) - int fd; - struct type **tpp; - int tq; - union aux_ext *ax; - int bigend; - char *sym_name; -{ - int off; - struct type *t; - - /* Used in array processing */ - int rf, id; - FDR *fh; - struct type *range; - struct type *indx; - int lower, upper; - RNDXR rndx; - - switch (tq) - { - case tqPtr: - t = lookup_pointer_type (*tpp); - *tpp = t; - return 0; - - case tqProc: - t = lookup_function_type (*tpp); - *tpp = t; - return 0; - - case tqArray: - off = 0; - - /* Determine and record the domain type (type of index) */ - ecoff_swap_rndx_in (bigend, &ax->a_rndx, &rndx); - id = rndx.index; - rf = rndx.rfd; - if (rf == 0xfff) - { - ax++; - rf = AUX_GET_ISYM (bigend, ax); - off++; - } - fh = get_rfd (fd, rf); - - indx = parse_type (fd, - ecoff_data (cur_bfd)->external_aux + fh->iauxBase, - id, (int *) NULL, bigend, sym_name); - - /* The bounds type should be an integer type, but might be anything - else due to corrupt aux entries. */ - if (TYPE_CODE (indx) != TYPE_CODE_INT) - { - complain (&array_index_type_complaint, sym_name); - indx = builtin_type_int; - } - - /* Get the bounds, and create the array type. */ - ax++; - lower = AUX_GET_DNLOW (bigend, ax); - ax++; - upper = AUX_GET_DNHIGH (bigend, ax); - ax++; - rf = AUX_GET_WIDTH (bigend, ax); /* bit size of array element */ - - range = create_range_type ((struct type *) NULL, indx, - lower, upper); - - t = create_array_type ((struct type *) NULL, *tpp, range); - - /* We used to fill in the supplied array element bitsize - here if the TYPE_LENGTH of the target type was zero. - This happens for a `pointer to an array of anonymous structs', - but in this case the array element bitsize is also zero, - so nothing is gained. - And we used to check the TYPE_LENGTH of the target type against - the supplied array element bitsize. - gcc causes a mismatch for `pointer to array of object', - since the sdb directives it uses do not have a way of - specifying the bitsize, but it does no harm (the - TYPE_LENGTH should be correct) and we should be able to - ignore the erroneous bitsize from the auxiliary entry safely. - dbx seems to ignore it too. */ - - *tpp = t; - return 4 + off; - - case tqVol: - /* Volatile -- currently ignored */ - return 0; - - case tqConst: - /* Const -- currently ignored */ - return 0; - - default: - complain (&unknown_type_qual_complaint, tq); - return 0; - } -} - - -/* Parse a procedure descriptor record PR. Note that the procedure is - parsed _after_ the local symbols, now we just insert the extra - information we need into a MIPS_EFI_SYMBOL_NAME symbol that has - already been placed in the procedure's main block. Note also that - images that have been partially stripped (ld -x) have been deprived - of local symbols, and we have to cope with them here. FIRST_OFF is - the offset of the first procedure for this FDR; we adjust the - address by this amount, but I don't know why. SEARCH_SYMTAB is the symtab - to look for the function which contains the MIPS_EFI_SYMBOL_NAME symbol - in question, or NULL to use top_stack->cur_block. */ - -static void parse_procedure PARAMS ((PDR *, struct symtab *, unsigned long)); - -static void -parse_procedure (pr, search_symtab, first_off) - PDR *pr; - struct symtab *search_symtab; - unsigned long first_off; -{ - struct symbol *s, *i; - struct block *b; - struct mips_extra_func_info *e; - char *sh_name; - - /* Simple rule to find files linked "-x" */ - if (cur_fdr->rss == -1) - { - if (pr->isym == -1) - { - /* Static procedure at address pr->adr. Sigh. */ - complain (&pdr_static_symbol_complaint, (unsigned long) pr->adr); - return; - } - else - { - /* external */ - EXTR she; - - (*ecoff_backend (cur_bfd)->swap_ext_in) - (cur_bfd, - ((char *) ecoff_data (cur_bfd)->external_ext - + pr->isym * ecoff_backend (cur_bfd)->external_ext_size), - &she); - sh_name = ecoff_data (cur_bfd)->ssext + she.asym.iss; - } - } - else - { - /* Full symbols */ - SYMR sh; - - (*ecoff_backend (cur_bfd)->swap_sym_in) - (cur_bfd, - ((char *) ecoff_data (cur_bfd)->external_sym - + ((cur_fdr->isymBase + pr->isym) - * ecoff_backend (cur_bfd)->external_sym_size)), - &sh); - sh_name = ecoff_data (cur_bfd)->ss + cur_fdr->issBase + sh.iss; - } - - if (search_symtab != NULL) - { -#if 0 - /* This loses both in the case mentioned (want a static, find a global), - but also if we are looking up a non-mangled name which happens to - match the name of a mangled function. */ - /* We have to save the cur_fdr across the call to lookup_symbol. - If the pdr is for a static function and if a global function with - the same name exists, lookup_symbol will eventually read in the symtab - for the global function and clobber cur_fdr. */ - FDR *save_cur_fdr = cur_fdr; - s = lookup_symbol (sh_name, NULL, VAR_NAMESPACE, 0, NULL); - cur_fdr = save_cur_fdr; -#else - s = mylookup_symbol - (sh_name, - BLOCKVECTOR_BLOCK (BLOCKVECTOR (search_symtab), STATIC_BLOCK), - VAR_NAMESPACE, - LOC_BLOCK); -#endif - } - else - s = mylookup_symbol (sh_name, top_stack->cur_block, - VAR_NAMESPACE, LOC_BLOCK); - - if (s != 0) - { - b = SYMBOL_BLOCK_VALUE (s); - } - else - { - complain (&pdr_for_nonsymbol_complaint, sh_name); -#if 1 - return; -#else -/* FIXME -- delete. We can't do symbol allocation now; it's all done. */ - s = new_symbol (sh_name); - SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; - SYMBOL_CLASS (s) = LOC_BLOCK; - /* Donno its type, hope int is ok */ - SYMBOL_TYPE (s) = lookup_function_type (builtin_type_int); - add_symbol (s, top_stack->cur_block); - /* Wont have symbols for this one */ - b = new_block (2); - SYMBOL_BLOCK_VALUE (s) = b; - BLOCK_FUNCTION (b) = s; - BLOCK_START (b) = pr->adr; - /* BOUND used to be the end of procedure's text, but the - argument is no longer passed in. */ - BLOCK_END (b) = bound; - BLOCK_SUPERBLOCK (b) = top_stack->cur_block; - add_block (b, top_stack->cur_st); -#endif - } - - i = mylookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, LOC_CONST); - - if (i) - { - e = (struct mips_extra_func_info *) SYMBOL_VALUE (i); - e->pdr = *pr; - e->pdr.isym = (long) s; - e->pdr.adr += cur_fdr->adr - first_off; - - /* Correct incorrect setjmp procedure descriptor from the library - to make backtrace through setjmp work. */ - if (e->pdr.pcreg == 0 && STREQ (sh_name, "setjmp")) - { - complain (&bad_setjmp_pdr_complaint, 0); - e->pdr.pcreg = RA_REGNUM; - e->pdr.regmask = 0x80000000; - e->pdr.regoffset = -4; - } - - /* Fake PC_REGNUM for alpha __sigtramp so that read_next_frame_reg - will use the saved user pc from the sigcontext. */ - if (STREQ (sh_name, "__sigtramp")) - e->pdr.pcreg = PC_REGNUM; - } -} - -/* Parse the external symbol ES. Just call parse_symbol() after - making sure we know where the aux are for it. For procedures, - parsing of the PDRs has already provided all the needed - information, we only parse them if SKIP_PROCEDURES is false, - and only if this causes no symbol duplication. - BIGEND says whether aux entries are big-endian or little-endian. - - This routine clobbers top_stack->cur_block and ->cur_st. */ - -static void -parse_external (es, skip_procedures, bigend) - EXTR *es; - int skip_procedures; - int bigend; -{ - union aux_ext *ax; - - if (es->ifd != ifdNil) - { - cur_fd = es->ifd; - cur_fdr = ecoff_data (cur_bfd)->fdr + cur_fd; - ax = ecoff_data (cur_bfd)->external_aux + cur_fdr->iauxBase; - } - else - { - cur_fdr = ecoff_data (cur_bfd)->fdr; - ax = 0; - } - - /* Reading .o files */ - if (es->asym.sc == scUndefined || es->asym.sc == scNil) - { - char *what; - switch (es->asym.st) - { - case stNil: - /* These are generated for static symbols in .o files, - ignore them. */ - return; - case stStaticProc: - case stProc: - what = "procedure"; - n_undef_procs++; - break; - case stGlobal: - what = "variable"; - n_undef_vars++; - break; - case stLabel: - what = "label"; - n_undef_labels++; - break; - default: - what = "symbol"; - break; - } - n_undef_symbols++; - /* FIXME: Turn this into a complaint? */ - if (info_verbose) - printf_filtered ("Warning: %s `%s' is undefined (in %s)\n", - what, - ecoff_data (cur_bfd)->ssext + es->asym.iss, - fdr_name (cur_fdr)); - return; - } - - switch (es->asym.st) - { - case stProc: - /* If we have full symbols we do not need more */ - if (skip_procedures) - return; - if (mylookup_symbol (ecoff_data (cur_bfd)->ssext + es->asym.iss, - top_stack->cur_block, - VAR_NAMESPACE, LOC_BLOCK)) - break; - /* fall through */ - case stGlobal: - case stLabel: - /* Note that the case of a symbol with indexNil must be handled - anyways by parse_symbol(). */ - parse_symbol (&es->asym, ax, (char *) NULL, bigend); - break; - default: - break; - } -} - -/* Parse the line number info for file descriptor FH into - GDB's linetable LT. MIPS' encoding requires a little bit - of magic to get things out. Note also that MIPS' line - numbers can go back and forth, apparently we can live - with that and do not need to reorder our linetables */ - -static void -parse_lines (fh, pr, lt, maxlines) - FDR *fh; - PDR *pr; - struct linetable *lt; - int maxlines; -{ - unsigned char *base; - int j, k; - int delta, count, lineno = 0; - unsigned long first_off = pr->adr; - - if (fh->cbLine == 0) - return; - - base = ecoff_data (cur_bfd)->line + fh->cbLineOffset; - - /* Scan by procedure descriptors */ - k = 0; - for (j = 0; j < fh->cpd; j++, pr++) - { - long l; - unsigned long adr; - unsigned char *halt; - - /* No code for this one */ - if (pr->iline == ilineNil || - pr->lnLow == -1 || pr->lnHigh == -1) - continue; - - /* Determine start and end address of compressed line bytes for - this procedure. */ - base = ecoff_data (cur_bfd)->line + fh->cbLineOffset; - if (j != (fh->cpd - 1)) - halt = base + pr[1].cbLineOffset; - else - halt = base + fh->cbLine; - base += pr->cbLineOffset; - - adr = fh->adr + pr->adr - first_off; - l = adr >> 2; /* in words */ - for (lineno = pr->lnLow; base < halt; ) - { - count = *base & 0x0f; - delta = *base++ >> 4; - if (delta >= 8) - delta -= 16; - if (delta == -8) - { - delta = (base[0] << 8) | base[1]; - if (delta >= 0x8000) - delta -= 0x10000; - base += 2; - } - lineno += delta; /* first delta is 0 */ - - /* Complain if the line table overflows. Could happen - with corrupt binaries. */ - if (lt->nitems >= maxlines) - { - complain (&bad_linetable_guess_complaint, fdr_name (fh)); - break; - } - k = add_line (lt, lineno, l, k); - l += count + 1; - } - } -} - -/* Master parsing procedure for first-pass reading of file symbols - into a partial_symtab. */ - -static void -parse_partial_symbols (objfile, section_offsets) - struct objfile *objfile; - struct section_offsets *section_offsets; -{ - const struct ecoff_backend_data * const backend = ecoff_backend (cur_bfd); - const bfd_size_type external_sym_size = backend->external_sym_size; - const bfd_size_type external_rfd_size = backend->external_rfd_size; - const bfd_size_type external_ext_size = backend->external_ext_size; - void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *)) - = backend->swap_ext_in; - void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) - = backend->swap_sym_in; - void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *)) - = backend->swap_rfd_in; - int f_idx, s_idx; - HDRR *hdr = &ecoff_data (cur_bfd)->symbolic_header; - /* Running pointers */ - FDR *fh; - char *ext_out; - char *ext_out_end; - EXTR *ext_block; - register EXTR *ext_in; - EXTR *ext_in_end; - SYMR sh; - struct partial_symtab *pst; - - int past_first_source_file = 0; - - /* List of current psymtab's include files */ - char **psymtab_include_list; - int includes_allocated; - int includes_used; - EXTR *extern_tab; - struct pst_map *fdr_to_pst; - /* Index within current psymtab dependency list */ - struct partial_symtab **dependency_list; - int dependencies_used, dependencies_allocated; - struct cleanup *old_chain; - char *name; - enum language prev_language; - - extern_tab = (EXTR *) obstack_alloc (&objfile->psymbol_obstack, - sizeof (EXTR) * hdr->iextMax); - - includes_allocated = 30; - includes_used = 0; - psymtab_include_list = (char **) alloca (includes_allocated * - sizeof (char *)); - next_symbol_text_func = mips_next_symbol_text; - - dependencies_allocated = 30; - dependencies_used = 0; - dependency_list = - (struct partial_symtab **) alloca (dependencies_allocated * - sizeof (struct partial_symtab *)); - - last_source_file = NULL; - - /* - * Big plan: - * - * Only parse the Local and External symbols, and the Relative FDR. - * Fixup enough of the loader symtab to be able to use it. - * Allocate space only for the file's portions we need to - * look at. (XXX) - */ - - max_gdbinfo = 0; - max_glevel = MIN_GLEVEL; - - /* Allocate the map FDR -> PST. - Minor hack: -O3 images might claim some global data belongs - to FDR -1. We`ll go along with that */ - fdr_to_pst = (struct pst_map *) xzalloc ((hdr->ifdMax + 1) * sizeof *fdr_to_pst); - old_chain = make_cleanup (free, fdr_to_pst); - fdr_to_pst++; - { - struct partial_symtab *pst = new_psymtab ("", objfile); - fdr_to_pst[-1].pst = pst; - FDR_IDX (pst) = -1; - } - - /* Allocate the global pending list. */ - ECOFF_PENDING_LIST (objfile) = - ((struct mips_pending **) - obstack_alloc (&objfile->psymbol_obstack, - hdr->ifdMax * sizeof (struct mips_pending *))); - memset ((PTR) ECOFF_PENDING_LIST (objfile), 0, - hdr->ifdMax * sizeof (struct mips_pending *)); - - /* Pass 0 over external syms: swap them in. */ - ext_block = (EXTR *) xmalloc (hdr->iextMax * sizeof (EXTR)); - make_cleanup (free, ext_block); - - ext_out = (char *) ecoff_data (cur_bfd)->external_ext; - ext_out_end = ext_out + hdr->iextMax * external_ext_size; - ext_in = ext_block; - for (; ext_out < ext_out_end; ext_out += external_ext_size, ext_in++) - (*swap_ext_in) (cur_bfd, ext_out, ext_in); - - /* Pass 1 over external syms: Presize and partition the list */ - ext_in = ext_block; - ext_in_end = ext_in + hdr->iextMax; - for (; ext_in < ext_in_end; ext_in++) - fdr_to_pst[ext_in->ifd].n_globals++; - - /* Pass 1.5 over files: partition out global symbol space */ - s_idx = 0; - for (f_idx = -1; f_idx < hdr->ifdMax; f_idx++) - { - fdr_to_pst[f_idx].globals_offset = s_idx; - s_idx += fdr_to_pst[f_idx].n_globals; - fdr_to_pst[f_idx].n_globals = 0; - } - - /* Pass 2 over external syms: fill in external symbols */ - ext_in = ext_block; - ext_in_end = ext_in + hdr->iextMax; - for (; ext_in < ext_in_end; ext_in++) - { - enum minimal_symbol_type ms_type = mst_text; - - extern_tab[fdr_to_pst[ext_in->ifd].globals_offset - + fdr_to_pst[ext_in->ifd].n_globals++] = *ext_in; - - if (ext_in->asym.sc == scUndefined || ext_in->asym.sc == scNil) - continue; - - name = ecoff_data (cur_bfd)->ssext + ext_in->asym.iss; - switch (ext_in->asym.st) - { - case stProc: - break; - case stStaticProc: - ms_type = mst_file_text; - break; - case stGlobal: - if (ext_in->asym.sc == scData - || ext_in->asym.sc == scSData - || ext_in->asym.sc == scRData) - ms_type = mst_data; - else - ms_type = mst_bss; - break; - case stLabel: - if (ext_in->asym.sc == scAbs) - ms_type = mst_abs; - else if (ext_in->asym.sc == scText) - ms_type = mst_text; - else if (ext_in->asym.sc == scData - || ext_in->asym.sc == scSData - || ext_in->asym.sc == scRData) - ms_type = mst_data; - else - ms_type = mst_bss; - break; - case stLocal: - /* The alpha has the section start addresses in stLocal symbols - whose name starts with a `.'. Skip those but complain for all - other stLocal symbols. */ - if (name[0] == '.') - continue; - /* Fall through. */ - default: - ms_type = mst_unknown; - complain (&unknown_ext_complaint, name); - } - prim_record_minimal_symbol (name, ext_in->asym.value, ms_type); - } - - /* Pass 3 over files, over local syms: fill in static symbols */ - for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) - { - struct partial_symtab *save_pst; - EXTR *ext_ptr; - - cur_fdr = fh = ecoff_data (cur_bfd)->fdr + f_idx; - - if (fh->csym == 0) - { - fdr_to_pst[f_idx].pst = NULL; - continue; - } - pst = start_psymtab_common (objfile, section_offsets, - fdr_name (fh), - fh->cpd ? fh->adr : 0, - objfile->global_psymbols.next, - objfile->static_psymbols.next); - pst->read_symtab_private = ((char *) - obstack_alloc (&objfile->psymbol_obstack, - sizeof (struct symloc))); - memset ((PTR) pst->read_symtab_private, 0, sizeof (struct symloc)); - - save_pst = pst; - FDR_IDX (pst) = f_idx; - CUR_BFD (pst) = cur_bfd; - - /* The way to turn this into a symtab is to call... */ - pst->read_symtab = mipscoff_psymtab_to_symtab; - - /* Set up language for the pst. - The language from the FDR is used if it is unambigious (e.g. cfront - with native cc and g++ will set the language to C). - Otherwise we have to deduce the language from the filename. - Native ecoff has every header file in a separate FDR, so - deduce_language_from_filename will return language_unknown for - a header file, which is not what we want. - But the FDRs for the header files are after the FDR for the source - file, so we can assign the language of the source file to the - following header files. Then we save the language in the private - pst data so that we can reuse it when building symtabs. */ - prev_language = psymtab_language; - - switch (fh->lang) - { - case langCplusplusV2: - psymtab_language = language_cplus; - break; - default: - psymtab_language = deduce_language_from_filename (fdr_name (fh)); - break; - } - if (psymtab_language == language_unknown) - psymtab_language = prev_language; - PST_PRIVATE (pst)->pst_language = psymtab_language; - - pst->texthigh = pst->textlow; - - /* For stabs-in-ecoff files, the second symbol must be @stab. - This symbol is emitted by mips-tfile to signal that the - current object file uses encapsulated stabs instead of mips - ecoff for local symbols. (It is the second symbol because - the first symbol is the stFile used to signal the start of a - file). */ - processing_gcc_compilation = 0; - if (fh->csym >= 2) - { - (*swap_sym_in) (cur_bfd, - ((char *) ecoff_data (cur_bfd)->external_sym - + (fh->isymBase + 1) * external_sym_size), - &sh); - if (STREQ (ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss, - stabs_symbol)) - processing_gcc_compilation = 2; - } - - if (processing_gcc_compilation != 0) - { - for (cur_sdx = 2; cur_sdx < fh->csym; cur_sdx++) - { - int type_code; - char *namestring; - - (*swap_sym_in) (cur_bfd, - ((char *) ecoff_data (cur_bfd)->external_sym - + (fh->isymBase + cur_sdx) * external_sym_size), - &sh); - type_code = ECOFF_UNMARK_STAB (sh.index); - if (!ECOFF_IS_STAB (&sh)) - { - if (sh.st == stProc || sh.st == stStaticProc) - { - long procaddr = sh.value; - long isym; - - - isym = AUX_GET_ISYM (fh->fBigendian, - (ecoff_data (cur_bfd)->external_aux - + fh->iauxBase - + sh.index)); - (*swap_sym_in) (cur_bfd, - (((char *) - ecoff_data (cur_bfd)->external_sym) - + ((fh->isymBase + isym - 1) - * external_sym_size)), - &sh); - if (sh.st == stEnd) - { - long high = procaddr + sh.value; - if (high > pst->texthigh) - pst->texthigh = high; - } - } - continue; - } -#define SET_NAMESTRING() \ - namestring = ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss -#define CUR_SYMBOL_TYPE type_code -#define CUR_SYMBOL_VALUE sh.value -#define START_PSYMTAB(ofile,secoff,fname,low,symoff,global_syms,static_syms)\ - pst = save_pst -#define END_PSYMTAB(pst,ilist,ninc,c_off,c_text,dep_list,n_deps) (void)0 -#define HANDLE_RBRAC(val) \ - if ((val) > save_pst->texthigh) save_pst->texthigh = (val); -#include "partial-stab.h" - } - } - else - { - for (cur_sdx = 0; cur_sdx < fh->csym;) - { - char *name; - enum address_class class; - - (*swap_sym_in) (cur_bfd, - ((char *) ecoff_data (cur_bfd)->external_sym - + ((fh->isymBase + cur_sdx) - * external_sym_size)), - &sh); - - if (ECOFF_IS_STAB (&sh)) - { - cur_sdx++; - continue; - } - - /* Non absolute static symbols go into the minimal table. */ - if (sh.sc == scUndefined || sh.sc == scNil - || (sh.index == indexNil - && (sh.st != stStatic || sh.sc == scAbs))) - { - /* FIXME, premature? */ - cur_sdx++; - continue; - } - - name = ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss; - - switch (sh.st) - { - long high; - long procaddr; - int new_sdx; - - case stStaticProc: /* Function */ - /* I believe this is used only for file-local functions. - The comment in symconst.h ("load time only static procs") - isn't particularly clear on this point. */ - prim_record_minimal_symbol (name, sh.value, mst_file_text); - /* FALLTHROUGH */ - - case stProc: /* Asm labels apparently */ - ADD_PSYMBOL_TO_LIST (name, strlen (name), - VAR_NAMESPACE, LOC_BLOCK, - objfile->static_psymbols, sh.value, - psymtab_language, objfile); - /* Skip over procedure to next one. */ - if (sh.index >= hdr->iauxMax) - { - /* Should not happen, but does when cross-compiling - with the MIPS compiler. FIXME -- pull later. */ - complain (&index_complaint, name); - new_sdx = cur_sdx + 1; /* Don't skip at all */ - } - else - new_sdx = AUX_GET_ISYM (fh->fBigendian, - (ecoff_data (cur_bfd)->external_aux - + fh->iauxBase - + sh.index)); - procaddr = sh.value; - - if (new_sdx <= cur_sdx) - { - /* This should not happen either... FIXME. */ - complain (&aux_index_complaint, name); - new_sdx = cur_sdx + 1; /* Don't skip backward */ - } - - cur_sdx = new_sdx; - (*swap_sym_in) (cur_bfd, - ((char *) ecoff_data (cur_bfd)->external_sym - + ((fh->isymBase + cur_sdx - 1) - * external_sym_size)), - &sh); - if (sh.st != stEnd) - continue; - high = procaddr + sh.value; - if (high > pst->texthigh) - pst->texthigh = high; - continue; - - case stStatic: /* Variable */ - if (sh.sc == scData || sh.sc == scSData || sh.sc == scRData) - prim_record_minimal_symbol (name, sh.value, mst_file_data); - else - prim_record_minimal_symbol (name, sh.value, mst_file_bss); - class = LOC_STATIC; - break; - - case stTypedef:/* Typedef */ - class = LOC_TYPEDEF; - break; - - case stConstant: /* Constant decl */ - class = LOC_CONST; - break; - - case stUnion: - case stStruct: - case stEnum: - case stBlock: /* { }, str, un, enum*/ - if (sh.sc == scInfo || sh.sc == scCommon) - { - ADD_PSYMBOL_TO_LIST (name, strlen (name), - STRUCT_NAMESPACE, LOC_TYPEDEF, - objfile->static_psymbols, - sh.value, - psymtab_language, objfile); - } - /* Skip over the block */ - new_sdx = sh.index; - if (new_sdx <= cur_sdx) - { - /* This happens with the Ultrix kernel. */ - complain (&block_index_complaint, name); - new_sdx = cur_sdx + 1; /* Don't skip backward */ - } - cur_sdx = new_sdx; - continue; - - case stFile: /* File headers */ - case stLabel: /* Labels */ - case stEnd: /* Ends of files */ - goto skip; - - case stLocal: /* Local variables */ - /* Normally these are skipped because we skip over - all blocks we see. However, these can occur - as visible symbols in a .h file that contains code. */ - goto skip; - - default: - /* Both complaints are valid: one gives symbol name, - the other the offending symbol type. */ - complain (&unknown_sym_complaint, name); - complain (&unknown_st_complaint, sh.st); - cur_sdx++; - continue; - } - /* Use this gdb symbol */ - ADD_PSYMBOL_TO_LIST (name, strlen (name), - VAR_NAMESPACE, class, - objfile->static_psymbols, sh.value, - psymtab_language, objfile); - skip: - cur_sdx++; /* Go to next file symbol */ - } - - /* Now do enter the external symbols. */ - ext_ptr = &extern_tab[fdr_to_pst[f_idx].globals_offset]; - cur_sdx = fdr_to_pst[f_idx].n_globals; - PST_PRIVATE (save_pst)->extern_count = cur_sdx; - PST_PRIVATE (save_pst)->extern_tab = ext_ptr; - for (; --cur_sdx >= 0; ext_ptr++) - { - enum address_class class; - SYMR *psh; - char *name; - - if (ext_ptr->ifd != f_idx) - abort (); - psh = &ext_ptr->asym; - - /* Do not add undefined symbols to the partial symbol table. */ - if (psh->sc == scUndefined || psh->sc == scNil) - continue; - - switch (psh->st) - { - case stNil: - /* These are generated for static symbols in .o files, - ignore them. */ - continue; - case stProc: - case stStaticProc: - class = LOC_BLOCK; - break; - case stLabel: - class = LOC_LABEL; - break; - default: - complain (&unknown_ext_complaint, - ecoff_data (cur_bfd)->ssext + psh->iss); - /* Fall through, pretend it's global. */ - case stGlobal: - class = LOC_STATIC; - break; - } - name = ecoff_data (cur_bfd)->ssext + psh->iss; - ADD_PSYMBOL_ADDR_TO_LIST (name, strlen (name), - VAR_NAMESPACE, class, - objfile->global_psymbols, (CORE_ADDR) psh->value, - psymtab_language, objfile); - } - } - - /* Link pst to FDR. end_psymtab returns NULL if the psymtab was - empty and put on the free list. */ - fdr_to_pst[f_idx].pst = end_psymtab (save_pst, - psymtab_include_list, includes_used, - -1, save_pst->texthigh, - dependency_list, dependencies_used); - if (objfile->ei.entry_point >= save_pst->textlow && - objfile->ei.entry_point < save_pst->texthigh) - { - objfile->ei.entry_file_lowpc = save_pst->textlow; - objfile->ei.entry_file_highpc = save_pst->texthigh; - } - } - - /* Now scan the FDRs for dependencies */ - for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) - { - fh = f_idx + ecoff_data (cur_bfd)->fdr; - pst = fdr_to_pst[f_idx].pst; - - if (pst == (struct partial_symtab *)NULL) - continue; - - /* This should catch stabs-in-ecoff. */ - if (fh->crfd <= 1) - continue; - - /* Skip the first file indirect entry as it is a self dependency - for source files or a reverse .h -> .c dependency for header files. */ - pst->number_of_dependencies = 0; - pst->dependencies = - ((struct partial_symtab **) - obstack_alloc (&objfile->psymbol_obstack, - ((fh->crfd - 1) - * sizeof (struct partial_symtab *)))); - for (s_idx = 1; s_idx < fh->crfd; s_idx++) - { - RFDT rh; - - (*swap_rfd_in) (cur_bfd, - ((char *) ecoff_data (cur_bfd)->external_rfd - + (fh->rfdBase + s_idx) * external_rfd_size), - &rh); - if (rh < 0 || rh >= hdr->ifdMax) - { - complain (&bad_file_number_complaint, rh); - continue; - } - - /* Skip self dependencies of header files. */ - if (rh == f_idx) - continue; - - /* Do not add to dependeny list if psymtab was empty. */ - if (fdr_to_pst[rh].pst == (struct partial_symtab *)NULL) - continue; - pst->dependencies[pst->number_of_dependencies++] = fdr_to_pst[rh].pst; - } - } - do_cleanups (old_chain); -} - - -static char * -mips_next_symbol_text () -{ - SYMR sh; - - cur_sdx++; - (*ecoff_backend (cur_bfd)->swap_sym_in) - (cur_bfd, - ((char *) ecoff_data (cur_bfd)->external_sym - + ((cur_fdr->isymBase + cur_sdx) - * ecoff_backend (cur_bfd)->external_sym_size)), - &sh); - return ecoff_data (cur_bfd)->ss + cur_fdr->issBase + sh.iss; -} - -/* Ancillary function to psymtab_to_symtab(). Does all the work - for turning the partial symtab PST into a symtab, recurring - first on all dependent psymtabs. The argument FILENAME is - only passed so we can see in debug stack traces what file - is being read. - - This function has a split personality, based on whether the - symbol table contains ordinary ecoff symbols, or stabs-in-ecoff. - The flow of control and even the memory allocation differs. FIXME. */ - -static void -psymtab_to_symtab_1 (pst, filename) - struct partial_symtab *pst; - char *filename; -{ - const bfd_size_type external_sym_size - = ecoff_backend (cur_bfd)->external_sym_size; - const bfd_size_type external_pdr_size - = ecoff_backend (cur_bfd)->external_pdr_size; - void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) - = ecoff_backend (cur_bfd)->swap_sym_in; - void (* const swap_pdr_in) PARAMS ((bfd *, PTR, PDR *)) - = ecoff_backend (cur_bfd)->swap_pdr_in; - int i; - struct symtab *st; - FDR *fh; - struct linetable *lines; - - if (pst->readin) - return; - pst->readin = 1; - - /* Read in all partial symbtabs on which this one is dependent. - NOTE that we do have circular dependencies, sigh. We solved - that by setting pst->readin before this point. */ - - for (i = 0; i < pst->number_of_dependencies; i++) - if (!pst->dependencies[i]->readin) - { - /* Inform about additional files to be read in. */ - if (info_verbose) - { - fputs_filtered (" ", stdout); - wrap_here (""); - fputs_filtered ("and ", stdout); - wrap_here (""); - printf_filtered ("%s...", - pst->dependencies[i]->filename); - wrap_here (""); /* Flush output */ - fflush (stdout); - } - /* We only pass the filename for debug purposes */ - psymtab_to_symtab_1 (pst->dependencies[i], - pst->dependencies[i]->filename); - } - - /* Do nothing if this is a dummy psymtab. */ - - if (pst->n_global_syms == 0 && pst->n_static_syms == 0 - && pst->textlow == 0 && pst->texthigh == 0) - return; - - /* Now read the symbols for this symtab */ - - cur_bfd = CUR_BFD (pst); - current_objfile = pst->objfile; - cur_fd = FDR_IDX (pst); - fh = (cur_fd == -1) ? (FDR *) NULL : ecoff_data (cur_bfd)->fdr + cur_fd; - cur_fdr = fh; - - /* See comment in parse_partial_symbols about the @stabs sentinel. */ - processing_gcc_compilation = 0; - if (fh != (FDR *) NULL && fh->csym >= 2) - { - SYMR sh; - - (*swap_sym_in) (cur_bfd, - ((char *) ecoff_data (cur_bfd)->external_sym - + (fh->isymBase + 1) * external_sym_size), - &sh); - if (STREQ (ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss, - stabs_symbol)) - { - /* We indicate that this is a GCC compilation so that certain - features will be enabled in stabsread/dbxread. */ - processing_gcc_compilation = 2; - } - } - - if (processing_gcc_compilation != 0) - { - char *pdr_ptr; - char *pdr_end; - int first_pdr; - unsigned long first_off = 0; - - /* This symbol table contains stabs-in-ecoff entries. */ - - /* Parse local symbols first */ - - if (fh->csym <= 2) /* FIXME, this blows psymtab->symtab ptr */ - { - current_objfile = NULL; - return; - } - for (cur_sdx = 2; cur_sdx < fh->csym; cur_sdx++) - { - SYMR sh; - char *name; - CORE_ADDR valu; - - (*swap_sym_in) (cur_bfd, - ((char *) ecoff_data (cur_bfd)->external_sym - + (fh->isymBase + cur_sdx) * external_sym_size), - &sh); - name = ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss; - valu = sh.value; - if (ECOFF_IS_STAB (&sh)) - { - int type_code = ECOFF_UNMARK_STAB (sh.index); - process_one_symbol (type_code, 0, valu, name, - pst->section_offsets, pst->objfile); - if (type_code == N_FUN) - { - /* Make up special symbol to contain - procedure specific info */ - struct mips_extra_func_info *e = - ((struct mips_extra_func_info *) - obstack_alloc (¤t_objfile->symbol_obstack, - sizeof (struct mips_extra_func_info))); - struct symbol *s = new_symbol (MIPS_EFI_SYMBOL_NAME); - SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE; - SYMBOL_CLASS (s) = LOC_CONST; - SYMBOL_TYPE (s) = builtin_type_void; - SYMBOL_VALUE (s) = (long) e; - add_symbol_to_list (s, &local_symbols); - } - } - else if (sh.st == stLabel && sh.index != indexNil) - { - /* Handle encoded stab line number. */ - record_line (current_subfile, sh.index, valu); - } - else if (sh.st == stProc || sh.st == stStaticProc || sh.st == stEnd) - /* These are generated by gcc-2.x, do not complain */ - ; - else - complain (&stab_unknown_complaint, name); - } - st = end_symtab (pst->texthigh, 0, 0, pst->objfile, SECT_OFF_TEXT); - end_stabs (); - - /* Sort the symbol table now, we are done adding symbols to it. - We must do this before parse_procedure calls lookup_symbol. */ - sort_symtab_syms (st); - - /* This may not be necessary for stabs symtabs. FIXME. */ - sort_blocks (st); - - /* Fill in procedure info next. */ - first_pdr = 1; - pdr_ptr = ((char *) ecoff_data (cur_bfd)->external_pdr - + fh->ipdFirst * external_pdr_size); - pdr_end = pdr_ptr + fh->cpd * external_pdr_size; - for (; pdr_ptr < pdr_end; pdr_ptr += external_pdr_size) - { - PDR pr; - - (*swap_pdr_in) (cur_bfd, pdr_ptr, &pr); - if (first_pdr) - { - first_off = pr.adr; - first_pdr = 0; - } - parse_procedure (&pr, st, first_off); - } - } - else - { - /* This symbol table contains ordinary ecoff entries. */ - - /* FIXME: doesn't use pst->section_offsets. */ - - int f_max; - int maxlines; - EXTR *ext_ptr; - - /* How many symbols will we need */ - /* FIXME, this does not count enum values. */ - f_max = pst->n_global_syms + pst->n_static_syms; - if (fh == 0) - { - maxlines = 0; - st = new_symtab ("unknown", f_max, 0, pst->objfile); - } - else - { - f_max += fh->csym + fh->cpd; - maxlines = 2 * fh->cline; - st = new_symtab (pst->filename, 2 * f_max, maxlines, pst->objfile); - - /* The proper language was already determined when building - the psymtab, use it. */ - st->language = PST_PRIVATE (pst)->pst_language; - } - - psymtab_language = st->language; - - lines = LINETABLE (st); - - /* Get a new lexical context */ - - push_parse_stack (); - top_stack->cur_st = st; - top_stack->cur_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (st), - STATIC_BLOCK); - BLOCK_START (top_stack->cur_block) = fh ? fh->adr : 0; - BLOCK_END (top_stack->cur_block) = 0; - top_stack->blocktype = stFile; - top_stack->maxsyms = 2 * f_max; - top_stack->cur_type = 0; - top_stack->procadr = 0; - top_stack->numargs = 0; - - if (fh) - { - char *sym_ptr; - char *sym_end; - - /* Parse local symbols first */ - sym_ptr = ((char *) ecoff_data (cur_bfd)->external_sym - + fh->isymBase * external_sym_size); - sym_end = sym_ptr + fh->csym * external_sym_size; - while (sym_ptr < sym_end) - { - SYMR sh; - int c; - - (*swap_sym_in) (cur_bfd, sym_ptr, &sh); - c = parse_symbol (&sh, - (ecoff_data (cur_bfd)->external_aux - + fh->iauxBase), - sym_ptr, fh->fBigendian); - sym_ptr += c * external_sym_size; - } - - /* Linenumbers. At the end, check if we can save memory. - parse_lines has to look ahead an arbitrary number of PDR - structures, so we swap them all first. */ - if (fh->cpd > 0) - { - PDR *pr_block; - struct cleanup *old_chain; - char *pdr_ptr; - char *pdr_end; - PDR *pdr_in; - PDR *pdr_in_end; - - pr_block = (PDR *) xmalloc (fh->cpd * sizeof (PDR)); - - old_chain = make_cleanup (free, pr_block); - - pdr_ptr = ((char *) ecoff_data (cur_bfd)->external_pdr - + fh->ipdFirst * external_pdr_size); - pdr_end = pdr_ptr + fh->cpd * external_pdr_size; - pdr_in = pr_block; - for (; - pdr_ptr < pdr_end; - pdr_ptr += external_pdr_size, pdr_in++) - (*swap_pdr_in) (cur_bfd, pdr_ptr, pdr_in); - - parse_lines (fh, pr_block, lines, maxlines); - if (lines->nitems < fh->cline) - lines = shrink_linetable (lines); - - /* Fill in procedure info next. */ - pdr_in = pr_block; - pdr_in_end = pdr_in + fh->cpd; - for (; pdr_in < pdr_in_end; pdr_in++) - parse_procedure (pdr_in, 0, pr_block->adr); - - do_cleanups (old_chain); - } - } - - LINETABLE (st) = lines; - - /* .. and our share of externals. - XXX use the global list to speed up things here. how? - FIXME, Maybe quit once we have found the right number of ext's? */ - top_stack->cur_st = st; - top_stack->cur_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (top_stack->cur_st), - GLOBAL_BLOCK); - top_stack->blocktype = stFile; - top_stack->maxsyms = (ecoff_data (cur_bfd)->symbolic_header.isymMax - + ecoff_data (cur_bfd)->symbolic_header.ipdMax - + ecoff_data (cur_bfd)->symbolic_header.iextMax); - - ext_ptr = PST_PRIVATE (pst)->extern_tab; - for (i = PST_PRIVATE (pst)->extern_count; --i >= 0; ext_ptr++) - parse_external (ext_ptr, 1, fh->fBigendian); - - /* If there are undefined symbols, tell the user. - The alpha has an undefined symbol for every symbol that is - from a shared library, so tell the user only if verbose is on. */ - if (info_verbose && n_undef_symbols) - { - printf_filtered ("File %s contains %d unresolved references:", - st->filename, n_undef_symbols); - printf_filtered ("\n\t%4d variables\n\t%4d procedures\n\t%4d labels\n", - n_undef_vars, n_undef_procs, n_undef_labels); - n_undef_symbols = n_undef_labels = n_undef_vars = n_undef_procs = 0; - - } - pop_parse_stack (); - - /* Sort the symbol table now, we are done adding symbols to it.*/ - sort_symtab_syms (st); - - sort_blocks (st); - } - - /* Now link the psymtab and the symtab. */ - pst->symtab = st; - - current_objfile = NULL; -} - -/* Ancillary parsing procedures. */ - -/* Lookup the type at relative index RN. Return it in TPP - if found and in any event come up with its name PNAME. - BIGEND says whether aux symbols are big-endian or not (from fh->fBigendian). - Return value says how many aux symbols we ate. */ - -static int -cross_ref (fd, ax, tpp, type_code, pname, bigend, sym_name) - int fd; - union aux_ext *ax; - struct type **tpp; - enum type_code type_code; /* Use to alloc new type if none is found. */ - char **pname; - int bigend; - char *sym_name; -{ - RNDXR rn[1]; - unsigned int rf; - int result = 1; - FDR *fh; - char *esh; - SYMR sh; - int xref_fd; - struct mips_pending *pend; - - *tpp = (struct type *)NULL; - - ecoff_swap_rndx_in (bigend, &ax->a_rndx, rn); - - /* Escape index means 'the next one' */ - if (rn->rfd == 0xfff) - { - result++; - rf = AUX_GET_ISYM (bigend, ax + 1); - } - else - { - rf = rn->rfd; - } - - /* mips cc uses a rf of -1 for opaque struct definitions. - Set TYPE_FLAG_STUB for these types so that check_stub_type will - resolve them if the struct gets defined in another compilation unit. */ - if (rf == -1) - { - *pname = ""; - *tpp = init_type (type_code, 0, 0, (char *) NULL, current_objfile); - TYPE_FLAGS (*tpp) |= TYPE_FLAG_STUB; - return result; - } - - /* mips cc uses an escaped rn->index of 0 for struct return types - of procedures that were compiled without -g. These will always remain - undefined. */ - if (rn->rfd == 0xfff && rn->index == 0) - { - *pname = ""; - return result; - } - - /* Find the relative file descriptor and the symbol in it. */ - fh = get_rfd (fd, rf); - xref_fd = fh - ecoff_data (cur_bfd)->fdr; - - if (rn->index >= fh->csym) - { - /* File indirect entry is corrupt. */ - *pname = ""; - complain (&bad_rfd_entry_complaint, - sym_name, xref_fd, rn->index); - return result; - } - - /* If we have processed this symbol then we left a forwarding - pointer to the type in the pending list. If not, we`ll put - it in a list of pending types, to be processed later when - the file will be. In any event, we collect the name for the - type here. */ - - esh = ((char *) ecoff_data (cur_bfd)->external_sym - + ((fh->isymBase + rn->index) - * ecoff_backend (cur_bfd)->external_sym_size)); - (*ecoff_backend (cur_bfd)->swap_sym_in) (cur_bfd, esh, &sh); - - /* Make sure that this type of cross reference can be handled. */ - if (sh.sc != scInfo - || (sh.st != stBlock && sh.st != stTypedef - && sh.st != stStruct && sh.st != stUnion - && sh.st != stEnum)) - { - /* File indirect entry is corrupt. */ - *pname = ""; - complain (&bad_rfd_entry_complaint, - sym_name, xref_fd, rn->index); - return result; - } - - *pname = ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss; - - pend = is_pending_symbol (fh, esh); - if (pend) - *tpp = pend->t; - else - { - /* We have not yet seen this type. */ - - if (sh.iss == 0 && sh.st == stTypedef) - { - TIR tir; - - /* alpha cc puts out a stTypedef with a sh.iss of zero for - two cases: - a) forward declarations of structs/unions/enums which are not - defined in this compilation unit. - For these the type will be void. This is a bad design decision - as cross referencing across compilation units is impossible - due to the missing name. - b) forward declarations of structs/unions/enums which are defined - later in this file or in another file in the same compilation - unit. Simply cross reference those again to get the - true type. - The forward references are not entered in the pending list and - in the symbol table. */ - - ecoff_swap_tir_in (bigend, - &(ecoff_data (cur_bfd)->external_aux - + fh->iauxBase + sh.index)->a_ti, - &tir); - if (tir.tq0 != tqNil) - complain (&illegal_forward_tq0_complaint, sym_name); - switch (tir.bt) - { - case btVoid: - *tpp = init_type (type_code, 0, 0, (char *) NULL, - current_objfile); - *pname = ""; - break; - - case btStruct: - case btUnion: - case btEnum: - cross_ref (xref_fd, - (ecoff_data (cur_bfd)->external_aux - + fh->iauxBase + sh.index + 1), - tpp, type_code, pname, - fh->fBigendian, sym_name); - break; - - default: - complain (&illegal_forward_bt_complaint, tir.bt, sym_name); - *tpp = init_type (type_code, 0, 0, (char *) NULL, - current_objfile); - break; - } - return result; - } - else if (sh.st == stTypedef) - { - /* Parse the type for a normal typedef. This might recursively call - cross_ref till we get a non typedef'ed type. - FIXME: This is not correct behaviour, but gdb currently - cannot handle typedefs without type copying. But type copying is - impossible as we might have mutual forward references between - two files and the copied type would not get filled in when - we later parse its definition. */ - *tpp = parse_type (xref_fd, - ecoff_data (cur_bfd)->external_aux + fh->iauxBase, - sh.index, - (int *)NULL, - fh->fBigendian, - (ecoff_data (cur_bfd)->ss - + fh->issBase + sh.iss)); - } - else - { - /* Cross reference to a struct/union/enum which is defined - in another file in the same compilation unit but that file - has not been parsed yet. - Initialize the type only, it will be filled in when - it's definition is parsed. */ - *tpp = init_type (type_code, 0, 0, (char *) NULL, current_objfile); - } - add_pending (fh, esh, *tpp); - } - - /* We used one auxent normally, two if we got a "next one" rf. */ - return result; -} - - -/* Quick&dirty lookup procedure, to avoid the MI ones that require - keeping the symtab sorted */ - -static struct symbol * -mylookup_symbol (name, block, namespace, class) - char *name; - register struct block *block; - enum namespace namespace; - enum address_class class; -{ - register int bot, top, inc; - register struct symbol *sym; - - bot = 0; - top = BLOCK_NSYMS (block); - inc = name[0]; - while (bot < top) - { - sym = BLOCK_SYM (block, bot); - if (SYMBOL_NAME (sym)[0] == inc - && SYMBOL_NAMESPACE (sym) == namespace - && SYMBOL_CLASS (sym) == class - && strcmp (SYMBOL_NAME (sym), name) == 0) - return sym; - bot++; - } - block = BLOCK_SUPERBLOCK (block); - if (block) - return mylookup_symbol (name, block, namespace, class); - return 0; -} - - -/* Add a new symbol S to a block B. - Infrequently, we will need to reallocate the block to make it bigger. - We only detect this case when adding to top_stack->cur_block, since - that's the only time we know how big the block is. FIXME. */ - -static void -add_symbol (s, b) - struct symbol *s; - struct block *b; -{ - int nsyms = BLOCK_NSYMS (b)++; - struct block *origb; - struct parse_stack *stackp; - - if (b == top_stack->cur_block && - nsyms >= top_stack->maxsyms) - { - complain (&block_overflow_complaint, SYMBOL_NAME (s)); - /* In this case shrink_block is actually grow_block, since - BLOCK_NSYMS(b) is larger than its current size. */ - origb = b; - b = shrink_block (top_stack->cur_block, top_stack->cur_st); - - /* Now run through the stack replacing pointers to the - original block. shrink_block has already done this - for the blockvector and BLOCK_FUNCTION. */ - for (stackp = top_stack; stackp; stackp = stackp->next) - { - if (stackp->cur_block == origb) - { - stackp->cur_block = b; - stackp->maxsyms = BLOCK_NSYMS (b); - } - } - } - BLOCK_SYM (b, nsyms) = s; -} - -/* Add a new block B to a symtab S */ - -static void -add_block (b, s) - struct block *b; - struct symtab *s; -{ - struct blockvector *bv = BLOCKVECTOR (s); - - bv = (struct blockvector *) xrealloc ((PTR) bv, - (sizeof (struct blockvector) - + BLOCKVECTOR_NBLOCKS (bv) - * sizeof (bv->block))); - if (bv != BLOCKVECTOR (s)) - BLOCKVECTOR (s) = bv; - - BLOCKVECTOR_BLOCK (bv, BLOCKVECTOR_NBLOCKS (bv)++) = b; -} - -/* Add a new linenumber entry (LINENO,ADR) to a linevector LT. - MIPS' linenumber encoding might need more than one byte - to describe it, LAST is used to detect these continuation lines. - - Combining lines with the same line number seems like a bad idea. - E.g: There could be a line number entry with the same line number after the - prologue and GDB should not ignore it (this is a better way to find - a prologue than mips_skip_prologue). - But due to the compressed line table format there are line number entries - for the same line which are needed to bridge the gap to the next - line number entry. These entries have a bogus address info with them - and we are unable to tell them from intended duplicate line number - entries. - This is another reason why -ggdb debugging format is preferable. */ - -static int -add_line (lt, lineno, adr, last) - struct linetable *lt; - int lineno; - CORE_ADDR adr; - int last; -{ - if (last == 0) - last = -2; /* make sure we record first line */ - - if (last == lineno) /* skip continuation lines */ - return lineno; - - lt->item[lt->nitems].line = lineno; - lt->item[lt->nitems++].pc = adr << 2; - return lineno; -} - -/* Sorting and reordering procedures */ - -/* Blocks with a smaller low bound should come first */ - -static int -compare_blocks (arg1, arg2) - const PTR arg1; - const PTR arg2; -{ - register int addr_diff; - struct block **b1 = (struct block **) arg1; - struct block **b2 = (struct block **) arg2; - - addr_diff = (BLOCK_START ((*b1))) - (BLOCK_START ((*b2))); - if (addr_diff == 0) - return (BLOCK_END ((*b2))) - (BLOCK_END ((*b1))); - return addr_diff; -} - -/* Sort the blocks of a symtab S. - Reorder the blocks in the blockvector by code-address, - as required by some MI search routines */ - -static void -sort_blocks (s) - struct symtab *s; -{ - struct blockvector *bv = BLOCKVECTOR (s); - - if (BLOCKVECTOR_NBLOCKS (bv) <= 2) - { - /* Cosmetic */ - if (BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) == 0) - BLOCK_START (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) = 0; - if (BLOCK_END (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) == 0) - BLOCK_START (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) = 0; - return; - } - /* - * This is very unfortunate: normally all functions are compiled in - * the order they are found, but if the file is compiled -O3 things - * are very different. It would be nice to find a reliable test - * to detect -O3 images in advance. - */ - if (BLOCKVECTOR_NBLOCKS (bv) > 3) - qsort (&BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK), - BLOCKVECTOR_NBLOCKS (bv) - FIRST_LOCAL_BLOCK, - sizeof (struct block *), - compare_blocks); - - { - register CORE_ADDR high = 0; - register int i, j = BLOCKVECTOR_NBLOCKS (bv); - - for (i = FIRST_LOCAL_BLOCK; i < j; i++) - if (high < BLOCK_END (BLOCKVECTOR_BLOCK (bv, i))) - high = BLOCK_END (BLOCKVECTOR_BLOCK (bv, i)); - BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) = high; - } - - BLOCK_START (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) = - BLOCK_START (BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK)); - - BLOCK_START (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) = - BLOCK_START (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)); - BLOCK_END (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) = - BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)); -} - - -/* Constructor/restructor/destructor procedures */ - -/* Allocate a new symtab for NAME. Needs an estimate of how many symbols - MAXSYMS and linenumbers MAXLINES we'll put in it */ - -static struct symtab * -new_symtab (name, maxsyms, maxlines, objfile) - char *name; - int maxsyms; - int maxlines; - struct objfile *objfile; -{ - struct symtab *s = allocate_symtab (name, objfile); - - LINETABLE (s) = new_linetable (maxlines); - - /* All symtabs must have at least two blocks */ - BLOCKVECTOR (s) = new_bvect (2); - BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK) = new_block (maxsyms); - BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK) = new_block (maxsyms); - BLOCK_SUPERBLOCK (BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)) = - BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); - - s->free_code = free_linetable; - - return (s); -} - -/* Allocate a new partial_symtab NAME */ - -static struct partial_symtab * -new_psymtab (name, objfile) - char *name; - struct objfile *objfile; -{ - struct partial_symtab *psymtab; - - psymtab = allocate_psymtab (name, objfile); - - /* Keep a backpointer to the file's symbols */ - - psymtab->read_symtab_private = ((char *) - obstack_alloc (&objfile->psymbol_obstack, - sizeof (struct symloc))); - memset ((PTR) psymtab->read_symtab_private, 0, sizeof (struct symloc)); - CUR_BFD (psymtab) = cur_bfd; - - /* The way to turn this into a symtab is to call... */ - psymtab->read_symtab = mipscoff_psymtab_to_symtab; - return (psymtab); -} - - -/* Allocate a linetable array of the given SIZE. Since the struct - already includes one item, we subtract one when calculating the - proper size to allocate. */ - -static struct linetable * -new_linetable (size) - int size; -{ - struct linetable *l; - - size = (size - 1) * sizeof (l->item) + sizeof (struct linetable); - l = (struct linetable *) xmalloc (size); - l->nitems = 0; - return l; -} - -/* Oops, too big. Shrink it. This was important with the 2.4 linetables, - I am not so sure about the 3.4 ones. - - Since the struct linetable already includes one item, we subtract one when - calculating the proper size to allocate. */ - -static struct linetable * -shrink_linetable (lt) - struct linetable *lt; -{ - - return (struct linetable *) xrealloc ((PTR) lt, - (sizeof (struct linetable) - + ((lt->nitems - 1) - * sizeof (lt->item)))); -} - -/* Allocate and zero a new blockvector of NBLOCKS blocks. */ - -static struct blockvector * -new_bvect (nblocks) - int nblocks; -{ - struct blockvector *bv; - int size; - - size = sizeof (struct blockvector) + nblocks * sizeof (struct block *); - bv = (struct blockvector *) xzalloc (size); - - BLOCKVECTOR_NBLOCKS (bv) = nblocks; - - return bv; -} - -/* Allocate and zero a new block of MAXSYMS symbols */ - -static struct block * -new_block (maxsyms) - int maxsyms; -{ - int size = sizeof (struct block) + (maxsyms - 1) * sizeof (struct symbol *); - - return (struct block *) xzalloc (size); -} - -/* Ooops, too big. Shrink block B in symtab S to its minimal size. - Shrink_block can also be used by add_symbol to grow a block. */ - -static struct block * -shrink_block (b, s) - struct block *b; - struct symtab *s; -{ - struct block *new; - struct blockvector *bv = BLOCKVECTOR (s); - int i; - - /* Just reallocate it and fix references to the old one */ - - new = (struct block *) xrealloc ((PTR) b, - (sizeof (struct block) - + ((BLOCK_NSYMS (b) - 1) - * sizeof (struct symbol *)))); - - /* Should chase pointers to old one. Fortunately, that`s just - the block`s function and inferior blocks */ - if (BLOCK_FUNCTION (new) && SYMBOL_BLOCK_VALUE (BLOCK_FUNCTION (new)) == b) - SYMBOL_BLOCK_VALUE (BLOCK_FUNCTION (new)) = new; - for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); i++) - if (BLOCKVECTOR_BLOCK (bv, i) == b) - BLOCKVECTOR_BLOCK (bv, i) = new; - else if (BLOCK_SUPERBLOCK (BLOCKVECTOR_BLOCK (bv, i)) == b) - BLOCK_SUPERBLOCK (BLOCKVECTOR_BLOCK (bv, i)) = new; - return new; -} - -/* Create a new symbol with printname NAME */ - -static struct symbol * -new_symbol (name) - char *name; -{ - struct symbol *s = ((struct symbol *) - obstack_alloc (¤t_objfile->symbol_obstack, - sizeof (struct symbol))); - - memset ((PTR) s, 0, sizeof (*s)); - SYMBOL_NAME (s) = name; - SYMBOL_LANGUAGE (s) = psymtab_language; - SYMBOL_INIT_DEMANGLED_NAME (s, ¤t_objfile->symbol_obstack); - return s; -} - -/* Create a new type with printname NAME */ - -static struct type * -new_type (name) - char *name; -{ - struct type *t; - - t = alloc_type (current_objfile); - TYPE_NAME (t) = name; - TYPE_CPLUS_SPECIFIC (t) = (struct cplus_struct_type *) &cplus_struct_default; - return t; -} - - -/* Things used for calling functions in the inferior. - These functions are exported to our companion - mips-tdep.c file and are here because they play - with the symbol-table explicitly. */ - -/* Sigtramp: make sure we have all the necessary information - about the signal trampoline code. Since the official code - from MIPS does not do so, we make up that information ourselves. - If they fix the library (unlikely) this code will neutralize itself. */ - -static void -fixup_sigtramp () -{ - struct symbol *s; - struct symtab *st; - struct block *b, *b0 = NULL; - - sigtramp_address = -1; - - /* We have to handle the following cases here: - a) The Mips library has a sigtramp label within sigvec. - b) Irix has a _sigtramp which we want to use, but it also has sigvec. */ - s = lookup_symbol ("sigvec", 0, VAR_NAMESPACE, 0, NULL); - if (s != 0) - { - b0 = SYMBOL_BLOCK_VALUE (s); - s = lookup_symbol ("sigtramp", b0, VAR_NAMESPACE, 0, NULL); - } - if (s == 0) - { - /* No sigvec or no sigtramp inside sigvec, try _sigtramp. */ - s = lookup_symbol ("_sigtramp", 0, VAR_NAMESPACE, 0, NULL); - } - - /* But maybe this program uses its own version of sigvec */ - if (s == 0) - return; - - /* Did we or MIPSco fix the library ? */ - if (SYMBOL_CLASS (s) == LOC_BLOCK) - { - sigtramp_address = BLOCK_START (SYMBOL_BLOCK_VALUE (s)); - sigtramp_end = BLOCK_END (SYMBOL_BLOCK_VALUE (s)); - return; - } - - sigtramp_address = SYMBOL_VALUE (s); - sigtramp_end = sigtramp_address + 0x88; /* black magic */ - - /* But what symtab does it live in ? */ - st = find_pc_symtab (SYMBOL_VALUE (s)); - - /* - * Ok, there goes the fix: turn it into a procedure, with all the - * needed info. Note we make it a nested procedure of sigvec, - * which is the way the (assembly) code is actually written. - */ - SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; - SYMBOL_CLASS (s) = LOC_BLOCK; - SYMBOL_TYPE (s) = init_type (TYPE_CODE_FUNC, 4, 0, (char *) NULL, - st->objfile); - TYPE_TARGET_TYPE (SYMBOL_TYPE (s)) = builtin_type_void; - - /* Need a block to allocate MIPS_EFI_SYMBOL_NAME in */ - b = new_block (1); - SYMBOL_BLOCK_VALUE (s) = b; - BLOCK_START (b) = sigtramp_address; - BLOCK_END (b) = sigtramp_end; - BLOCK_FUNCTION (b) = s; - BLOCK_SUPERBLOCK (b) = BLOCK_SUPERBLOCK (b0); - add_block (b, st); - sort_blocks (st); - - /* Make a MIPS_EFI_SYMBOL_NAME entry for it */ - { - struct mips_extra_func_info *e = - ((struct mips_extra_func_info *) - xzalloc (sizeof (struct mips_extra_func_info))); - - e->numargs = 0; /* the kernel thinks otherwise */ - /* align_longword(sigcontext + SIGFRAME) */ - e->pdr.frameoffset = 0x150; - e->pdr.framereg = SP_REGNUM; - /* read_next_frame_reg provides the true pc at the time of signal */ - e->pdr.pcreg = PC_REGNUM; - e->pdr.regmask = -2; - e->pdr.regoffset = -(41 * sizeof (int)); - e->pdr.fregmask = -1; - e->pdr.fregoffset = -(7 * sizeof (int)); - e->pdr.isym = (long) s; - e->pdr.adr = sigtramp_address; - - current_objfile = st->objfile; /* Keep new_symbol happy */ - s = new_symbol (MIPS_EFI_SYMBOL_NAME); - SYMBOL_VALUE (s) = (long) e; - SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE; - SYMBOL_CLASS (s) = LOC_CONST; - SYMBOL_TYPE (s) = builtin_type_void; - current_objfile = NULL; - } - - BLOCK_SYM (b, BLOCK_NSYMS (b)++) = s; -} - - /* Fake up identical offsets for all sections. */ -struct section_offsets * +static struct section_offsets * mipscoff_symfile_offsets (objfile, addr) struct objfile *objfile; CORE_ADDR addr; @@ -3591,6 +140,7 @@ mipscoff_symfile_offsets (objfile, addr) struct section_offsets *section_offsets; int i; + objfile->num_sections = SECT_OFF_MAX; section_offsets = ((struct section_offsets *) obstack_alloc (&objfile->psymbol_obstack, (sizeof (struct section_offsets) @@ -3602,13 +152,296 @@ mipscoff_symfile_offsets (objfile, addr) return section_offsets; } - + +/* Alpha OSF/1 encapsulates the dynamic symbols in ELF format in a + standard coff section. The ELF format for the symbols differs from + the format defined in elf/external.h. It seems that a normal ELF 32 bit + format is used, and the representation only changes because longs are + 64 bit on the alpha. In addition, the handling of text/data section + indices for symbols is different from the ELF ABI. + As the BFD linker currently does not support dynamic linking on the alpha, + there seems to be no reason to pollute BFD with another mixture of object + file formats for now. */ + +/* Format of an alpha external ELF symbol. */ + +typedef struct { + unsigned char st_name[4]; /* Symbol name, index in string tbl */ + unsigned char st_pad[4]; /* Pad to long word boundary */ + unsigned char st_value[8]; /* Value of the symbol */ + unsigned char st_size[4]; /* Associated symbol size */ + unsigned char st_info[1]; /* Type and binding attributes */ + unsigned char st_other[1]; /* No defined meaning, 0 */ + unsigned char st_shndx[2]; /* Associated section index */ +} Elfalpha_External_Sym; + +/* Format of an alpha external ELF dynamic info structure. */ + +typedef struct { + unsigned char d_tag[4]; /* Tag */ + unsigned char d_pad[4]; /* Pad to long word boundary */ + union { + unsigned char d_ptr[8]; /* Pointer value */ + unsigned char d_val[4]; /* Integer value */ + } d_un; +} Elfalpha_External_Dyn; + +/* Struct to obtain the section pointers for alpha dynamic symbol info. */ + +struct alphacoff_dynsecinfo { + asection *sym_sect; /* Section pointer for .dynsym section */ + asection *str_sect; /* Section pointer for .dynstr section */ + asection *dyninfo_sect; /* Section pointer for .dynamic section */ + asection *got_sect; /* Section pointer for .got section */ +}; + +static void +alphacoff_locate_sections PARAMS ((bfd *, asection *, void *)); + +/* We are called once per section from read_alphacoff_dynamic_symtab. + We need to examine each section we are passed, check to see + if it is something we are interested in processing, and + if so, stash away some access information for the section. */ + +static void +alphacoff_locate_sections (ignore_abfd, sectp, sip) + bfd *ignore_abfd; + asection *sectp; + PTR sip; +{ + register struct alphacoff_dynsecinfo *si; + + si = (struct alphacoff_dynsecinfo *) sip; + + if (STREQ (sectp->name, ".dynsym")) + { + si->sym_sect = sectp; + } + else if (STREQ (sectp->name, ".dynstr")) + { + si->str_sect = sectp; + } + else if (STREQ (sectp->name, ".dynamic")) + { + si->dyninfo_sect = sectp; + } + else if (STREQ (sectp->name, ".got")) + { + si->got_sect = sectp; + } +} + +/* Scan an alpha dynamic symbol table for symbols of interest and + add them to the minimal symbol table. */ + +static void +read_alphacoff_dynamic_symtab (section_offsets, objfile) + struct section_offsets *section_offsets; + struct objfile *objfile; +{ + bfd *abfd = objfile->obfd; + struct alphacoff_dynsecinfo si; + char *sym_secptr; + char *str_secptr; + char *dyninfo_secptr; + char *got_secptr; + bfd_size_type sym_secsize; + bfd_size_type str_secsize; + bfd_size_type dyninfo_secsize; + bfd_size_type got_secsize; + int sym_count; + int i; + int stripped; + Elfalpha_External_Sym *x_symp; + char *dyninfo_p; + char *dyninfo_end; + int got_entry_size = 8; + int dt_mips_local_gotno = -1; + int dt_mips_gotsym = -1; + + + /* We currently only know how to handle alpha dynamic symbols. */ + if (bfd_get_arch (abfd) != bfd_arch_alpha) + return; + + /* Locate the dynamic symbols sections and read them in. */ + memset ((char *) &si, 0, sizeof (si)); + bfd_map_over_sections (abfd, alphacoff_locate_sections, (PTR) &si); + if (si.sym_sect == NULL + || si.str_sect == NULL + || si.dyninfo_sect == NULL + || si.got_sect == NULL) + return; + + sym_secsize = bfd_get_section_size_before_reloc (si.sym_sect); + str_secsize = bfd_get_section_size_before_reloc (si.str_sect); + dyninfo_secsize = bfd_get_section_size_before_reloc (si.dyninfo_sect); + got_secsize = bfd_get_section_size_before_reloc (si.got_sect); + sym_secptr = alloca (sym_secsize); + str_secptr = alloca (str_secsize); + dyninfo_secptr = alloca (dyninfo_secsize); + got_secptr = alloca (got_secsize); + + if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr, + (file_ptr)0, sym_secsize)) + return; + if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr, + (file_ptr)0, str_secsize)) + return; + if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr, + (file_ptr)0, dyninfo_secsize)) + return; + if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr, + (file_ptr)0, got_secsize)) + return; + + /* Find the number of local GOT entries and the index for the + the first dynamic symbol in the GOT. */ + for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize; + dyninfo_p < dyninfo_end; + dyninfo_p += sizeof (Elfalpha_External_Dyn)) + { + Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *)dyninfo_p; + long dyn_tag; + + dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag); + if (dyn_tag == DT_NULL) + break; + else if (dyn_tag == DT_MIPS_LOCAL_GOTNO) + { + dt_mips_local_gotno = bfd_h_get_32 (abfd, + (bfd_byte *) x_dynp->d_un.d_val); + } + else if (dyn_tag == DT_MIPS_GOTSYM) + { + dt_mips_gotsym = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val); + } + } + if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0) + return; + + /* Scan all dynamic symbols and enter them into the minimal symbol table + if appropriate. */ + sym_count = sym_secsize / sizeof (Elfalpha_External_Sym); + stripped = (bfd_get_symcount (abfd) == 0); + + /* Skip first symbol, which is a null dummy. */ + for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1; + i < sym_count; + i++, x_symp++) + { + unsigned long strx; + char *name; + bfd_vma sym_value; + unsigned char sym_info; + unsigned int sym_shndx; + int isglobal; + enum minimal_symbol_type ms_type; + + strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name); + if (strx >= str_secsize) + continue; + name = str_secptr + strx; + if (*name == '\0' || *name == '.') + continue; + + sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value); + sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info); + sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx); + isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL); + + if (sym_shndx == SHN_UNDEF) + { + /* Handle undefined functions which are defined in a shared + library. */ + if (ELF_ST_TYPE (sym_info) != STT_FUNC + || ELF_ST_BIND (sym_info) != STB_GLOBAL) + continue; + + ms_type = mst_solib_trampoline; + + /* If sym_value is nonzero, it points to the shared library + trampoline entry, which is what we are looking for. + + If sym_value is zero, then we have to get the GOT entry + for the symbol. + If the GOT entry is nonzero, it represents the quickstart + address of the function and we use that as the symbol value. + + If the GOT entry is zero, the function address has to be resolved + by the runtime loader before the executable is started. + We are unable to find any meaningful address for these + functions in the executable file, so we skip them. */ + if (sym_value == 0) + { + int got_entry_offset = + (i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size; + + if (got_entry_offset < 0 || got_entry_offset >= got_secsize) + continue; + sym_value = + bfd_h_get_64 (abfd, + (bfd_byte *) (got_secptr + got_entry_offset)); + if (sym_value == 0) + continue; + } + } + else + { + /* Symbols defined in the executable itself. We only care about + them if this is a stripped executable, otherwise they have + been retrieved from the normal symbol table already. */ + if (!stripped) + continue; + + if (sym_shndx == SHN_MIPS_TEXT) + { + if (isglobal) + ms_type = mst_text; + else + ms_type = mst_file_text; + sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT); + } + else if (sym_shndx == SHN_MIPS_DATA) + { + if (isglobal) + ms_type = mst_data; + else + ms_type = mst_file_data; + sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA); + } + else if (sym_shndx == SHN_MIPS_ACOMMON) + { + if (isglobal) + ms_type = mst_bss; + else + ms_type = mst_file_bss; + sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS); + } + else if (sym_shndx == SHN_ABS) + { + ms_type = mst_abs; + } + else + { + continue; + } + } + + prim_record_minimal_symbol (obsavestring (name, + strlen (name), + &objfile -> symbol_obstack), + sym_value, + ms_type, + objfile); + } +} + /* Initialization */ static struct sym_fns ecoff_sym_fns = { - "ecoff", /* sym_name: name or name prefix of BFD target type */ - 5, /* sym_namelen: number of significant sym_name chars */ + bfd_target_ecoff_flavour, mipscoff_new_init, /* sym_new_init: init anything gbl to entire symtab */ mipscoff_symfile_init, /* sym_init: read initial info, setup for sym_read() */ mipscoff_symfile_read, /* sym_read: read a symbol file into symtab */ @@ -3617,37 +450,8 @@ static struct sym_fns ecoff_sym_fns = NULL /* next: pointer to next struct sym_fns */ }; - void _initialize_mipsread () { add_symtab_fns (&ecoff_sym_fns); - - /* Missing basic types */ - - builtin_type_string = - init_type (TYPE_CODE_STRING, - TARGET_CHAR_BIT / TARGET_CHAR_BIT, - 0, "string", - (struct objfile *) NULL); - builtin_type_complex = - init_type (TYPE_CODE_FLT, - TARGET_COMPLEX_BIT / TARGET_CHAR_BIT, - 0, "complex", - (struct objfile *) NULL); - builtin_type_double_complex = - init_type (TYPE_CODE_FLT, - TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT, - 0, "double complex", - (struct objfile *) NULL); - builtin_type_fixed_dec = - init_type (TYPE_CODE_INT, - TARGET_INT_BIT / TARGET_CHAR_BIT, - 0, "fixed decimal", - (struct objfile *) NULL); - builtin_type_float_dec = - init_type (TYPE_CODE_FLT, - TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, - 0, "floating decimal", - (struct objfile *) NULL); } diff --git a/gnu/usr.bin/gdb/gdb/nlmread.c b/gnu/usr.bin/gdb/gdb/nlmread.c index fde3af249328..7ba977a87cbb 100644 --- a/gnu/usr.bin/gdb/gdb/nlmread.c +++ b/gnu/usr.bin/gdb/gdb/nlmread.c @@ -1,5 +1,5 @@ /* Read NLM (NetWare Loadable Module) format executable files for GDB. - Copyright 1993 Free Software Foundation, Inc. + Copyright 1993, 1994 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support (fnf@cygnus.com). This file is part of GDB. @@ -19,11 +19,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" +#include #include "bfd.h" #include "symtab.h" #include "symfile.h" #include "objfiles.h" #include "gdb-stabs.h" +#include "buildsym.h" +#include "stabsread.h" static void nlm_new_init PARAMS ((struct objfile *)); @@ -87,7 +90,7 @@ record_minimal_symbol (name, address, ms_type, objfile) struct objfile *objfile; { name = obsavestring (name, strlen (name), &objfile -> symbol_obstack); - prim_record_minimal_symbol (name, address, ms_type); + prim_record_minimal_symbol (name, address, ms_type, objfile); } @@ -116,50 +119,49 @@ nlm_symtab_read (abfd, addr, objfile) CORE_ADDR addr; struct objfile *objfile; { - unsigned int storage_needed; + long storage_needed; asymbol *sym; asymbol **symbol_table; - unsigned int number_of_symbols; - unsigned int i; + long number_of_symbols; + long i; struct cleanup *back_to; CORE_ADDR symaddr; enum minimal_symbol_type ms_type; - storage_needed = get_symtab_upper_bound (abfd); + storage_needed = bfd_get_symtab_upper_bound (abfd); + if (storage_needed < 0) + error ("Can't read symbols from %s: %s", bfd_get_filename (abfd), + bfd_errmsg (bfd_get_error ())); if (storage_needed > 0) { symbol_table = (asymbol **) xmalloc (storage_needed); back_to = make_cleanup (free, symbol_table); number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); + if (number_of_symbols < 0) + error ("Can't read symbols from %s: %s", bfd_get_filename (abfd), + bfd_errmsg (bfd_get_error ())); for (i = 0; i < number_of_symbols; i++) { sym = symbol_table[i]; - if (sym -> flags & BSF_GLOBAL) + if (/*sym -> flags & BSF_GLOBAL*/ 1) { /* Bfd symbols are section relative. */ symaddr = sym -> value + sym -> section -> vma; /* Relocate all non-absolute symbols by base address. */ if (sym -> section != &bfd_abs_section) - { - symaddr += addr; - } + symaddr += addr; /* For non-absolute symbols, use the type of the section - they are relative to, to intuit text/data. Bfd provides + they are relative to, to intuit text/data. BFD provides no way of figuring this out for absolute symbols. */ if (sym -> section -> flags & SEC_CODE) - { - ms_type = mst_text; - } + ms_type = mst_text; else if (sym -> section -> flags & SEC_DATA) - { - ms_type = mst_data; - } + ms_type = mst_data; else - { - ms_type = mst_unknown; - } + ms_type = mst_unknown; + record_minimal_symbol ((char *) sym -> name, symaddr, ms_type, objfile); } @@ -205,6 +207,7 @@ nlm_symfile_read (objfile, section_offsets, mainline) bfd *abfd = objfile -> obfd; struct cleanup *back_to; CORE_ADDR offset; + struct symbol *mainsym; init_minimal_symbol_collection (); back_to = make_cleanup (discard_minimal_symbols, 0); @@ -218,16 +221,21 @@ nlm_symfile_read (objfile, section_offsets, mainline) nlm_symtab_read (abfd, offset, objfile); + stabsect_build_psymtabs (objfile, section_offsets, mainline, ".stab", + ".stabstr", ".text"); + + mainsym = lookup_symbol ("main", NULL, VAR_NAMESPACE, NULL, NULL); + + if (mainsym + && SYMBOL_CLASS(mainsym) == LOC_BLOCK) + { + objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym)); + objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym)); + } + /* FIXME: We could locate and read the optional native debugging format here and add the symbols to the minimal symbol table. */ - if (!have_partial_symbols ()) - { - wrap_here (""); - printf_filtered ("(no debugging symbols found)..."); - wrap_here (""); - } - /* Install any minimal symbols that have been collected as the current minimal symbols for this objfile. */ @@ -264,7 +272,8 @@ nlm_symfile_offsets (objfile, addr) { struct section_offsets *section_offsets; int i; - + + objfile->num_sections = SECT_OFF_MAX; section_offsets = (struct section_offsets *) obstack_alloc (&objfile -> psymbol_obstack, sizeof (struct section_offsets) + @@ -279,12 +288,11 @@ nlm_symfile_offsets (objfile, addr) } -/* Register that we are able to handle NLM file format. */ +/* Register that we are able to handle NLM file format. */ static struct sym_fns nlm_sym_fns = { - "nlm", /* sym_name: name or name prefix of BFD target type */ - 3, /* sym_namelen: number of significant sym_name chars */ + bfd_target_nlm_flavour, nlm_new_init, /* sym_new_init: init anything gbl to entire symtab */ nlm_symfile_init, /* sym_init: read initial info, setup for sym_read() */ nlm_symfile_read, /* sym_read: read a symbol file into symtab */ diff --git a/gnu/usr.bin/gdb/gdb/nm.h b/gnu/usr.bin/gdb/gdb/nm.h index a7af00f33d87..65c73372a038 100644 --- a/gnu/usr.bin/gdb/gdb/nm.h +++ b/gnu/usr.bin/gdb/gdb/nm.h @@ -40,5 +40,61 @@ extern int i386_register_u_addr PARAMS ((int, int)); #define PTRACE_ARG3_TYPE char* +#define ATTACH_DETACH +#define KERNEL_DEBUG + +/* make structure definitions match up with those expected in solib.c */ + +#define link_object sod +#define lo_name sod_name +#define lo_library sod_library +#define lo_unused sod_reserved +#define lo_major sod_major +#define lo_minor sod_minor +#define lo_next sod_next + +#define link_map so_map +#define lm_addr som_addr +#define lm_name som_path +#define lm_next som_next +#define lm_lop som_sod +#define lm_lob som_sodbase +#define lm_rwt som_write +#define lm_ld som_dynamic +#define lm_lpd som_spd + +#define link_dynamic_2 section_dispatch_table +#define ld_loaded sdt_loaded +#define ld_need sdt_sods +#define ld_rules sdt_filler1 +#define ld_got sdt_got +#define ld_plt sdt_plt +#define ld_rel sdt_rel +#define ld_hash sdt_hash +#define ld_stab sdt_nzlist +#define ld_stab_hash sdt_filler2 +#define ld_buckets sdt_buckets +#define ld_symbols sdt_strings +#define ld_symb_size sdt_str_sz +#define ld_text sdt_text_sz +#define ld_plt_sz sdt_plt_sz + +#define rtc_symb rt_symbol +#define rtc_sp rt_sp +#define rtc_next rt_next + +#define ld_debug so_debug +#define ldd_version dd_version +#define ldd_in_debugger dd_in_debugger +#define ldd_sym_loaded dd_sym_loaded +#define ldd_bp_addr dd_bpt_addr +#define ldd_bp_inst dd_bpt_shadow +#define ldd_cp dd_cc + +#define link_dynamic _dynamic +#define ld_version d_version +#define ldd d_debug +#define ld_un d_un +#define ld_2 d_sdt #endif /* NM_FREEBSD_H */ diff --git a/gnu/usr.bin/gdb/gdb/objfiles.c b/gnu/usr.bin/gdb/gdb/objfiles.c index b111f005c05d..5e9e35467816 100644 --- a/gnu/usr.bin/gdb/gdb/objfiles.c +++ b/gnu/usr.bin/gdb/gdb/objfiles.c @@ -77,14 +77,13 @@ add_to_objfile_sections (abfd, asect, objfile_p_char) flagword aflag; aflag = bfd_get_section_flags (abfd, asect); - /* FIXME, we need to handle BSS segment here...it alloc's but doesn't load */ - if (!(aflag & SEC_LOAD)) + if (!(aflag & SEC_ALLOC)) return; if (0 == bfd_section_size (abfd, asect)) return; section.offset = 0; section.objfile = objfile; - section.sec_ptr = asect; + section.the_bfd_section = asect; section.addr = bfd_section_vma (abfd, asect); section.endaddr = section.addr + bfd_section_size (abfd, asect); obstack_grow (&objfile->psymbol_obstack, §ion, sizeof(section)); @@ -92,14 +91,18 @@ add_to_objfile_sections (abfd, asect, objfile_p_char) } /* Builds a section table for OBJFILE. - Returns 0 if OK, 1 on error. */ + Returns 0 if OK, 1 on error (in which case bfd_error contains the + error). */ -static int +int build_objfile_section_table (objfile) struct objfile *objfile; { - if (objfile->sections) - abort(); + /* objfile->sections can be already set when reading a mapped symbol + file. I believe that we do need to rebuild the section table in + this case (we rebuild other things derived from the bfd), but we + can't free the old one (it's in the psymbol_obstack). So we just + waste some memory. */ objfile->sections_end = 0; bfd_map_over_sections (objfile->obfd, add_to_objfile_sections, (char *)objfile); @@ -120,79 +123,88 @@ allocate_objfile (abfd, mapped) int mapped; { struct objfile *objfile = NULL; - int fd; - PTR md; - CORE_ADDR mapto; mapped |= mapped_symbol_files; #if !defined(NO_MMALLOC) && defined(HAVE_MMAP) + { - /* If we can support mapped symbol files, try to open/reopen the mapped file - that corresponds to the file from which we wish to read symbols. If the - objfile is to be mapped, we must malloc the structure itself using the - mmap version, and arrange that all memory allocation for the objfile uses - the mmap routines. If we are reusing an existing mapped file, from which - we get our objfile pointer, we have to make sure that we update the - pointers to the alloc/free functions in the obstack, in case these - functions have moved within the current gdb. */ + /* If we can support mapped symbol files, try to open/reopen the + mapped file that corresponds to the file from which we wish to + read symbols. If the objfile is to be mapped, we must malloc + the structure itself using the mmap version, and arrange that + all memory allocation for the objfile uses the mmap routines. + If we are reusing an existing mapped file, from which we get + our objfile pointer, we have to make sure that we update the + pointers to the alloc/free functions in the obstack, in case + these functions have moved within the current gdb. */ - fd = open_mapped_file (bfd_get_filename (abfd), bfd_get_mtime (abfd), - mapped); - if (fd >= 0) - { - if (((mapto = map_to_address ()) == 0) || - ((md = mmalloc_attach (fd, (PTR) mapto)) == NULL)) - { - close (fd); - } - else if ((objfile = (struct objfile *) mmalloc_getkey (md, 0)) != NULL) - { - /* Update memory corruption handler function addresses. */ - init_malloc (md); - objfile -> md = md; - objfile -> mmfd = fd; - /* Update pointers to functions to *our* copies */ - obstack_chunkfun (&objfile -> psymbol_obstack, xmmalloc); - obstack_freefun (&objfile -> psymbol_obstack, mfree); - obstack_chunkfun (&objfile -> symbol_obstack, xmmalloc); - obstack_freefun (&objfile -> symbol_obstack, mfree); - obstack_chunkfun (&objfile -> type_obstack, xmmalloc); - obstack_freefun (&objfile -> type_obstack, mfree); - /* If already in objfile list, unlink it. */ - unlink_objfile (objfile); - /* Forget things specific to a particular gdb, may have changed. */ - objfile -> sf = NULL; - } - else - { - /* Set up to detect internal memory corruption. MUST be done before - the first malloc. See comments in init_malloc() and mmcheck(). */ - init_malloc (md); - objfile = (struct objfile *) xmmalloc (md, sizeof (struct objfile)); - memset (objfile, 0, sizeof (struct objfile)); - objfile -> md = md; - objfile -> mmfd = fd; - objfile -> flags |= OBJF_MAPPED; - mmalloc_setkey (objfile -> md, 0, objfile); - obstack_specify_allocation_with_arg (&objfile -> psymbol_obstack, - 0, 0, xmmalloc, mfree, - objfile -> md); - obstack_specify_allocation_with_arg (&objfile -> symbol_obstack, - 0, 0, xmmalloc, mfree, - objfile -> md); - obstack_specify_allocation_with_arg (&objfile -> type_obstack, - 0, 0, xmmalloc, mfree, - objfile -> md); - } - } + int fd; - if (mapped && (objfile == NULL)) - { - warning ("symbol table for '%s' will not be mapped", - bfd_get_filename (abfd)); - } + fd = open_mapped_file (bfd_get_filename (abfd), bfd_get_mtime (abfd), + mapped); + if (fd >= 0) + { + CORE_ADDR mapto; + PTR md; + if (((mapto = map_to_address ()) == 0) || + ((md = mmalloc_attach (fd, (PTR) mapto)) == NULL)) + { + close (fd); + } + else if ((objfile = (struct objfile *) mmalloc_getkey (md, 0)) != NULL) + { + /* Update memory corruption handler function addresses. */ + init_malloc (md); + objfile -> md = md; + objfile -> mmfd = fd; + /* Update pointers to functions to *our* copies */ + obstack_chunkfun (&objfile -> psymbol_obstack, xmmalloc); + obstack_freefun (&objfile -> psymbol_obstack, mfree); + obstack_chunkfun (&objfile -> symbol_obstack, xmmalloc); + obstack_freefun (&objfile -> symbol_obstack, mfree); + obstack_chunkfun (&objfile -> type_obstack, xmmalloc); + obstack_freefun (&objfile -> type_obstack, mfree); + /* If already in objfile list, unlink it. */ + unlink_objfile (objfile); + /* Forget things specific to a particular gdb, may have changed. */ + objfile -> sf = NULL; + } + else + { + + /* Set up to detect internal memory corruption. MUST be + done before the first malloc. See comments in + init_malloc() and mmcheck(). */ + + init_malloc (md); + + objfile = (struct objfile *) + xmmalloc (md, sizeof (struct objfile)); + memset (objfile, 0, sizeof (struct objfile)); + objfile -> md = md; + objfile -> mmfd = fd; + objfile -> flags |= OBJF_MAPPED; + mmalloc_setkey (objfile -> md, 0, objfile); + obstack_specify_allocation_with_arg (&objfile -> psymbol_obstack, + 0, 0, xmmalloc, mfree, + objfile -> md); + obstack_specify_allocation_with_arg (&objfile -> symbol_obstack, + 0, 0, xmmalloc, mfree, + objfile -> md); + obstack_specify_allocation_with_arg (&objfile -> type_obstack, + 0, 0, xmmalloc, mfree, + objfile -> md); + } + } + + if (mapped && (objfile == NULL)) + { + warning ("symbol table for '%s' will not be mapped", + bfd_get_filename (abfd)); + } + } #else /* defined(NO_MMALLOC) || !defined(HAVE_MMAP) */ if (mapped) @@ -242,7 +254,7 @@ allocate_objfile (abfd, mapped) if (build_objfile_section_table (objfile)) { error ("Can't find the file sections in `%s': %s", - objfile -> name, bfd_errmsg (bfd_error)); + objfile -> name, bfd_errmsg (bfd_get_error ())); } /* Push this file onto the head of the linked list of other such files. */ @@ -304,8 +316,6 @@ void free_objfile (objfile) struct objfile *objfile; { - int mmfd; - /* First do any symbol file specific actions required when we are finished with a particular symbol file. Note that if the objfile is using reusable symbol information (via mmalloc) then each of @@ -349,6 +359,8 @@ free_objfile (objfile) (t->to_detach) (NULL, 0); } #endif + /* I *think* all our callers call clear_symtab_users. If so, no need + to call this here. */ clear_pc_function_cache (); /* The last thing we do is free the objfile struct itself for the @@ -362,6 +374,8 @@ free_objfile (objfile) { /* Remember the fd so we can close it. We can't close it before doing the detach, and after the detach the objfile is gone. */ + int mmfd; + mmfd = objfile -> mmfd; mmalloc_detach (objfile -> md); objfile = NULL; @@ -436,7 +450,7 @@ objfile_relocate (objfile, new_offsets) { struct symtab *s; - for (s = objfile->symtabs; s; s = s->next) + ALL_OBJFILE_SYMTABS (objfile, s) { struct linetable *l; struct blockvector *bv; @@ -478,6 +492,15 @@ objfile_relocate (objfile, new_offsets) SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (delta, SYMBOL_SECTION (sym)); } +#ifdef MIPS_EFI_SYMBOL_NAME + /* Relocate Extra Function Info for ecoff. */ + + else + if (SYMBOL_CLASS (sym) == LOC_CONST + && SYMBOL_NAMESPACE (sym) == LABEL_NAMESPACE + && STRCMP (SYMBOL_NAME (sym), MIPS_EFI_SYMBOL_NAME) == 0) + ecoff_relocate_efi (sym, ANOFFSET (delta, s->block_line_section)); +#endif } } } @@ -524,6 +547,58 @@ objfile_relocate (objfile, new_offsets) for (i = 0; i < objfile->num_sections; ++i) ANOFFSET (objfile->section_offsets, i) = ANOFFSET (new_offsets, i); } + + { + struct obj_section *s; + bfd *abfd; + + abfd = symfile_objfile->obfd; + + for (s = symfile_objfile->sections; + s < symfile_objfile->sections_end; ++s) + { + flagword flags; + + flags = bfd_get_section_flags (abfd, s->the_bfd_section); + + if (flags & SEC_CODE) + { + s->addr += ANOFFSET (delta, SECT_OFF_TEXT); + s->endaddr += ANOFFSET (delta, SECT_OFF_TEXT); + } + else if (flags & (SEC_DATA | SEC_LOAD)) + { + s->addr += ANOFFSET (delta, SECT_OFF_DATA); + s->endaddr += ANOFFSET (delta, SECT_OFF_DATA); + } + else if (flags & SEC_ALLOC) + { + s->addr += ANOFFSET (delta, SECT_OFF_BSS); + s->endaddr += ANOFFSET (delta, SECT_OFF_BSS); + } + } + } + + if (objfile->ei.entry_point != ~0) + objfile->ei.entry_point += ANOFFSET (delta, SECT_OFF_TEXT); + + if (objfile->ei.entry_func_lowpc != INVALID_ENTRY_LOWPC) + { + objfile->ei.entry_func_lowpc += ANOFFSET (delta, SECT_OFF_TEXT); + objfile->ei.entry_func_highpc += ANOFFSET (delta, SECT_OFF_TEXT); + } + + if (objfile->ei.entry_file_lowpc != INVALID_ENTRY_LOWPC) + { + objfile->ei.entry_file_lowpc += ANOFFSET (delta, SECT_OFF_TEXT); + objfile->ei.entry_file_highpc += ANOFFSET (delta, SECT_OFF_TEXT); + } + + if (objfile->ei.main_func_lowpc != INVALID_ENTRY_LOWPC) + { + objfile->ei.main_func_lowpc += ANOFFSET (delta, SECT_OFF_TEXT); + objfile->ei.main_func_highpc += ANOFFSET (delta, SECT_OFF_TEXT); + } } /* Many places in gdb want to test just to see if we have any partial @@ -627,7 +702,7 @@ open_existing_mapped_file (symsfilename, mtime, mapped) { if (error_pre_print) { - printf (error_pre_print); + printf_unfiltered (error_pre_print); } print_sys_errmsg (symsfilename, errno); } @@ -697,7 +772,7 @@ open_mapped_file (filename, mtime, mapped) { if (error_pre_print) { - printf (error_pre_print); + printf_unfiltered (error_pre_print); } print_sys_errmsg (symsfilename, errno); } @@ -771,3 +846,23 @@ find_pc_section(pc) return(NULL); } + +/* In SVR4, we recognize a trampoline by it's section name. + That is, if the pc is in a section named ".plt" then we are in + a trampoline. */ + +int +in_plt_section(pc, name) + CORE_ADDR pc; + char *name; +{ + struct obj_section *s; + int retval = 0; + + s = find_pc_section(pc); + + retval = (s != NULL + && s->the_bfd_section->name != NULL + && STREQ (s->the_bfd_section->name, ".plt")); + return(retval); +} diff --git a/gnu/usr.bin/gdb/gdb/objfiles.h b/gnu/usr.bin/gdb/gdb/objfiles.h index 50226ff47e77..f7cd113eda68 100644 --- a/gnu/usr.bin/gdb/gdb/objfiles.h +++ b/gnu/usr.bin/gdb/gdb/objfiles.h @@ -1,5 +1,5 @@ /* Definitions for symbol file management in GDB. - Copyright (C) 1992 Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -23,7 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This structure maintains information on a per-objfile basis about the "entry point" of the objfile, and the scope within which the entry point exists. It is possible that gdb will see more than one objfile that is - executable, each with it's own entry point. + executable, each with its own entry point. For example, for dynamically linked executables in SVR4, the dynamic linker code is contained within the shared C library, which is actually executable @@ -40,10 +40,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ executable which correspond to the "startup file", I.E. crt0.o in most cases. This file is assumed to be a startup file and frames with pc's inside it are treated as nonexistent. Setting these variables is necessary - so that backtraces do not fly off the bottom of the stack (or top, depending - upon your stack orientation). + so that backtraces do not fly off the bottom of the stack. - Gdb also supports an alternate method to avoid running off the top/bottom + Gdb also supports an alternate method to avoid running off the bottom of the stack. There are two frames that are "special", the frame for the function @@ -94,6 +93,8 @@ struct entry_info CORE_ADDR entry_point; +#define INVALID_ENTRY_POINT (~0) /* ~0 will not be in any file, we hope. */ + /* Start (inclusive) and end (exclusive) of function containing the entry point. */ @@ -111,8 +112,16 @@ struct entry_info CORE_ADDR main_func_lowpc; CORE_ADDR main_func_highpc; -}; +/* Use these values when any of the above ranges is invalid. */ +/* We use these values because it guarantees that there is no number that is + both >= LOWPC && < HIGHPC. It is also highly unlikely that 3 is a valid + module or function start address (as opposed to 0). */ + +#define INVALID_ENTRY_LOWPC (3) +#define INVALID_ENTRY_HIGHPC (1) + +}; /* Sections in an objfile. @@ -140,19 +149,20 @@ struct obj_section { addresses", but that's not true; addr & endaddr are actual memory addresses. */ CORE_ADDR offset; - - sec_ptr sec_ptr; /* BFD section pointer */ - /* Objfile this section is part of. Not currently used, but I'm sure - that someone will want the bfd that the sec_ptr goes with or something - like that before long. */ + sec_ptr the_bfd_section; /* BFD section pointer */ + + /* Objfile this section is part of. */ struct objfile *objfile; }; -/* Master structure for keeping track of each input file from which - gdb reads symbols. One of these is allocated for each such file we - access, e.g. the exec_file, symbol_file, and any shared library object - files. */ +/* Master structure for keeping track of each file from which + gdb reads symbols. There are several ways these get allocated: 1. + The main symbol file, symfile_objfile, set by the symbol-file command, + 2. Additional symbol files added by the add-symbol-file command, + 3. Shared library objfiles, added by ADD_SOLIB, 4. symbol files + for modules that were loaded when GDB attached to a remote system + (see remote-vx.c). */ struct objfile { @@ -308,12 +318,15 @@ struct objfile struct obj_section *sections, *sections_end; + + /* two auxiliary fields, used to hold the fp of separate symbol files */ + FILE *auxf1, *auxf2; }; /* Defines for the objfile flag word. */ /* Gdb can arrange to allocate storage for all objects related to a - particular objfile in a designated section of it's address space, + particular objfile in a designated section of its address space, managed at a low level by mmap() and using a special version of malloc that handles malloc/free/realloc on top of the mmap() interface. This allows the "internal gdb state" for a particular objfile to be @@ -360,6 +373,9 @@ extern struct objfile *object_files; extern struct objfile * allocate_objfile PARAMS ((bfd *, int)); +extern int +build_objfile_section_table PARAMS ((struct objfile *)); + extern void unlink_objfile PARAMS ((struct objfile *)); @@ -398,7 +414,6 @@ find_pc_section PARAMS((CORE_ADDR pc)); (obj) != NULL? ((nxt)=(obj)->next,1) :0; \ (obj) = (nxt)) - /* Traverse all symtabs in one objfile. */ #define ALL_OBJFILE_SYMTABS(objfile, s) \ @@ -414,7 +429,6 @@ find_pc_section PARAMS((CORE_ADDR pc)); #define ALL_OBJFILE_MSYMBOLS(objfile, m) \ for ((m) = (objfile) -> msymbols; SYMBOL_NAME(m) != NULL; (m)++) - /* Traverse all symtabs in all objfiles. */ #define ALL_SYMTABS(objfile, s) \ diff --git a/gnu/usr.bin/gdb/gdb/obstack.h b/gnu/usr.bin/gdb/gdb/obstack.h index 689f14855fed..28061a021937 100644 --- a/gnu/usr.bin/gdb/gdb/obstack.h +++ b/gnu/usr.bin/gdb/gdb/obstack.h @@ -1,5 +1,5 @@ /* obstack.h - object stack macros - Copyright (C) 1988, 1992 Free Software Foundation, Inc. + Copyright (C) 1988, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the @@ -100,8 +100,8 @@ break the ordinary 'growth' macro. /* Don't do the contents of this file more than once. */ -#ifndef __OBSTACKS__ -#define __OBSTACKS__ +#ifndef __OBSTACK_H__ +#define __OBSTACK_H__ /* We use subtraction of (char *)0 instead of casting to int because on word-addressable machines a simple cast to int @@ -122,17 +122,14 @@ break the ordinary 'growth' macro. #if defined (__STDC__) && ! defined (offsetof) #if defined (__GNUC__) && defined (IN_GCC) /* On Next machine, the system's stddef.h screws up if included - after we have defined just ptrdiff_t, so include all of gstddef.h. + after we have defined just ptrdiff_t, so include all of stddef.h. Otherwise, define just ptrdiff_t, which is all we need. */ #ifndef __NeXT__ #define __need_ptrdiff_t #endif - -/* While building GCC, the stddef.h that goes with GCC has this name. */ -#include "gstddef.h" -#else -#include #endif + +#include #endif #ifdef __STDC__ @@ -165,6 +162,7 @@ struct obstack /* control current object in current chunk */ chunk contains a zero-length object. This prevents freeing the chunk if we allocate a bigger chunk to replace it. */ + unsigned alloc_failed:1; /* chunk alloc func returned 0 */ }; /* Declare the external functions we use; they are in obstack.c. */ @@ -172,15 +170,15 @@ struct obstack /* control current object in current chunk */ #ifdef __STDC__ extern void _obstack_newchunk (struct obstack *, int); extern void _obstack_free (struct obstack *, void *); -extern void _obstack_begin (struct obstack *, int, int, +extern int _obstack_begin (struct obstack *, int, int, void *(*) (), void (*) ()); -extern void _obstack_begin_1 (struct obstack *, int, int, +extern int _obstack_begin_1 (struct obstack *, int, int, void *(*) (), void (*) (), void *); #else extern void _obstack_newchunk (); extern void _obstack_free (); -extern void _obstack_begin (); -extern void _obstack_begin_1 (); +extern int _obstack_begin (); +extern int _obstack_begin_1 (); #endif #ifdef __STDC__ @@ -230,7 +228,7 @@ int obstack_chunk_size (struct obstack *obstack); Note that this might not be the final address of the object because a new chunk might be needed to hold the final size. */ -#define obstack_base(h) ((h)->object_base) +#define obstack_base(h) ((h)->alloc_failed ? 0 : (h)->object_base) /* Size for allocating ordinary chunks. */ @@ -238,7 +236,7 @@ int obstack_chunk_size (struct obstack *obstack); /* Pointer to next byte not yet allocated in current chunk. */ -#define obstack_next_free(h) ((h)->next_free) +#define obstack_next_free(h) ((h)->alloc_failed ? 0 : (h)->next_free) /* Mask specifying low bits that should be clear in address of an object. */ @@ -283,6 +281,7 @@ int obstack_chunk_size (struct obstack *obstack); #define obstack_object_size(OBSTACK) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ + __o->alloc_failed ? 0 : \ (unsigned) (__o->next_free - __o->object_base); }) #define obstack_room(OBSTACK) \ @@ -290,38 +289,40 @@ int obstack_chunk_size (struct obstack *obstack); ({ struct obstack *__o = (OBSTACK); \ (unsigned) (__o->chunk_limit - __o->next_free); }) -/* Note that the call to _obstack_newchunk is enclosed in (..., 0) - so that we can avoid having void expressions - in the arms of the conditional expression. - Casting the third operand to void was tried before, - but some compilers won't accept it. */ #define obstack_grow(OBSTACK,where,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ - ((__o->next_free + __len > __o->chunk_limit) \ - ? (_obstack_newchunk (__o, __len), 0) : 0); \ - bcopy (where, __o->next_free, __len); \ - __o->next_free += __len; \ + if (__o->next_free + __len > __o->chunk_limit) \ + _obstack_newchunk (__o, __len); \ + if (!__o->alloc_failed) \ + { \ + bcopy (where, __o->next_free, __len); \ + __o->next_free += __len; \ + } \ (void) 0; }) #define obstack_grow0(OBSTACK,where,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ - ((__o->next_free + __len + 1 > __o->chunk_limit) \ - ? (_obstack_newchunk (__o, __len + 1), 0) : 0), \ - bcopy (where, __o->next_free, __len), \ - __o->next_free += __len, \ - *(__o->next_free)++ = 0; \ + if (__o->next_free + __len + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, __len + 1); \ + if (!__o->alloc_failed) \ + { \ + bcopy (where, __o->next_free, __len); \ + __o->next_free += __len; \ + *(__o->next_free)++ = 0; \ + } \ (void) 0; }) #define obstack_1grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - ((__o->next_free + 1 > __o->chunk_limit) \ - ? (_obstack_newchunk (__o, 1), 0) : 0), \ - *(__o->next_free)++ = (datum); \ + if (__o->next_free + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, 1); \ + if (!__o->alloc_failed) \ + *(__o->next_free)++ = (datum); \ (void) 0; }) /* These assume that the obstack alignment is good enough for pointers or ints, @@ -331,17 +332,19 @@ __extension__ \ #define obstack_ptr_grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - ((__o->next_free + sizeof (void *) > __o->chunk_limit) \ - ? (_obstack_newchunk (__o, sizeof (void *)), 0) : 0), \ - *((void **)__o->next_free)++ = ((void *)datum); \ + if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (void *)); \ + if (!__o->alloc_failed) \ + *((void **)__o->next_free)++ = ((void *)datum); \ (void) 0; }) #define obstack_int_grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - ((__o->next_free + sizeof (int) > __o->chunk_limit) \ - ? (_obstack_newchunk (__o, sizeof (int)), 0) : 0), \ - *((int *)__o->next_free)++ = ((int)datum); \ + if (__o->next_free + sizeof (int) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (int)); \ + if (!__o->alloc_failed) \ + *((int *)__o->next_free)++ = ((int)datum); \ (void) 0; }) #define obstack_ptr_grow_fast(h,aptr) (*((void **)(h)->next_free)++ = (void *)aptr) @@ -351,9 +354,10 @@ __extension__ \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ - ((__o->chunk_limit - __o->next_free < __len) \ - ? (_obstack_newchunk (__o, __len), 0) : 0); \ - __o->next_free += __len; \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + if (!__o->alloc_failed) \ + __o->next_free += __len; \ (void) 0; }) #define obstack_alloc(OBSTACK,length) \ @@ -379,16 +383,22 @@ __extension__ \ #define obstack_finish(OBSTACK) \ __extension__ \ ({ struct obstack *__o1 = (OBSTACK); \ - void *value = (void *) __o1->object_base; \ - if (__o1->next_free == value) \ - __o1->maybe_empty_object = 1; \ - __o1->next_free \ - = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\ - & ~ (__o1->alignment_mask)); \ - ((__o1->next_free - (char *)__o1->chunk \ - > __o1->chunk_limit - (char *)__o1->chunk) \ - ? (__o1->next_free = __o1->chunk_limit) : 0); \ - __o1->object_base = __o1->next_free; \ + void *value; \ + if (__o1->alloc_failed) \ + value = 0; \ + else \ + { \ + value = (void *) __o1->object_base; \ + if (__o1->next_free == value) \ + __o1->maybe_empty_object = 1; \ + __o1->next_free \ + = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\ + & ~ (__o1->alignment_mask)); \ + if (__o1->next_free - (char *)__o1->chunk \ + > __o1->chunk_limit - (char *)__o1->chunk) \ + __o1->next_free = __o1->chunk_limit; \ + __o1->object_base = __o1->next_free; \ + } \ value; }) #define obstack_free(OBSTACK, OBJ) \ @@ -402,40 +412,51 @@ __extension__ \ #else /* not __GNUC__ or not __STDC__ */ #define obstack_object_size(h) \ - (unsigned) ((h)->next_free - (h)->object_base) + (unsigned) ((h)->alloc_failed ? 0 : (h)->next_free - (h)->object_base) #define obstack_room(h) \ (unsigned) ((h)->chunk_limit - (h)->next_free) +/* Note that the call to _obstack_newchunk is enclosed in (..., 0) + so that we can avoid having void expressions + in the arms of the conditional expression. + Casting the third operand to void was tried before, + but some compilers won't accept it. */ + #define obstack_grow(h,where,length) \ ( (h)->temp = (length), \ (((h)->next_free + (h)->temp > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ - bcopy (where, (h)->next_free, (h)->temp), \ - (h)->next_free += (h)->temp) + ((h)->alloc_failed ? 0 : \ + (bcopy (where, (h)->next_free, (h)->temp), \ + (h)->next_free += (h)->temp))) #define obstack_grow0(h,where,length) \ ( (h)->temp = (length), \ (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \ - bcopy (where, (h)->next_free, (h)->temp), \ + ((h)->alloc_failed ? 0 : \ + (bcopy (where, (h)->next_free, (h)->temp), \ (h)->next_free += (h)->temp, \ - *((h)->next_free)++ = 0) + *((h)->next_free)++ = 0))) #define obstack_1grow(h,datum) \ ( (((h)->next_free + 1 > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), 1), 0) : 0), \ - *((h)->next_free)++ = (datum)) + ((h)->alloc_failed ? 0 : \ + (*((h)->next_free)++ = (datum)))) #define obstack_ptr_grow(h,datum) \ ( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ - *((char **)(((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *)datum)) + ((h)->alloc_failed ? 0 : \ + (*((char **)(((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *)datum)))) #define obstack_int_grow(h,datum) \ ( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ - *((int *)(((h)->next_free+=sizeof(int))-sizeof(int))) = ((int)datum)) + ((h)->alloc_failed ? 0 : \ + (*((int *)(((h)->next_free+=sizeof(int))-sizeof(int))) = ((int)datum)))) #define obstack_ptr_grow_fast(h,aptr) (*((char **)(h)->next_free)++ = (char *)aptr) #define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint) @@ -444,7 +465,8 @@ __extension__ \ ( (h)->temp = (length), \ (((h)->chunk_limit - (h)->next_free < (h)->temp) \ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ - (h)->next_free += (h)->temp) + ((h)->alloc_failed ? 0 : \ + ((h)->next_free += (h)->temp))) #define obstack_alloc(h,length) \ (obstack_blank ((h), (length)), obstack_finish ((h))) @@ -456,7 +478,8 @@ __extension__ \ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) #define obstack_finish(h) \ -( ((h)->next_free == (h)->object_base \ +( (h)->alloc_failed ? 0 : \ + (((h)->next_free == (h)->object_base \ ? (((h)->maybe_empty_object = 1), 0) \ : 0), \ (h)->temp = __PTR_TO_INT ((h)->object_base), \ @@ -467,7 +490,7 @@ __extension__ \ > (h)->chunk_limit - (char *)(h)->chunk) \ ? ((h)->next_free = (h)->chunk_limit) : 0), \ (h)->object_base = (h)->next_free, \ - __INT_TO_PTR ((h)->temp)) + __INT_TO_PTR ((h)->temp))) #ifdef __STDC__ #define obstack_free(h,obj) \ @@ -487,4 +510,4 @@ __extension__ \ #endif /* not __GNUC__ or not __STDC__ */ -#endif /* not __OBSTACKS__ */ +#endif /* not __OBSTACK_H__ */ diff --git a/gnu/usr.bin/gdb/gdb/parse.c b/gnu/usr.bin/gdb/gdb/parse.c index 08f2b7e67484..8c387c823383 100644 --- a/gnu/usr.bin/gdb/gdb/parse.c +++ b/gnu/usr.bin/gdb/gdb/parse.c @@ -1,5 +1,5 @@ /* Parse expressions for GDB. - Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc. + Copyright (C) 1986, 1989, 1990, 1991, 1994 Free Software Foundation, Inc. Modified from expread.y by the Department of Computer Science at the State University of New York at Buffalo, 1991. @@ -29,6 +29,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ come first in the result. */ #include "defs.h" +#include #include "symtab.h" #include "gdbtypes.h" #include "frame.h" @@ -37,7 +38,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "command.h" #include "language.h" #include "parser-defs.h" - + +/* Global variables declared in parser-defs.h (and commented there). */ +struct expression *expout; +int expout_size; +int expout_ptr; +struct block *expression_context_block; +struct block *innermost_block; +int arglist_len; +union type_stack_elt *type_stack; +int type_stack_depth, type_stack_size; +char *lexptr; +char *namecopy; +int paren_depth; +int comma_terminates; + static void free_funcalls PARAMS ((void)); @@ -338,6 +353,47 @@ write_exp_bitstring (str) expout_ptr += lenelt - 2; write_exp_elt_longcst ((LONGEST) bits); } + +/* Type that corresponds to the address given in a minimal symbol. */ + +static struct type *msymbol_addr_type; + +/* Add the appropriate elements for a minimal symbol to the end of + the expression. */ + +void +write_exp_msymbol (msymbol, text_symbol_type, data_symbol_type) + struct minimal_symbol *msymbol; + struct type *text_symbol_type; + struct type *data_symbol_type; +{ + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (msymbol_addr_type); + write_exp_elt_longcst ((LONGEST) SYMBOL_VALUE_ADDRESS (msymbol)); + write_exp_elt_opcode (OP_LONG); + + write_exp_elt_opcode (UNOP_MEMVAL); + switch (msymbol -> type) + { + case mst_text: + case mst_file_text: + case mst_solib_trampoline: + write_exp_elt_type (text_symbol_type); + break; + + case mst_data: + case mst_file_data: + case mst_bss: + case mst_file_bss: + write_exp_elt_type (data_symbol_type); + break; + + default: + write_exp_elt_type (builtin_type_char); + break; + } + write_exp_elt_opcode (UNOP_MEMVAL); +} /* Return a null-terminated temporary copy of the name of a string token. */ @@ -705,9 +761,9 @@ parse_exp_1 (stringptr, block, comma) /* Convert expression from postfix form as generated by yacc parser, to a prefix form. */ - DUMP_EXPRESSION (expout, stdout, "before conversion to prefix form"); + DUMP_EXPRESSION (expout, gdb_stdout, "before conversion to prefix form"); prefixify_expression (expout); - DUMP_EXPRESSION (expout, stdout, "after conversion to prefix form"); + DUMP_EXPRESSION (expout, gdb_stdout, "after conversion to prefix form"); *stringptr = lexptr; return expout; @@ -824,4 +880,11 @@ _initialize_parse () type_stack_depth = 0; type_stack = (union type_stack_elt *) xmalloc (type_stack_size * sizeof (*type_stack)); + + /* We don't worry too much about what the name of this type is + because the name should rarely appear in output to the user. */ + + msymbol_addr_type = + init_type (TYPE_CODE_PTR, TARGET_PTR_BIT / HOST_CHAR_BIT, 0, + "void *", NULL); } diff --git a/gnu/usr.bin/gdb/gdb/parser-defs.h b/gnu/usr.bin/gdb/gdb/parser-defs.h index 5c8710e4e6e2..fd03a6e0649a 100644 --- a/gnu/usr.bin/gdb/gdb/parser-defs.h +++ b/gnu/usr.bin/gdb/gdb/parser-defs.h @@ -30,24 +30,26 @@ struct std_regs { extern struct std_regs std_regs[]; extern unsigned num_std_regs; -struct expression *expout; -int expout_size; -int expout_ptr; +extern struct expression *expout; +extern int expout_size; +extern int expout_ptr; /* If this is nonzero, this block is used as the lexical context for symbol names. */ -struct block *expression_context_block; +extern struct block *expression_context_block; /* The innermost context required by the stack and register variables we've encountered so far. */ -struct block *innermost_block; +extern struct block *innermost_block; -/* The block in which the most recently discovered symbol was found. */ -struct block *block_found; +/* The block in which the most recently discovered symbol was found. + FIXME: Should be declared along with lookup_symbol in symtab.h; is not + related specifically to parsing. */ +extern struct block *block_found; /* Number of arguments seen so far in innermost function call. */ -int arglist_len; +extern int arglist_len; /* A string token, either a char-string or bit-string. Char-strings are used, for example, for the names of symbols. */ @@ -82,35 +84,31 @@ union type_stack_elt { enum type_pieces piece; int int_val; }; -union type_stack_elt *type_stack; -int type_stack_depth, type_stack_size; +extern union type_stack_elt *type_stack; +extern int type_stack_depth, type_stack_size; -extern void -write_exp_elt PARAMS ((union exp_element)); +extern void write_exp_elt PARAMS ((union exp_element)); -extern void -write_exp_elt_opcode PARAMS ((enum exp_opcode)); +extern void write_exp_elt_opcode PARAMS ((enum exp_opcode)); -extern void -write_exp_elt_sym PARAMS ((struct symbol *)); +extern void write_exp_elt_sym PARAMS ((struct symbol *)); -extern void -write_exp_elt_longcst PARAMS ((LONGEST)); +extern void write_exp_elt_longcst PARAMS ((LONGEST)); -extern void -write_exp_elt_dblcst PARAMS ((double)); +extern void write_exp_elt_dblcst PARAMS ((double)); -extern void -write_exp_elt_type PARAMS ((struct type *)); +extern void write_exp_elt_type PARAMS ((struct type *)); -extern void -write_exp_elt_intern PARAMS ((struct internalvar *)); +extern void write_exp_elt_intern PARAMS ((struct internalvar *)); -extern void -write_exp_string PARAMS ((struct stoken)); +extern void write_exp_string PARAMS ((struct stoken)); -extern void -write_exp_bitstring PARAMS ((struct stoken)); +extern void write_exp_bitstring PARAMS ((struct stoken)); + +extern void write_exp_elt_block PARAMS ((struct block *)); + +extern void write_exp_msymbol PARAMS ((struct minimal_symbol *, + struct type *, struct type *)); extern void start_arglist PARAMS ((void)); @@ -138,7 +136,7 @@ extern struct type *follow_types PARAMS ((struct type *)); /* During parsing of a C expression, the pointer to the next character is in this variable. */ -char *lexptr; +extern char *lexptr; /* Tokens that refer to names do so with explicit pointer and length, so they can share the storage that lexptr is parsing. @@ -149,15 +147,15 @@ char *lexptr; namecopy is allocated once, guaranteed big enough, for each parsing. */ -char *namecopy; +extern char *namecopy; /* Current depth in parentheses within the expression. */ -int paren_depth; +extern int paren_depth; /* Nonzero means stop parsing on first comma (if not within parentheses). */ -int comma_terminates; +extern int comma_terminates; /* These codes indicate operator precedences for expression printing, least tightly binding first. */ diff --git a/gnu/usr.bin/gdb/gdb/partial-stab.h b/gnu/usr.bin/gdb/gdb/partial-stab.h index 3be0be618873..747e6a5fc2ed 100644 --- a/gnu/usr.bin/gdb/gdb/partial-stab.h +++ b/gnu/usr.bin/gdb/gdb/partial-stab.h @@ -1,5 +1,5 @@ /* Shared code to pre-read a stab (dbx-style), when building a psymtab. - Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993 + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -240,69 +240,96 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ } case N_BINCL: + { #ifdef DBXREAD_ONLY - /* Add this bincl to the bincl_list for future EXCLs. No - need to save the string; it'll be around until - read_dbx_symtab function returns */ + enum language tmp_language; + /* Add this bincl to the bincl_list for future EXCLs. No + need to save the string; it'll be around until + read_dbx_symtab function returns */ - SET_NAMESTRING(); + SET_NAMESTRING(); - add_bincl_to_list (pst, namestring, CUR_SYMBOL_VALUE); + tmp_language = deduce_language_from_filename (namestring); - /* Mark down an include file in the current psymtab */ + /* Only change the psymtab's language if we've learned + something useful (eg. tmp_language is not language_unknown). + In addition, to match what start_subfile does, never change + from C++ to C. */ + if (tmp_language != language_unknown + && (tmp_language != language_c + || psymtab_language != language_cplus)) + psymtab_language = tmp_language; - goto record_include_file; + add_bincl_to_list (pst, namestring, CUR_SYMBOL_VALUE); + + /* Mark down an include file in the current psymtab */ + + goto record_include_file; #else /* DBXREAD_ONLY */ - continue; -#endif - - case N_SOL: - /* Mark down an include file in the current psymtab */ - - SET_NAMESTRING(); - - /* In C++, one may expect the same filename to come round many - times, when code is coming alternately from the main file - and from inline functions in other files. So I check to see - if this is a file we've seen before -- either the main - source file, or a previously included file. - - This seems to be a lot of time to be spending on N_SOL, but - things like "break c-exp.y:435" need to work (I - suppose the psymtab_include_list could be hashed or put - in a binary tree, if profiling shows this is a major hog). */ - if (pst && STREQ (namestring, pst->filename)) continue; - { - register int i; - for (i = 0; i < includes_used; i++) - if (STREQ (namestring, psymtab_include_list[i])) - { - i = -1; - break; - } - if (i == -1) - continue; +#endif } -#ifdef DBXREAD_ONLY - record_include_file: -#endif - - psymtab_include_list[includes_used++] = namestring; - if (includes_used >= includes_allocated) + case N_SOL: + { + enum language tmp_language; + /* Mark down an include file in the current psymtab */ + + SET_NAMESTRING(); + + tmp_language = deduce_language_from_filename (namestring); + + /* Only change the psymtab's language if we've learned + something useful (eg. tmp_language is not language_unknown). + In addition, to match what start_subfile does, never change + from C++ to C. */ + if (tmp_language != language_unknown + && (tmp_language != language_c + || psymtab_language != language_cplus)) + psymtab_language = tmp_language; + + /* In C++, one may expect the same filename to come round many + times, when code is coming alternately from the main file + and from inline functions in other files. So I check to see + if this is a file we've seen before -- either the main + source file, or a previously included file. + + This seems to be a lot of time to be spending on N_SOL, but + things like "break c-exp.y:435" need to work (I + suppose the psymtab_include_list could be hashed or put + in a binary tree, if profiling shows this is a major hog). */ + if (pst && STREQ (namestring, pst->filename)) + continue; { - char **orig = psymtab_include_list; - - psymtab_include_list = (char **) - alloca ((includes_allocated *= 2) * - sizeof (char *)); - memcpy ((PTR)psymtab_include_list, (PTR)orig, - includes_used * sizeof (char *)); + register int i; + for (i = 0; i < includes_used; i++) + if (STREQ (namestring, psymtab_include_list[i])) + { + i = -1; + break; + } + if (i == -1) + continue; } - continue; - + +#ifdef DBXREAD_ONLY + record_include_file: +#endif + + psymtab_include_list[includes_used++] = namestring; + if (includes_used >= includes_allocated) + { + char **orig = psymtab_include_list; + + psymtab_include_list = (char **) + alloca ((includes_allocated *= 2) * + sizeof (char *)); + memcpy ((PTR)psymtab_include_list, (PTR)orig, + includes_used * sizeof (char *)); + } + continue; + } case N_LSYM: /* Typedef or automatic variable. */ case N_STSYM: /* Data seg var -- static */ case N_LCSYM: /* BSS " */ @@ -375,6 +402,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ objfile); p += 1; } + /* The semantics of C++ state that "struct foo { ... }" + also defines a typedef for "foo". Unfortuantely, cfront + never makes the typedef when translating from C++ to C. + We make the typedef here so that "ptype foo" works as + expected for cfront translated code. */ + else if (psymtab_language == language_cplus) + { + /* Also a typedef with the same name. */ + ADD_PSYMBOL_TO_LIST (namestring, p - namestring, + VAR_NAMESPACE, LOC_TYPEDEF, + objfile->static_psymbols, + CUR_SYMBOL_VALUE, psymtab_language, + objfile); + } } goto check_enum; case 't': @@ -422,7 +463,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Check for and handle cretinous dbx symbol name continuation! */ - if (*p == '\\') + if (*p == '\\' || (*p == '?' && p[1] == '\0')) p = next_symbol_text (); /* Point to the character after the name @@ -455,10 +496,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ continue; case 'f': + CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT); #ifdef DBXREAD_ONLY /* Kludges for ELF/STABS with Sun ACC */ last_function_name = namestring; - if (pst && pst->textlow == 0) + /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit + value for the bottom of the text seg in those cases. */ + if (pst && pst->textlow == 0 && !symfile_relocatable) pst->textlow = CUR_SYMBOL_VALUE; #if 0 if (startup_file_end == 0) @@ -476,10 +520,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ are put into the global psymtab like one would expect. They're also in the minimal symbol table. */ case 'F': + CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT); #ifdef DBXREAD_ONLY /* Kludges for ELF/STABS with Sun ACC */ last_function_name = namestring; - if (pst && pst->textlow == 0) + /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit + value for the bottom of the text seg in those cases. */ + if (pst && pst->textlow == 0 && !symfile_relocatable) pst->textlow = CUR_SYMBOL_VALUE; #if 0 if (startup_file_end == 0) @@ -510,14 +557,28 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ case '9': continue; - default: - /* Unexpected symbol. Ignore it; perhaps it is an extension - that we don't know about. - - Someone says sun cc puts out symbols like + case ':': + /* It is a C++ nested symbol. We don't need to record it + (I don't think); if we try to look up foo::bar::baz, + then symbols for the symtab containing foo should get + read in, I think. */ + /* Someone says sun cc puts out symbols like /foo/baz/maclib::/usr/local/bin/maclib, which would get here with a symbol type of ':'. */ + continue; + + default: + /* Unexpected symbol descriptor. The second and subsequent stabs + of a continued stab can show up here. The question is + whether they ever can mimic a normal stab--it would be + nice if not, since we certainly don't want to spend the + time searching to the end of every string looking for + a backslash. */ + complain (&unknown_symchar_complaint, p[1]); + + /* Ignore it; perhaps it is an extension that we don't + know about. */ continue; } @@ -563,8 +624,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ (dependencies_used * sizeof (struct partial_symtab *))); #ifdef DEBUG_INFO - fprintf (stderr, "Had to reallocate dependency list.\n"); - fprintf (stderr, "New dependencies allocated: %d\n", + fprintf_unfiltered (gdb_stderr, "Had to reallocate dependency list.\n"); + fprintf_unfiltered (gdb_stderr, "New dependencies allocated: %d\n", dependencies_allocated); #endif } @@ -613,6 +674,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* If we haven't found it yet, ignore it. It's probably some new type we don't know about yet. */ complain (&unknown_symtype_complaint, - local_hex_string ((unsigned long) CUR_SYMBOL_TYPE)); + local_hex_string (CUR_SYMBOL_TYPE)); continue; } diff --git a/gnu/usr.bin/gdb/gdb/printcmd.c b/gnu/usr.bin/gdb/gdb/printcmd.c index 3530ac2f32f0..8ebc94c3e781 100644 --- a/gnu/usr.bin/gdb/gdb/printcmd.c +++ b/gnu/usr.bin/gdb/gdb/printcmd.c @@ -1,5 +1,6 @@ /* Print values for GNU debugger GDB. - Copyright 1986, 1987, 1988, 1989, 1990, 1991 Free Software Foundation, Inc. + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -31,6 +32,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "target.h" #include "breakpoint.h" #include "demangle.h" +#include "valprint.h" +#include "annotate.h" extern int asm_demangle; /* Whether to demangle syms in asm printouts */ extern int addressprint; /* Whether to print hex addresses in HLL " */ @@ -61,7 +64,7 @@ static CORE_ADDR last_examine_address; /* Contents of last address examined. This is not valid past the end of the `x' command! */ -static value last_examine_value; +static value_ptr last_examine_value; /* Largest offset between a symbolic value and an address, that will be printed as `0x1234 '. */ @@ -127,7 +130,7 @@ printf_command PARAMS ((char *, int)); static void print_frame_nameless_args PARAMS ((struct frame_info *, long, int, int, - FILE *)); + GDB_FILE *)); static void display_info PARAMS ((char *, int)); @@ -175,7 +178,7 @@ static void do_examine PARAMS ((struct format_data, CORE_ADDR)); static void -print_formatted PARAMS ((value, int, int)); +print_formatted PARAMS ((value_ptr, int, int)); static struct format_data decode_format PARAMS ((char **, int, int)); @@ -220,13 +223,6 @@ decode_format (string_ptr, oformat, osize) break; } -#ifndef CC_HAS_LONG_LONG - /* Make sure 'g' size is not used on integer types. - Well, actually, we can handle hex. */ - if (val.size == 'g' && val.format != 'f' && val.format != 'x') - val.size = 'w'; -#endif - while (*p == ' ' || *p == '\t') p++; *string_ptr = p; @@ -249,8 +245,16 @@ decode_format (string_ptr, oformat, osize) { case 'a': case 's': - /* Addresses must be words. */ - val.size = osize ? 'w' : osize; + /* Pick the appropriate size for an address. */ + if (TARGET_PTR_BIT == 64) + val.size = osize ? 'g' : osize; + else if (TARGET_PTR_BIT == 32) + val.size = osize ? 'w' : osize; + else if (TARGET_PTR_BIT == 16) + val.size = osize ? 'h' : osize; + else + /* Bad value for TARGET_PTR_BIT */ + abort (); break; case 'f': /* Floating point has to be word or giantword. */ @@ -273,7 +277,7 @@ decode_format (string_ptr, oformat, osize) return val; } -/* Print value VAL on stdout according to FORMAT, a letter or 0. +/* Print value VAL on gdb_stdout according to FORMAT, a letter or 0. Do not end with a newline. 0 means print VAL according to its own type. SIZE is the letter for the size of datum being printed. @@ -281,7 +285,7 @@ decode_format (string_ptr, oformat, osize) static void print_formatted (val, format, size) - register value val; + register value_ptr val; register int format; int size; { @@ -294,7 +298,7 @@ print_formatted (val, format, size) { case 's': next_address = VALUE_ADDRESS (val) - + value_print (value_addr (val), stdout, format, Val_pretty_default); + + value_print (value_addr (val), gdb_stdout, format, Val_pretty_default); break; case 'i': @@ -305,7 +309,7 @@ print_formatted (val, format, size) /* We often wrap here if there are long symbolic names. */ wrap_here (" "); next_address = VALUE_ADDRESS (val) - + print_insn (VALUE_ADDRESS (val), stdout); + + print_insn (VALUE_ADDRESS (val), gdb_stdout); break; default: @@ -315,10 +319,10 @@ print_formatted (val, format, size) || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION || VALUE_REPEATED (val)) - value_print (val, stdout, format, Val_pretty_default); + value_print (val, gdb_stdout, format, Val_pretty_default); else print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val), - format, size, stdout); + format, size, gdb_stdout); } } @@ -335,7 +339,7 @@ print_scalar_formatted (valaddr, type, format, size, stream) struct type *type; int format; int size; - FILE *stream; + GDB_FILE *stream; { LONGEST val_long; int len = TYPE_LENGTH (type); @@ -359,7 +363,8 @@ print_scalar_formatted (valaddr, type, format, size, stream) return; } - val_long = unpack_long (type, valaddr); + if (format != 'f') + val_long = unpack_long (type, valaddr); /* If we are printing it as unsigned, truncate it in case it is actually a negative signed value (e.g. "print/u (short)-1" should print 65535 @@ -496,50 +501,65 @@ set_next_address (addr) /* Optionally print address ADDR symbolically as on STREAM, after LEADIN. Print nothing if no symbolic name is found nearby. + Optionally also print source file and line number, if available. DO_DEMANGLE controls whether to print a symbol in its native "raw" form, or to interpret it as a possible C++ name and convert it back to source form. However note that DO_DEMANGLE can be overridden by the specific - settings of the demangle and asm_demangle variables. */ + settings of the demangle and asm_demangle variables. */ void print_address_symbolic (addr, stream, do_demangle, leadin) CORE_ADDR addr; - FILE *stream; + GDB_FILE *stream; int do_demangle; char *leadin; { - CORE_ADDR name_location; - register struct symbol *symbol; - char *name; + struct minimal_symbol *msymbol; + struct symbol *symbol; + struct symtab *symtab = 0; + CORE_ADDR name_location = 0; + char *name = ""; - /* First try to find the address in the symbol tables to find - static functions. If that doesn't succeed we try the minimal symbol - vector for symbols in non-text space. - FIXME: Should find a way to get at the static non-text symbols too. */ - + /* First try to find the address in the symbol table, then + in the minsyms. Take the closest one. */ + + /* This is defective in the sense that it only finds text symbols. So + really this is kind of pointless--we should make sure that the + minimal symbols have everything we need (by changing that we could + save some memory, but for many debug format--ELF/DWARF or + anything/stabs--it would be inconvenient to eliminate those minimal + symbols anyway). */ symbol = find_pc_function (addr); if (symbol) - { name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)); - if (do_demangle) - name = SYMBOL_SOURCE_NAME (symbol); - else - name = SYMBOL_LINKAGE_NAME (symbol); - } - else - { - register struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (addr); - /* If nothing comes out, don't print anything symbolic. */ - if (msymbol == NULL) - return; - name_location = SYMBOL_VALUE_ADDRESS (msymbol); - if (do_demangle) - name = SYMBOL_SOURCE_NAME (msymbol); - else - name = SYMBOL_LINKAGE_NAME (msymbol); + if (symbol) + { + if (do_demangle) + name = SYMBOL_SOURCE_NAME (symbol); + else + name = SYMBOL_LINKAGE_NAME (symbol); } + msymbol = lookup_minimal_symbol_by_pc (addr); + if (msymbol != NULL) + { + if (SYMBOL_VALUE_ADDRESS (msymbol) > name_location || symbol == NULL) + { + /* The msymbol is closer to the address than the symbol; + use the msymbol instead. */ + symbol = 0; + symtab = 0; + name_location = SYMBOL_VALUE_ADDRESS (msymbol); + if (do_demangle) + name = SYMBOL_SOURCE_NAME (msymbol); + else + name = SYMBOL_LINKAGE_NAME (msymbol); + } + } + if (symbol == NULL && msymbol == NULL) + return; + /* If the nearest symbol is too far away, don't print anything symbolic. */ /* For when CORE_ADDR is larger than unsigned int, we do math in @@ -557,18 +577,37 @@ print_address_symbolic (addr, stream, do_demangle, leadin) if (addr != name_location) fprintf_filtered (stream, "+%u", (unsigned int)(addr - name_location)); - /* Append source filename and line number if desired. */ - if (symbol && print_symbol_filename) + /* Append source filename and line number if desired. Give specific + line # of this addr, if we have it; else line # of the nearest symbol. */ + if (print_symbol_filename) { struct symtab_and_line sal; sal = find_pc_line (addr, 0); if (sal.symtab) fprintf_filtered (stream, " at %s:%d", sal.symtab->filename, sal.line); + else if (symtab && symbol && symbol->line) + fprintf_filtered (stream, " at %s:%d", symtab->filename, symbol->line); + else if (symtab) + fprintf_filtered (stream, " in %s", symtab->filename); } fputs_filtered (">", stream); } +/* Print address ADDR on STREAM. USE_LOCAL means the same thing as for + print_longest. */ +void +print_address_numeric (addr, use_local, stream) + CORE_ADDR addr; + int use_local; + GDB_FILE *stream; +{ + /* This assumes a CORE_ADDR can fit in a LONGEST. Probably a safe + assumption. We pass use_local but I'm not completely sure whether + that is correct. When (if ever) should we *not* use_local? */ + print_longest (stream, 'x', 1, (unsigned LONGEST) addr); +} + /* Print address ADDR symbolically on STREAM. First print it as a number. Then perhaps print after the number. */ @@ -576,16 +615,9 @@ print_address_symbolic (addr, stream, do_demangle, leadin) void print_address (addr, stream) CORE_ADDR addr; - FILE *stream; + GDB_FILE *stream; { -#if 0 && defined (ADDR_BITS_REMOVE) - /* This is wrong for pointer to char, in which we do want to print - the low bits. */ - fprintf_filtered (stream, local_hex_format(), - (unsigned long) ADDR_BITS_REMOVE(addr)); -#else - fprintf_filtered (stream, local_hex_format(), (unsigned long) addr); -#endif + print_address_numeric (addr, 1, stream); print_address_symbolic (addr, stream, asm_demangle, " "); } @@ -597,17 +629,22 @@ print_address (addr, stream) void print_address_demangle (addr, stream, do_demangle) CORE_ADDR addr; - FILE *stream; + GDB_FILE *stream; int do_demangle; { - if (addr == 0) { - fprintf_filtered (stream, "0"); - } else if (addressprint) { - fprintf_filtered (stream, local_hex_format(), (unsigned long) addr); - print_address_symbolic (addr, stream, do_demangle, " "); - } else { - print_address_symbolic (addr, stream, do_demangle, ""); - } + if (addr == 0) + { + fprintf_filtered (stream, "0"); + } + else if (addressprint) + { + print_address_numeric (addr, 1, stream); + print_address_symbolic (addr, stream, do_demangle, " "); + } + else + { + print_address_symbolic (addr, stream, do_demangle, ""); + } } @@ -620,7 +657,7 @@ static struct type *examine_w_type; static struct type *examine_g_type; /* Examine data at address ADDR in format FMT. - Fetch it from memory and print on stdout. */ + Fetch it from memory and print on gdb_stdout. */ static void do_examine (fmt, addr) @@ -666,7 +703,7 @@ do_examine (fmt, addr) while (count > 0) { - print_address (next_address, stdout); + print_address (next_address, gdb_stdout); printf_filtered (":"); for (i = maxelts; i > 0 && count > 0; @@ -680,7 +717,7 @@ do_examine (fmt, addr) print_formatted (last_examine_value, format, size); } printf_filtered ("\n"); - fflush (stdout); + gdb_flush (gdb_stdout); } } @@ -713,7 +750,7 @@ print_command_1 (exp, inspect, voidprint) struct expression *expr; register struct cleanup *old_chain = 0; register char format = 0; - register value val; + register value_ptr val; struct format_data fmt; int cleanup = 0; @@ -752,7 +789,7 @@ print_command_1 (exp, inspect, voidprint) && ( TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_UNION)) { - value v; + value_ptr v; v = value_from_vtable_info (val, TYPE_TARGET_TYPE (type)); if (v != 0) @@ -770,15 +807,29 @@ print_command_1 (exp, inspect, voidprint) { int histindex = record_latest_value (val); + if (histindex >= 0) + annotate_value_history_begin (histindex, VALUE_TYPE (val)); + else + annotate_value_begin (VALUE_TYPE (val)); + if (inspect) - printf ("\031(gdb-makebuffer \"%s\" %d '(\"", exp, histindex); + printf_unfiltered ("\031(gdb-makebuffer \"%s\" %d '(\"", exp, histindex); else if (histindex >= 0) printf_filtered ("$%d = ", histindex); + if (histindex >= 0) + annotate_value_history_value (); + print_formatted (val, format, fmt.size); printf_filtered ("\n"); + + if (histindex >= 0) + annotate_value_history_end (); + else + annotate_value_end (); + if (inspect) - printf("\") )\030"); + printf_unfiltered("\") )\030"); } if (cleanup) @@ -826,7 +877,7 @@ output_command (exp, from_tty) struct expression *expr; register struct cleanup *old_chain; register char format = 0; - register value val; + register value_ptr val; struct format_data fmt; if (exp && *exp == '/') @@ -842,8 +893,12 @@ output_command (exp, from_tty) val = evaluate_expression (expr); + annotate_value_begin (VALUE_TYPE (val)); + print_formatted (val, format, fmt.size); + annotate_value_end (); + do_cleanups (old_chain); } @@ -882,22 +937,34 @@ address_info (exp, from_tty) { if (is_a_field_of_this) { - printf ("Symbol \"%s\" is a field of the local class variable `this'\n", exp); + printf_filtered ("Symbol \""); + fprintf_symbol_filtered (gdb_stdout, exp, + current_language->la_language, DMGL_ANSI); + printf_filtered ("\" is a field of the local class variable `this'\n"); return; } msymbol = lookup_minimal_symbol (exp, (struct objfile *) NULL); if (msymbol != NULL) - printf ("Symbol \"%s\" is at %s in a file compiled without debugging.\n", - exp, - local_hex_string((unsigned long) SYMBOL_VALUE_ADDRESS (msymbol))); + { + printf_filtered ("Symbol \""); + fprintf_symbol_filtered (gdb_stdout, exp, + current_language->la_language, DMGL_ANSI); + printf_filtered ("\" is at "); + print_address_numeric (SYMBOL_VALUE_ADDRESS (msymbol), 1, + gdb_stdout); + printf_filtered (" in a file compiled without debugging.\n"); + } else error ("No symbol \"%s\" in current context.", exp); return; } - printf ("Symbol \"%s\" is ", SYMBOL_NAME (sym)); + printf_filtered ("Symbol \""); + fprintf_symbol_filtered (gdb_stdout, SYMBOL_NAME (sym), + current_language->la_language, DMGL_ANSI); + printf_filtered ("\" is ", SYMBOL_NAME (sym)); val = SYMBOL_VALUE (sym); basereg = SYMBOL_BASEREG (sym); @@ -905,64 +972,65 @@ address_info (exp, from_tty) { case LOC_CONST: case LOC_CONST_BYTES: - printf ("constant"); + printf_filtered ("constant"); break; case LOC_LABEL: - printf ("a label at address %s", - local_hex_string((unsigned long) SYMBOL_VALUE_ADDRESS (sym))); + printf_filtered ("a label at address "); + print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout); break; case LOC_REGISTER: - printf ("a variable in register %s", reg_names[val]); + printf_filtered ("a variable in register %s", reg_names[val]); break; case LOC_STATIC: - printf ("static storage at address %s", - local_hex_string((unsigned long) SYMBOL_VALUE_ADDRESS (sym))); + printf_filtered ("static storage at address "); + print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout); break; case LOC_REGPARM: - printf ("an argument in register %s", reg_names[val]); + printf_filtered ("an argument in register %s", reg_names[val]); break; case LOC_REGPARM_ADDR: - printf ("address of an argument in register %s", reg_names[val]); + printf_filtered ("address of an argument in register %s", reg_names[val]); break; case LOC_ARG: - printf ("an argument at offset %ld", val); + printf_filtered ("an argument at offset %ld", val); break; case LOC_LOCAL_ARG: - printf ("an argument at frame offset %ld", val); + printf_filtered ("an argument at frame offset %ld", val); break; case LOC_LOCAL: - printf ("a local variable at frame offset %ld", val); + printf_filtered ("a local variable at frame offset %ld", val); break; case LOC_REF_ARG: - printf ("a reference argument at offset %ld", val); + printf_filtered ("a reference argument at offset %ld", val); break; case LOC_BASEREG: - printf ("a variable at offset %ld from register %s", + printf_filtered ("a variable at offset %ld from register %s", val, reg_names[basereg]); break; case LOC_BASEREG_ARG: - printf ("an argument at offset %ld from register %s", + printf_filtered ("an argument at offset %ld from register %s", val, reg_names[basereg]); break; case LOC_TYPEDEF: - printf ("a typedef"); + printf_filtered ("a typedef"); break; case LOC_BLOCK: - printf ("a function at address %s", - local_hex_string((unsigned long) BLOCK_START (SYMBOL_BLOCK_VALUE (sym)))); + printf_filtered ("a function at address "); + print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1, + gdb_stdout); break; case LOC_OPTIMIZED_OUT: @@ -970,10 +1038,10 @@ address_info (exp, from_tty) break; default: - printf ("of unknown (botched) type"); + printf_filtered ("of unknown (botched) type"); break; } - printf (".\n"); + printf_filtered (".\n"); } static void @@ -1212,11 +1280,16 @@ do_one_display (d) current_display_number = d->number; - printf_filtered ("%d: ", d->number); + annotate_display_begin (); + printf_filtered ("%d", d->number); + annotate_display_number_end (); + printf_filtered (": "); if (d->format.size) { CORE_ADDR addr; - + + annotate_display_format (); + printf_filtered ("x/"); if (d->format.count != 1) printf_filtered ("%d", d->format.count); @@ -1224,7 +1297,12 @@ do_one_display (d) if (d->format.format != 'i' && d->format.format != 's') printf_filtered ("%c", d->format.size); printf_filtered (" "); - print_expression (d->exp, stdout); + + annotate_display_expression (); + + print_expression (d->exp, gdb_stdout); + annotate_display_expression_end (); + if (d->format.count != 1) printf_filtered ("\n"); else @@ -1233,21 +1311,35 @@ do_one_display (d) addr = value_as_pointer (evaluate_expression (d->exp)); if (d->format.format == 'i') addr = ADDR_BITS_REMOVE (addr); - + + annotate_display_value (); + do_examine (d->format, addr); } else { + annotate_display_format (); + if (d->format.format) printf_filtered ("/%c ", d->format.format); - print_expression (d->exp, stdout); + + annotate_display_expression (); + + print_expression (d->exp, gdb_stdout); + annotate_display_expression_end (); + printf_filtered (" = "); + + annotate_display_expression (); + print_formatted (evaluate_expression (d->exp), d->format.format, d->format.size); printf_filtered ("\n"); } - fflush (stdout); + annotate_display_end (); + + gdb_flush (gdb_stdout); current_display_number = -1; } @@ -1278,7 +1370,7 @@ disable_display (num) d->status = disabled; return; } - printf ("No display number %d.\n", num); + printf_unfiltered ("No display number %d.\n", num); } void @@ -1287,7 +1379,7 @@ disable_current_display () if (current_display_number >= 0) { disable_display (current_display_number); - fprintf (stderr, "Disabling display %d to avoid infinite recursion.\n", + fprintf_unfiltered (gdb_stderr, "Disabling display %d to avoid infinite recursion.\n", current_display_number); } current_display_number = -1; @@ -1301,7 +1393,7 @@ display_info (ignore, from_tty) register struct display *d; if (!display_chain) - printf ("There are no auto-display expressions now.\n"); + printf_unfiltered ("There are no auto-display expressions now.\n"); else printf_filtered ("Auto-display expressions now in effect:\n\ Num Enb Expression\n"); @@ -1314,11 +1406,11 @@ Num Enb Expression\n"); d->format.format); else if (d->format.format) printf_filtered ("/%c ", d->format.format); - print_expression (d->exp, stdout); + print_expression (d->exp, gdb_stdout); if (d->block && !contained_in (get_selected_block (), d->block)) printf_filtered (" (cannot be evaluated in the current context)"); printf_filtered ("\n"); - fflush (stdout); + gdb_flush (gdb_stdout); } } @@ -1354,7 +1446,7 @@ enable_display (args, from_tty) d->status = enabled; goto win; } - printf ("No display number %d.\n", num); + printf_unfiltered ("No display number %d.\n", num); win: p = p1; while (*p == ' ' || *p == '\t') @@ -1402,9 +1494,9 @@ void print_variable_value (var, frame, stream) struct symbol *var; FRAME frame; - FILE *stream; + GDB_FILE *stream; { - value val = read_var_value (var, frame); + value_ptr val = read_var_value (var, frame); value_print (val, stream, 0, Val_pretty_default); } @@ -1421,14 +1513,14 @@ print_frame_args (func, fi, num, stream) struct symbol *func; struct frame_info *fi; int num; - FILE *stream; + GDB_FILE *stream; { struct block *b = NULL; int nsyms = 0; int first = 1; register int i; register struct symbol *sym; - register value val; + register value_ptr val; /* Offset of next stack argument beyond the one we have seen that is at the highest offset. -1 if we haven't come to a stack argument yet. */ @@ -1495,23 +1587,61 @@ print_frame_args (func, fi, num, stream) and it is passed as a double and converted to float by the prologue (in the latter case the type of the LOC_ARG symbol is double and the type of the LOC_LOCAL symbol is - float). There are also LOC_ARG/LOC_REGISTER pairs which - are not combined in symbol-reading. */ + float). */ /* But if the parameter name is null, don't try it. Null parameter names occur on the RS/6000, for traceback tables. FIXME, should we even print them? */ if (*SYMBOL_NAME (sym)) - sym = lookup_symbol - (SYMBOL_NAME (sym), - b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL); + { + struct symbol *nsym; + nsym = lookup_symbol + (SYMBOL_NAME (sym), + b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL); + if (SYMBOL_CLASS (nsym) == LOC_REGISTER) + { + /* There is a LOC_ARG/LOC_REGISTER pair. This means that + it was passed on the stack and loaded into a register, + or passed in a register and stored in a stack slot. + GDB 3.x used the LOC_ARG; GDB 4.0-4.11 used the LOC_REGISTER. + + Reasons for using the LOC_ARG: + (1) because find_saved_registers may be slow for remote + debugging, + (2) because registers are often re-used and stack slots + rarely (never?) are. Therefore using the stack slot is + much less likely to print garbage. + + Reasons why we might want to use the LOC_REGISTER: + (1) So that the backtrace prints the same value as + "print foo". I see no compelling reason why this needs + to be the case; having the backtrace print the value which + was passed in, and "print foo" print the value as modified + within the called function, makes perfect sense to me. + + Additional note: It might be nice if "info args" displayed + both values. + One more note: There is a case with sparc structure passing + where we need to use the LOC_REGISTER, but this is dealt with + by creating a single LOC_REGPARM in symbol reading. */ + + /* Leave sym (the LOC_ARG) alone. */ + ; + } + else + sym = nsym; + } /* Print the current arg. */ if (! first) fprintf_filtered (stream, ", "); wrap_here (" "); + + annotate_arg_begin (); + fprintf_symbol_filtered (stream, SYMBOL_SOURCE_NAME (sym), SYMBOL_LANGUAGE (sym), DMGL_PARAMS | DMGL_ANSI); + annotate_arg_name_end (); fputs_filtered ("=", stream); /* Avoid value_print because it will deref ref parameters. We just @@ -1520,11 +1650,17 @@ print_frame_args (func, fi, num, stream) standard indentation here is 4 spaces, and val_print indents 2 for each recurse. */ val = read_var_value (sym, FRAME_INFO_ID (fi)); + + annotate_arg_value (val == NULL ? NULL : VALUE_TYPE (val)); + if (val) val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), VALUE_ADDRESS (val), stream, 0, 0, 2, Val_no_prettyprint); else fputs_filtered ("???", stream); + + annotate_arg_end (); + first = 0; } @@ -1555,7 +1691,7 @@ print_frame_nameless_args (fi, start, num, first, stream) long start; int num; int first; - FILE *stream; + GDB_FILE *stream; { int i; CORE_ADDR argsaddr; @@ -1600,15 +1736,14 @@ printf_command (arg, from_tty) register char *f; register char *s = arg; char *string; - value *val_args; + value_ptr *val_args; char *substrings; char *current_substring; int nargs = 0; int allocated_args = 20; - va_list args_to_vprintf; struct cleanup *old_cleanups; - val_args = (value *) xmalloc (allocated_args * sizeof (value)); + val_args = (value_ptr *) xmalloc (allocated_args * sizeof (value_ptr)); old_cleanups = make_cleanup (free_current_contents, &val_args); if (s == 0) @@ -1640,21 +1775,38 @@ printf_command (arg, from_tty) case '\\': *f++ = '\\'; break; + case 'a': +#ifdef __STDC__ + *f++ = '\a'; +#else + *f++ = '\007'; /* Bell */ +#endif + break; + case 'b': + *f++ = '\b'; + break; + case 'f': + *f++ = '\f'; + break; case 'n': *f++ = '\n'; break; + case 'r': + *f++ = '\r'; + break; case 't': *f++ = '\t'; break; - case 'r': - *f++ = '\r'; + case 'v': + *f++ = '\v'; break; case '"': *f++ = '"'; break; default: /* ??? TODO: handle other escape sequences */ - error ("Unrecognized \\ escape character in format string."); + error ("Unrecognized escape character \\%c in format string.", + c); } break; @@ -1680,8 +1832,8 @@ printf_command (arg, from_tty) { /* Now scan the string for %-specs and see what kinds of args they want. - argclass[I] classifies the %-specs so we can give vprintf something - of the right size. */ + argclass[I] classifies the %-specs so we can give printf_filtered + something of the right size. */ enum argclass {no_arg, int_arg, string_arg, double_arg, long_long_arg}; enum argclass *argclass; @@ -1752,9 +1904,9 @@ printf_command (arg, from_tty) { char *s1; if (nargs == allocated_args) - val_args = (value *) xrealloc ((char *) val_args, - (allocated_args *= 2) - * sizeof (value)); + val_args = (value_ptr *) xrealloc ((char *) val_args, + (allocated_args *= 2) + * sizeof (value_ptr)); s1 = s; val_args[nargs] = parse_to_comma_and_eval (&s1); @@ -1777,16 +1929,6 @@ printf_command (arg, from_tty) if (nargs != nargs_wanted) error ("Wrong number of arguments for specified format-string"); - /* FIXME: We should be using vprintf_filtered, but as long as it - has an arbitrary limit that is unacceptable. Correct fix is - for vprintf_filtered to scan down the format string so it knows - how big a buffer it needs (perhaps by putting a vasprintf (see - GNU C library) in libiberty). - - But for now, just force out any pending output, so at least the output - appears in the correct order. */ - wrap_here ((char *)NULL); - /* Now actually print them. */ current_substring = substrings; for (i = 0; i < nargs; i++) @@ -1815,23 +1957,20 @@ printf_command (arg, from_tty) read_memory (tem, str, j); str[j] = 0; - /* Don't use printf_filtered because of arbitrary limit. */ - printf (current_substring, str); + printf_filtered (current_substring, str); } break; case double_arg: { double val = value_as_double (val_args[i]); - /* Don't use printf_filtered because of arbitrary limit. */ - printf (current_substring, val); + printf_filtered (current_substring, val); break; } case long_long_arg: #if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG) { long long val = value_as_long (val_args[i]); - /* Don't use printf_filtered because of arbitrary limit. */ - printf (current_substring, val); + printf_filtered (current_substring, val); break; } #else @@ -1841,8 +1980,7 @@ printf_command (arg, from_tty) { /* FIXME: there should be separate int_arg and long_arg. */ long val = value_as_long (val_args[i]); - /* Don't use printf_filtered because of arbitrary limit. */ - printf (current_substring, val); + printf_filtered (current_substring, val); break; } default: @@ -1852,8 +1990,7 @@ printf_command (arg, from_tty) current_substring += strlen (current_substring) + 1; } /* Print the portion of the format string after the last argument. */ - /* It would be OK to use printf_filtered here. */ - printf (last_arg); + printf_filtered (last_arg); } do_cleanups (old_cleanups); } @@ -1908,21 +2045,26 @@ disassemble_command (arg, from_tty) } else { - printf_filtered ("from %s ", local_hex_string((unsigned long) low)); - printf_filtered ("to %s:\n", local_hex_string((unsigned long) high)); + printf_filtered ("from "); + print_address_numeric (low, 1, gdb_stdout); + printf_filtered (" to "); + print_address_numeric (high, 1, gdb_stdout); + printf_filtered (":\n"); } /* Dump the specified range. */ for (pc = low; pc < high; ) { QUIT; - print_address (pc, stdout); + print_address (pc, gdb_stdout); printf_filtered (":\t"); - pc += print_insn (pc, stdout); + /* We often wrap here if there are long symbolic names. */ + wrap_here (" "); + pc += print_insn (pc, gdb_stdout); printf_filtered ("\n"); } printf_filtered ("End of assembler dump.\n"); - fflush (stdout); + gdb_flush (gdb_stdout); } diff --git a/gnu/usr.bin/gdb/gdb/regex.c b/gnu/usr.bin/gdb/gdb/regex.c index 75bf4e9fc234..3f30284a6397 100644 --- a/gnu/usr.bin/gdb/gdb/regex.c +++ b/gnu/usr.bin/gdb/gdb/regex.c @@ -32,14 +32,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #else /* not emacs */ -/* Make alloca work the best possible way. */ -#ifdef __GNUC__ -#define alloca __builtin_alloca -#else -#ifdef sparc -#include -#endif -#endif +#include "defs.h" +#include /* * Define the syntax stuff, so we can do the \<...\> things. @@ -99,8 +93,16 @@ init_syntax_once () #define BYTEWIDTH 8 -#ifndef SIGN_EXTEND_CHAR -#define SIGN_EXTEND_CHAR(x) (x) +/* We remove any previous definition of `SIGN_EXTEND_CHAR', + since ours (we hope) works properly with all combinations of + machines, compilers, `char' and `unsigned char' argument types. + (Per Bothner suggested the basic approach.) */ +#undef SIGN_EXTEND_CHAR +#if __STDC__ +#define SIGN_EXTEND_CHAR(c) ((signed char) (c)) +#else /* not __STDC__ */ +/* As in Harbison and Steele. */ +#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) #endif static int obscure_syntax = 0; @@ -152,23 +154,40 @@ re_set_syntax (syntax) #define PATUNFETCH p-- -#define EXTEND_BUFFER \ - { char *old_buffer = bufp->buffer; \ - if (bufp->allocated == (1<<16)) goto too_big; \ - bufp->allocated *= 2; \ - if (bufp->allocated > (1<<16)) bufp->allocated = (1<<16); \ - if (!(bufp->buffer = (char *) realloc (bufp->buffer, bufp->allocated))) \ - goto memory_exhausted; \ - c = bufp->buffer - old_buffer; \ - b += c; \ - if (fixup_jump) \ - fixup_jump += c; \ - if (laststart) \ - laststart += c; \ - begalt += c; \ - if (pending_exact) \ - pending_exact += c; \ - } +/* This is not an arbitrary limit: the arguments which represent offsets + into the pattern are two bytes long. So if 2^16 bytes turns out to + be too small, many things would have to change. */ +#define MAX_BUF_SIZE (1 << 16) + + +/* Extend the buffer by twice its current size via realloc and + reset the pointers that pointed into the old block to point to the + correct places in the new one. If extending the buffer results in it + being larger than MAX_BUF_SIZE, then flag memory exhausted. */ +#define EXTEND_BUFFER \ + do { \ + char *old_buffer = bufp->buffer; \ + if (bufp->allocated == MAX_BUF_SIZE) \ + goto too_big; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + bufp->buffer = (char *) realloc (bufp->buffer, bufp->allocated);\ + if (bufp->buffer == NULL) \ + goto memory_exhausted; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != bufp->buffer) \ + { \ + b = (b - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (fixup_jump) \ + fixup_jump = (fixup_jump - old_buffer) + bufp->buffer;\ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + } \ + } while (0) static void store_jump (), insert_jump (); @@ -1556,7 +1575,7 @@ static struct re_pattern_buffer re_comp_buf; char * re_comp (s) - char *s; + const char *s; { if (!s) { @@ -1657,21 +1676,21 @@ main (argc, argv) for (i = 0; i < buf.used; i++) printchar (buf.buffer[i]); - putchar ('\n'); + putchar_unfiltered ('\n'); - printf ("%d allocated, %d used.\n", buf.allocated, buf.used); + printf_unfiltered ("%d allocated, %d used.\n", buf.allocated, buf.used); re_compile_fastmap (&buf); - printf ("Allowed by fastmap: "); + printf_unfiltered ("Allowed by fastmap: "); for (i = 0; i < (1 << BYTEWIDTH); i++) if (fastmap[i]) printchar (i); - putchar ('\n'); + putchar_unfiltered ('\n'); } gets (pat); /* Now read the string to match against */ i = re_match (&buf, pat, strlen (pat), 0, 0); - printf ("Match value %d.\n", i); + printf_unfiltered ("Match value %d.\n", i); } } @@ -1681,23 +1700,23 @@ print_buf (bufp) { int i; - printf ("buf is :\n----------------\n"); + printf_unfiltered ("buf is :\n----------------\n"); for (i = 0; i < bufp->used; i++) printchar (bufp->buffer[i]); - printf ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used); + printf_unfiltered ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used); - printf ("Allowed by fastmap: "); + printf_unfiltered ("Allowed by fastmap: "); for (i = 0; i < (1 << BYTEWIDTH); i++) if (bufp->fastmap[i]) printchar (i); - printf ("\nAllowed by translate: "); + printf_unfiltered ("\nAllowed by translate: "); if (bufp->translate) for (i = 0; i < (1 << BYTEWIDTH); i++) if (bufp->translate[i]) printchar (i); - printf ("\nfastmap is%s accurate\n", bufp->fastmap_accurate ? "" : "n't"); - printf ("can %s be null\n----------", bufp->can_be_null ? "" : "not"); + printf_unfiltered ("\nfastmap is%s accurate\n", bufp->fastmap_accurate ? "" : "n't"); + printf_unfiltered ("can %s be null\n----------", bufp->can_be_null ? "" : "not"); } #endif @@ -1706,19 +1725,19 @@ printchar (c) { if (c < 041 || c >= 0177) { - putchar ('\\'); - putchar (((c >> 6) & 3) + '0'); - putchar (((c >> 3) & 7) + '0'); - putchar ((c & 7) + '0'); + putchar_unfiltered ('\\'); + putchar_unfiltered (((c >> 6) & 3) + '0'); + putchar_unfiltered (((c >> 3) & 7) + '0'); + putchar_unfiltered ((c & 7) + '0'); } else - putchar (c); + putchar_unfiltered (c); } error (string) char *string; { - puts (string); + puts_unfiltered (string); exit (1); } diff --git a/gnu/usr.bin/gdb/gdb/regex.h b/gnu/usr.bin/gdb/gdb/regex.h index 6348c3eb6e45..a4ed6d3591e0 100644 --- a/gnu/usr.bin/gdb/gdb/regex.h +++ b/gnu/usr.bin/gdb/gdb/regex.h @@ -177,3 +177,5 @@ extern int re_exec (); #ifdef SYNTAX_TABLE extern char *re_syntax_table; #endif + +extern int re_set_syntax (); diff --git a/gnu/usr.bin/gdb/gdb/remote-utils.c b/gnu/usr.bin/gdb/gdb/remote-utils.c index f4f25e4c490c..ba7d29712d9f 100644 --- a/gnu/usr.bin/gdb/gdb/remote-utils.c +++ b/gnu/usr.bin/gdb/gdb/remote-utils.c @@ -1,6 +1,6 @@ /* Generic support for remote debugging interfaces. - Copyright 1993 Free Software Foundation, Inc. + Copyright 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -37,13 +37,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ * a pass through mode a la kermit or telnet. * autobaud. * ask remote to change his baud rate. - * put generic load here. - */ #include #include "defs.h" +#include #include "gdbcmd.h" #include "target.h" #include "serial.h" @@ -76,12 +75,10 @@ usage(proto, junk) char *junk; { if (junk != NULL) - fprintf(stderr, "Unrecognized arguments: `%s'.\n", junk); + fprintf_unfiltered(gdb_stderr, "Unrecognized arguments: `%s'.\n", junk); - /* FIXME-now: service@host? */ - - error("Usage: target %s >>\n\ -or target %s \n", proto, proto); + error ("Usage: target %s [DEVICE [SPEED [DEBUG]]]\n\ +where DEVICE is the name of a device or HOST:PORT", proto, proto); return; } @@ -126,7 +123,7 @@ sr_scan_args(proto, args) /* check for missing or empty baud rate. */ CHECKDONE(p, q); - sr_set_baud_rate(n); + baud_rate = n; /* look for debug value. */ n = strtol(p, &q, 10); @@ -169,14 +166,24 @@ gr_open(args, from_tty, gr) if (sr_get_desc() != NULL) gr_close (0); + /* If no args are specified, then we use the device specified by a + previous command or "set remotedevice". But if there is no + device, better stop now, not dump core. */ + + if (sr_get_device () == NULL) + usage (gr->ops->to_shortname, NULL); + sr_set_desc(SERIAL_OPEN (sr_get_device())); if (!sr_get_desc()) perror_with_name((char *) sr_get_device()); - if (SERIAL_SETBAUDRATE(sr_get_desc(), sr_get_baud_rate()) != 0) + if (baud_rate != -1) { - SERIAL_CLOSE(sr_get_desc()); - perror_with_name(sr_get_device()); + if (SERIAL_SETBAUDRATE(sr_get_desc(), baud_rate) != 0) + { + SERIAL_CLOSE(sr_get_desc()); + perror_with_name(sr_get_device()); + } } SERIAL_RAW (sr_get_desc()); @@ -194,8 +201,13 @@ gr_open(args, from_tty, gr) gr_settings->clear_all_breakpoints = remove_breakpoints; if (from_tty) - printf_filtered ("Remote debugging using `%s' at baud rate of %d\n", - sr_get_device(), sr_get_baud_rate()); + { + printf_filtered ("Remote debugging using `%s'", sr_get_device ()); + if (baud_rate != -1) + printf_filtered (" at baud rate of %d", + baud_rate); + printf_filtered ("\n"); + } push_target(gr->ops); gr_checkin(); @@ -217,7 +229,7 @@ sr_readchar () error ("Timeout reading from remote system."); if (sr_get_debug() > 0) - printf ("%c", buf); + printf_unfiltered ("%c", buf); return buf & 0x7f; } @@ -232,9 +244,9 @@ sr_pollchar() buf = 0; if (sr_get_debug() > 0) if (buf) - printf ("%c", buf); + printf_unfiltered ("%c", buf); else - printf (""); + printf_unfiltered (""); return buf & 0x7f; } @@ -276,7 +288,7 @@ sr_write (a, l) if (sr_get_debug() > 0) for (i = 0; i < l; i++) - printf ("%c", a[i]); + printf_unfiltered ("%c", a[i]); return; } @@ -432,22 +444,20 @@ void gr_files_info (ops) struct target_ops *ops; { - char *file = "nothing"; - - if (exec_bfd) - file = bfd_get_filename (exec_bfd); +#ifdef __GO32__ + printf_filtered ("\tAttached to DOS asynctsr\n"); +#else + printf_filtered ("\tAttached to %s", sr_get_device()); + if (baud_rate != -1) + printf_filtered ("at %d baud", baud_rate); + printf_filtered ("\n"); +#endif if (exec_bfd) { -#ifdef __GO32__ - printf_filtered ("\tAttached to DOS asynctsr\n"); -#else - printf_filtered ("\tAttached to %s at %d baud\n", - sr_get_device(), sr_get_baud_rate()); -#endif + printf_filtered ("\tand running program %s\n", + bfd_get_filename (exec_bfd)); } - - printf_filtered ("\tand running program %s\n", file); printf_filtered ("\tusing the %s protocol.\n", ops->to_shortname); } @@ -573,9 +583,9 @@ gr_multi_scan (list, passthrough) if (passthrough) { for (p = swallowed; p < swallowed_p; ++p) - putc (*p, stdout); + fputc_unfiltered (*p, gdb_stdout); - putc (ch, stdout); + fputc_unfiltered (ch, gdb_stdout); } swallowed_p = swallowed; @@ -620,17 +630,66 @@ gr_store_word (addr, word) dcache_poke (gr_get_dcache(), addr, word); } +/* general purpose load a file specified on the command line + into target memory. */ + +void +gr_load_image (args, fromtty) + char *args; + int fromtty; +{ + bfd *abfd; + + asection *s; + struct cleanup *old_cleanups; + int delta = 4096; + char *buffer = xmalloc (delta); + + abfd = bfd_openr (args, (char *) 0); + + if (!abfd) + perror_with_name (args); + + old_cleanups = make_cleanup (bfd_close, abfd); + + QUIT; + + if (!bfd_check_format (abfd, bfd_object)) + error ("It doesn't seem to be an object file.\n"); + + for (s = abfd->sections; s && !quit_flag; s = s->next) + { + if (bfd_get_section_flags (abfd, s) & SEC_LOAD) + { + int i; + printf_filtered ("%s\t: 0x%4x .. 0x%4x ", + s->name, s->vma, s->vma + s->_raw_size); + fflush (stdout); + for (i = 0; i < s->_raw_size && !quit_flag; i += delta) + { + int sub_delta = delta; + if (sub_delta > s->_raw_size - i) + sub_delta = s->_raw_size - i; + QUIT; + bfd_get_section_contents (abfd, s, buffer, i, sub_delta); + target_write_memory (s->vma + i, buffer, sub_delta); + printf_filtered ("*"); + fflush (stdout); + } + printf_filtered ("\n"); + } + } + + free (buffer); + write_pc (bfd_get_start_address (abfd)); + bfd_close (abfd); + discard_cleanups (old_cleanups); +} + + void _initialize_sr_support () { -/* FIXME-now: if target is open when baud changes... */ - add_show_from_set (add_set_cmd ("remotebaud", no_class, - var_zinteger, (char *)&baud_rate, - "Set baud rate for remote serial I/O.\n\ -This value is used to set the speed of the serial port when debugging\n\ -using remote targets.", &setlist), - &showlist); - /* FIXME-now: if target is open... */ add_show_from_set (add_set_cmd ("remotedevice", no_class, var_filename, (char *)&sr_settings.device, diff --git a/gnu/usr.bin/gdb/gdb/remote-utils.h b/gnu/usr.bin/gdb/gdb/remote-utils.h index 59f4d3b3706f..9c344d83025f 100644 --- a/gnu/usr.bin/gdb/gdb/remote-utils.h +++ b/gnu/usr.bin/gdb/gdb/remote-utils.h @@ -39,17 +39,11 @@ struct _sr_settings { }; extern struct _sr_settings sr_settings; -extern int remote_debug; -extern int baud_rate; /* get and set debug value. */ #define sr_get_debug() (remote_debug) #define sr_set_debug(newval) (remote_debug = (newval)) -/* get and set baud rate. */ -#define sr_get_baud_rate() (baud_rate) -#define sr_set_baud_rate(newval) (baud_rate = (newval)) - /* get and set timeout. */ #define sr_get_timeout() (sr_settings.timeout) #define sr_set_timeout(newval) (sr_settings.timeout = (newval)) @@ -144,6 +138,5 @@ void sr_write_cr PARAMS((char *s)); void gr_open PARAMS((char *args, int from_tty, struct gr_settings *gr_settings)); - - +void gr_load_image PARAMS((char*, int from_tty)); #endif /* REMOTE_UTILS_H */ diff --git a/gnu/usr.bin/gdb/gdb/remote.c b/gnu/usr.bin/gdb/gdb/remote.c index 266d5f389def..371b14677cd8 100644 --- a/gnu/usr.bin/gdb/gdb/remote.c +++ b/gnu/usr.bin/gdb/gdb/remote.c @@ -1,5 +1,5 @@ /* Remote target communications for serial-line targets in custom GDB protocol - Copyright 1988, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1988, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -25,7 +25,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ $ # CSUM1 CSUM2 must be ASCII alphanumeric and cannot include characters - '$' or '#' + '$' or '#'. If starts with two characters followed by + ':', then the existing stubs interpret this as a sequence number. CSUM1 and CSUM2 are ascii hex representation of an 8-bit checksum of , the most significant nibble is sent first. @@ -54,6 +55,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ reply OK for success ENN for an error + write reg Pn...=r... Write register n... with value r..., + which contains two hex digits for each + byte in the register (target byte + order). + reply OK for success + ENN for an error + (not supported by all stubs). + read mem mAA..AA,LLLL AA..AA is address, LLLL is length. reply XX..XX XX..XX is mem contents Can be fewer bytes than requested @@ -90,22 +99,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ AA = signal number n... = register number r... = register contents - or... WAA The process extited, and AA is + or... WAA The process exited, and AA is the exit status. This is only applicable for certains sorts of targets. - or... NAATT;DD;BB Relocate the object file. - AA = signal number - TT = text address - DD = data address - BB = bss address - This is used by the NLM stub, - which is why it only has three - addresses rather than one per - section: the NLM stub always - sees only three sections, even - though gdb may see more. - kill request k toggle debug d toggle debug flag (see 386 & 68k stubs) @@ -116,7 +113,23 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ we can extend the protocol and GDB can tell whether the stub it is talking to uses the old or the new. -*/ + search tAA:PP,MM Search backwards starting at address + AA for a match with pattern PP and + mask MM. PP and MM are 4 bytes. + Not supported by all stubs. + + general query qXXXX Request info about XXXX. + general set QXXXX=yyyy Set value of XXXX to yyyy. + query sect offs qOffsets Get section offsets. Reply is + Text=xxx;Data=yyy;Bss=zzz + console output Otext Send text to stdout. Only comes from + remote target. + + Responses can be run-length encoded to save space. A '*' means that + the next two characters are hex digits giving a repeat count which + stands for that many repititions of the character preceding the '*'. + Note that this means that responses cannot contain '*'. Example: + "0*03" means the same as "0000". */ #include "defs.h" #include @@ -164,7 +177,7 @@ static void remote_fetch_registers PARAMS ((int regno)); static void -remote_resume PARAMS ((int pid, int step, int siggnal)); +remote_resume PARAMS ((int pid, int step, enum target_signal siggnal)); static int remote_start_remote PARAMS ((char *dummy)); @@ -188,10 +201,9 @@ static void remote_send PARAMS ((char *buf)); static int -readchar PARAMS ((void)); +readchar PARAMS ((int timeout)); -static int -remote_wait PARAMS ((int pid, WAITTYPE *status)); +static int remote_wait PARAMS ((int pid, struct target_waitstatus *status)); static int tohex PARAMS ((int nib)); @@ -213,15 +225,11 @@ interrupt_query PARAMS ((void)); extern struct target_ops remote_ops; /* Forward decl */ -extern int baud_rate; - -extern int remote_debug; - /* This was 5 seconds, which is a long time to sit and wait. Unless this is going though some terminal server or multiplexer or other form of hairy serial connection, I would think 2 seconds would be plenty. */ -static int timeout = 2; +static int remote_timeout = 2; #if 0 int icache; @@ -232,17 +240,30 @@ int icache; starts. */ serial_t remote_desc = NULL; -#define PBUFSIZ 1024 +/* Having this larger than 400 causes us to be incompatible with m68k-stub.c + and i386-stub.c. Normally, no one would notice because it only matters + for writing large chunks of memory (e.g. in downloads). Also, this needs + to be more than 400 if required to hold the registers (see below, where + we round it up based on REGISTER_BYTES). */ +#define PBUFSIZ 400 /* Maximum number of bytes to read/write at once. The value here is chosen to fill up a packet (the headers account for the 32). */ #define MAXBUFBYTES ((PBUFSIZ-32)/2) /* Round up PBUFSIZ to hold all the registers, at least. */ +/* The blank line after the #if seems to be required to work around a + bug in HP's PA compiler. */ #if REGISTER_BYTES > MAXBUFBYTES -#undef PBUFSIZ + +#undef PBUFSIZ #define PBUFSIZ (REGISTER_BYTES * 2 + 32) #endif + +/* Should we try the 'P' request? If this is set to one when the stub + doesn't support 'P', the only consequence is some unnecessary traffic. */ +static int stub_supports_P = 1; + /* Clean up connection to a remote debugger. */ @@ -256,6 +277,63 @@ remote_close (quitting) remote_desc = NULL; } +/* Query the remote side for the text, data and bss offsets. */ + +static void +get_offsets () +{ + unsigned char buf[PBUFSIZ]; + int nvals; + CORE_ADDR text_addr, data_addr, bss_addr; + struct section_offsets *offs; + + putpkt ("qOffsets"); + + getpkt (buf, 0); + + if (buf[0] == '\000') + return; /* Return silently. Stub doesn't support this + command. */ + if (buf[0] == 'E') + { + warning ("Remote failure reply: %s", buf); + return; + } + + nvals = sscanf (buf, "Text=%lx;Data=%lx;Bss=%lx", &text_addr, &data_addr, + &bss_addr); + if (nvals != 3) + error ("Malformed response to offset query, %s", buf); + + if (symfile_objfile == NULL) + return; + + offs = (struct section_offsets *) alloca (sizeof (struct section_offsets) + + symfile_objfile->num_sections + * sizeof (offs->offsets)); + memcpy (offs, symfile_objfile->section_offsets, + sizeof (struct section_offsets) + + symfile_objfile->num_sections + * sizeof (offs->offsets)); + + /* FIXME: This code assumes gdb-stabs.h is being used; it's broken + for xcoff, dwarf, sdb-coff, etc. But there is no simple + canonical representation for this stuff. (Just what does "text" + as seen by the stub mean, anyway? I think it means all sections + with SEC_CODE set, but we currently have no way to deal with that). */ + + ANOFFSET (offs, SECT_OFF_TEXT) = text_addr; + + /* This is a temporary kludge to force data and bss to use the same offsets + because that's what nlmconv does now. The real solution requires changes + to the stub and remote.c that I don't have time to do right now. */ + + ANOFFSET (offs, SECT_OFF_DATA) = data_addr; + ANOFFSET (offs, SECT_OFF_BSS) = data_addr; + + objfile_relocate (symfile_objfile, offs); +} + /* Stub for catch_errors. */ static int @@ -265,13 +343,16 @@ remote_start_remote (dummy) immediate_quit = 1; /* Allow user to interrupt it */ /* Ack any packet which the remote side has already sent. */ - /* I'm not sure this \r is needed; we don't use it any other time we - send an ack. */ - SERIAL_WRITE (remote_desc, "+\r", 2); + + SERIAL_WRITE (remote_desc, "+", 1); + + get_offsets (); /* Get text, data & bss offsets */ + putpkt ("?"); /* initiate a query from remote machine */ immediate_quit = 0; start_remote (); /* Initialize gdb process mechanisms */ + return 1; } @@ -300,10 +381,13 @@ device is attached to the remote system (e.g. /dev/ttya)."); if (!remote_desc) perror_with_name (name); - if (SERIAL_SETBAUDRATE (remote_desc, baud_rate)) + if (baud_rate != -1) { - SERIAL_CLOSE (remote_desc); - perror_with_name (name); + if (SERIAL_SETBAUDRATE (remote_desc, baud_rate)) + { + SERIAL_CLOSE (remote_desc); + perror_with_name (name); + } } SERIAL_RAW (remote_desc); @@ -320,6 +404,11 @@ device is attached to the remote system (e.g. /dev/ttya)."); } push_target (&remote_ops); /* Switch to using remote target now */ + /* Start out by trying the 'P' request to set registers. We set this each + time that we open a new target so that if the user switches from one + stub to another, we can (if the target is closed and reopened) cope. */ + stub_supports_P = 1; + /* Start the remote connection; if error (0), discard this target. In particular, if the user quits, be sure to discard it (we'd be in an inconsistent state otherwise). */ @@ -361,7 +450,6 @@ fromhex (a) return a - 'a' + 10; else error ("Reply contains invalid hex digit"); - return -1; } /* Convert number NIB to a hex digit. */ @@ -380,21 +468,17 @@ tohex (nib) static void remote_resume (pid, step, siggnal) - int pid, step, siggnal; + int pid, step; + enum target_signal siggnal; { char buf[PBUFSIZ]; if (siggnal) { - char *name; target_terminal_ours_for_output (); - printf_filtered ("Can't send signals to a remote system. "); - name = strsigno (siggnal); - if (name) - printf_filtered (name); - else - printf_filtered ("Signal %d", siggnal); - printf_filtered (" not sent.\n"); + printf_filtered + ("Can't send signals to a remote system. %s not sent.\n", + target_signal_to_name (siggnal)); target_terminal_inferior (); } @@ -416,7 +500,7 @@ remote_interrupt (signo) signal (signo, remote_interrupt_twice); if (remote_debug) - printf ("remote_interrupt called\n"); + printf_unfiltered ("remote_interrupt called\n"); SERIAL_WRITE (remote_desc, "\003", 1); /* Send a ^C */ } @@ -460,11 +544,12 @@ Give up (and stop debugging it)? ")) static int remote_wait (pid, status) int pid; - WAITTYPE *status; + struct target_waitstatus *status; { unsigned char buf[PBUFSIZ]; - WSETEXIT ((*status), 0); + status->kind = TARGET_WAITKIND_EXITED; + status->value.integer = 0; while (1) { @@ -474,162 +559,82 @@ remote_wait (pid, status) getpkt ((char *) buf, 1); signal (SIGINT, ofunc); - if (buf[0] == 'E') - warning ("Remote failure reply: %s", buf); - else if (buf[0] == 'T') + switch (buf[0]) { - int i; - long regno; - char regs[MAX_REGISTER_RAW_SIZE]; + case 'E': /* Error of some sort */ + warning ("Remote failure reply: %s", buf); + continue; + case 'T': /* Status with PC, SP, FP, ... */ + { + int i; + long regno; + char regs[MAX_REGISTER_RAW_SIZE]; - /* Expedited reply, containing Signal, {regno, reg} repeat */ - /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where - ss = signal number - n... = register number - r... = register contents - */ + /* Expedited reply, containing Signal, {regno, reg} repeat */ + /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where + ss = signal number + n... = register number + r... = register contents + */ - p = &buf[3]; /* after Txx */ + p = &buf[3]; /* after Txx */ - while (*p) - { - unsigned char *p1; - - regno = strtol (p, &p1, 16); /* Read the register number */ - - if (p1 == p) - warning ("Remote sent badly formed register number: %s\nPacket: '%s'\n", - p1, buf); - - p = p1; - - if (*p++ != ':') - warning ("Malformed packet (missing colon): %s\nPacket: '%s'\n", - p, buf); - - if (regno >= NUM_REGS) - warning ("Remote sent bad register number %d: %s\nPacket: '%s'\n", - regno, p, buf); - - for (i = 0; i < REGISTER_RAW_SIZE (regno); i++) - { - if (p[0] == 0 || p[1] == 0) - warning ("Remote reply is too short: %s", buf); - regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); - p += 2; - } - - if (*p++ != ';') - warning ("Remote register badly formatted: %s", buf); - - supply_register (regno, regs); - } - break; - } - else if (buf[0] == 'N') - { - unsigned char *p1; - bfd_vma text_addr, data_addr, bss_addr; - - /* Relocate object file. Format is NAATT;DD;BB where AA is - the signal number, TT is the new text address, DD is the - new data address, and BB is the new bss address. This is - used by the NLM stub; gdb may see more sections. */ - p = &buf[3]; - text_addr = strtoul (p, &p1, 16); - if (p1 == p || *p1 != ';') - warning ("Malformed relocation packet: Packet '%s'", buf); - p = p1 + 1; - data_addr = strtoul (p, &p1, 16); - if (p1 == p || *p1 != ';') - warning ("Malformed relocation packet: Packet '%s'", buf); - p = p1 + 1; - bss_addr = strtoul (p, &p1, 16); - if (p1 == p) - warning ("Malformed relocation packet: Packet '%s'", buf); - - if (symfile_objfile != NULL - && (ANOFFSET (symfile_objfile->section_offsets, - SECT_OFF_TEXT) != text_addr - || ANOFFSET (symfile_objfile->section_offsets, - SECT_OFF_DATA) != data_addr - || ANOFFSET (symfile_objfile->section_offsets, - SECT_OFF_BSS) != bss_addr)) - { - struct section_offsets *offs; - - /* FIXME: This code assumes gdb-stabs.h is being used; - it's broken for xcoff, dwarf, sdb-coff, etc. But - there is no simple canonical representation for this - stuff. (Just what does "text" as seen by the stub - mean, anyway?). */ - - /* FIXME: Why don't the various symfile_offsets routines - in the sym_fns vectors set this? - (no good reason -kingdon). */ - if (symfile_objfile->num_sections == 0) - symfile_objfile->num_sections = SECT_OFF_MAX; - - offs = ((struct section_offsets *) - alloca (sizeof (struct section_offsets) - + (symfile_objfile->num_sections - * sizeof (offs->offsets)))); - memcpy (offs, symfile_objfile->section_offsets, - (sizeof (struct section_offsets) - + (symfile_objfile->num_sections - * sizeof (offs->offsets)))); - ANOFFSET (offs, SECT_OFF_TEXT) = text_addr; - ANOFFSET (offs, SECT_OFF_DATA) = data_addr; - ANOFFSET (offs, SECT_OFF_BSS) = bss_addr; - - objfile_relocate (symfile_objfile, offs); + while (*p) { - struct obj_section *s; - bfd *abfd; + unsigned char *p1; - abfd = symfile_objfile->obfd; + regno = strtol (p, &p1, 16); /* Read the register number */ - for (s = symfile_objfile->sections; - s < symfile_objfile->sections_end; ++s) + if (p1 == p) + warning ("Remote sent badly formed register number: %s\nPacket: '%s'\n", + p1, buf); + + p = p1; + + if (*p++ != ':') + warning ("Malformed packet (missing colon): %s\nPacket: '%s'\n", + p, buf); + + if (regno >= NUM_REGS) + warning ("Remote sent bad register number %d: %s\nPacket: '%s'\n", + regno, p, buf); + + for (i = 0; i < REGISTER_RAW_SIZE (regno); i++) { - flagword flags; - - flags = bfd_get_section_flags (abfd, s->sec_ptr); - - if (flags & SEC_CODE) - { - s->addr += text_addr; - s->endaddr += text_addr; - } - else if (flags & (SEC_DATA | SEC_LOAD)) - { - s->addr += data_addr; - s->endaddr += data_addr; - } - else if (flags & SEC_ALLOC) - { - s->addr += bss_addr; - s->endaddr += bss_addr; - } + if (p[0] == 0 || p[1] == 0) + warning ("Remote reply is too short: %s", buf); + regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); + p += 2; } + + if (*p++ != ';') + warning ("Remote register badly formatted: %s", buf); + + supply_register (regno, regs); } - } - break; - } - else if (buf[0] == 'W') - { - /* The remote process exited. */ - WSETEXIT (*status, (fromhex (buf[1]) << 4) + fromhex (buf[2])); + } + /* fall through */ + case 'S': /* Old style status, just signal only */ + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = (enum target_signal) + (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))); + return 0; + case 'W': /* Target exited */ + { + /* The remote process exited. */ + status->kind = TARGET_WAITKIND_EXITED; + status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]); + return 0; + } + case 'O': /* Console output */ + fputs_filtered (buf + 1, gdb_stdout); + continue; + default: + warning ("Invalid remote reply: %s", buf); + continue; } - else if (buf[0] == 'S') - break; - else - warning ("Invalid remote reply: %s", buf); } - - WSETSTOP ((*status), (((fromhex (buf[1])) << 4) + (fromhex (buf[2])))); - return 0; } @@ -661,7 +666,7 @@ remote_fetch_registers (regno) && (buf[0] < 'a' || buf[0] > 'f')) { if (remote_debug) - printf ("Bad register packet; fetching a new packet\n"); + printf_unfiltered ("Bad register packet; fetching a new packet\n"); getpkt (buf, 0); } @@ -699,8 +704,9 @@ remote_fetch_registers (regno) supply_register (i, ®s[REGISTER_BYTE(i)]); } -/* Prepare to store registers. Since we send them all, we have to - read out the ones we don't want to change first. */ +/* Prepare to store registers. Since we may send them all (using a + 'G' request), we have to read out the ones we don't want to change + first. */ static void remote_prepare_to_store () @@ -709,10 +715,9 @@ remote_prepare_to_store () read_register_bytes (0, (char *)NULL, REGISTER_BYTES); } -/* Store the remote registers from the contents of the block REGISTERS. - FIXME, eventually just store one register if that's all that is needed. */ +/* Store register REGNO, or all registers if REGNO == -1, from the contents + of REGISTERS. FIXME: ignores errors. */ -/* ARGSUSED */ static void remote_store_registers (regno) int regno; @@ -721,8 +726,35 @@ remote_store_registers (regno) int i; char *p; + if (regno >= 0 && stub_supports_P) + { + /* Try storing a single register. */ + char *regp; + + sprintf (buf, "P%x=", regno); + p = buf + strlen (buf); + regp = ®isters[REGISTER_BYTE (regno)]; + for (i = 0; i < REGISTER_RAW_SIZE (regno); ++i) + { + *p++ = tohex ((regp[i] >> 4) & 0xf); + *p++ = tohex (regp[i] & 0xf); + } + *p = '\0'; + remote_send (buf); + if (buf[0] != '\0') + { + /* The stub understands the 'P' request. We are done. */ + return; + } + + /* The stub does not support the 'P' request. Use 'G' instead, + and don't try using 'P' in the future (it will just waste our + time). */ + stub_supports_P = 0; + } + buf[0] = 'G'; - + /* Command describes registers byte by byte, each byte encoded as two hex characters. */ @@ -802,10 +834,9 @@ remote_write_bytes (memaddr, myaddr, len) int i; char *p; - if (len > PBUFSIZ / 2 - 20) - abort (); - - sprintf (buf, "M%x,%x:", memaddr, len); + /* FIXME-32x64: Need a version of print_address_numeric which puts the + result in a buffer like sprintf. */ + sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, len); /* We send target system values byte by byte, in increasing byte addresses, each byte encoded as two hex characters. */ @@ -854,7 +885,9 @@ remote_read_bytes (memaddr, myaddr, len) if (len > PBUFSIZ / 2 - 1) abort (); - sprintf (buf, "m%x,%x", memaddr, len); + /* FIXME-32x64: Need a version of print_address_numeric which puts the + result in a buffer like sprintf. */ + sprintf (buf, "m%lx,%x", (unsigned long) memaddr, len); putpkt (buf); getpkt (buf, 0); @@ -909,9 +942,11 @@ remote_xfer_memory(memaddr, myaddr, len, should_write, target) xfersize = len; if (should_write) - bytes_xferred = remote_write_bytes (memaddr, myaddr, xfersize); + bytes_xferred = remote_write_bytes (memaddr, + (unsigned char *)myaddr, xfersize); else - bytes_xferred = remote_read_bytes (memaddr, myaddr, xfersize); + bytes_xferred = remote_read_bytes (memaddr, + (unsigned char *)myaddr, xfersize); /* If we get an error, we are done xferring. */ if (bytes_xferred == 0) @@ -925,6 +960,80 @@ remote_xfer_memory(memaddr, myaddr, len, should_write, target) return total_xferred; } +#if 0 +/* Enable after 4.12. */ + +void +remote_search (len, data, mask, startaddr, increment, lorange, hirange + addr_found, data_found) + int len; + char *data; + char *mask; + CORE_ADDR startaddr; + int increment; + CORE_ADDR lorange; + CORE_ADDR hirange; + CORE_ADDR *addr_found; + char *data_found; +{ + if (increment == -4 && len == 4) + { + long mask_long, data_long; + long data_found_long; + CORE_ADDR addr_we_found; + char buf[PBUFSIZ]; + long returned_long[2]; + char *p; + + mask_long = extract_unsigned_integer (mask, len); + data_long = extract_unsigned_integer (data, len); + sprintf (buf, "t%x:%x,%x", startaddr, data_long, mask_long); + putpkt (buf); + getpkt (buf, 0); + if (buf[0] == '\0') + { + /* The stub doesn't support the 't' request. We might want to + remember this fact, but on the other hand the stub could be + switched on us. Maybe we should remember it only until + the next "target remote". */ + generic_search (len, data, mask, startaddr, increment, lorange, + hirange, addr_found, data_found); + return; + } + + if (buf[0] == 'E') + /* There is no correspondance between what the remote protocol uses + for errors and errno codes. We would like a cleaner way of + representing errors (big enough to include errno codes, bfd_error + codes, and others). But for now just use EIO. */ + memory_error (EIO, startaddr); + p = buf; + addr_we_found = 0; + while (*p != '\0' && *p != ',') + addr_we_found = (addr_we_found << 4) + fromhex (*p++); + if (*p == '\0') + error ("Protocol error: short return for search"); + + data_found_long = 0; + while (*p != '\0' && *p != ',') + data_found_long = (data_found_long << 4) + fromhex (*p++); + /* Ignore anything after this comma, for future extensions. */ + + if (addr_we_found < lorange || addr_we_found >= hirange) + { + *addr_found = 0; + return; + } + + *addr_found = addr_we_found; + *data_found = store_unsigned_integer (data_we_found, len); + return; + } + generic_search (len, data, mask, startaddr, increment, lorange, + hirange, addr_found, data_found); +} +#endif /* 0 */ + static void remote_files_info (ignore) struct target_ops *ignore; @@ -938,16 +1047,24 @@ remote_files_info (ignore) /* Read a single character from the remote end, masking it down to 7 bits. */ static int -readchar () +readchar (timeout) + int timeout; { int ch; ch = SERIAL_READCHAR (remote_desc, timeout); - if (ch < 0) - return ch; - - return ch & 0x7f; + switch (ch) + { + case SERIAL_EOF: + error ("Remote connection closed"); + case SERIAL_ERROR: + perror_with_name ("Remote communication error"); + case SERIAL_TIMEOUT: + return ch; + default: + return ch & 0x7f; + } } /* Send the command in BUF to the remote machine, @@ -1002,10 +1119,13 @@ putpkt (buf) while (1) { + int started_error_output = 0; + if (remote_debug) { *p = '\0'; - printf ("Sending packet: %s...", buf2); fflush(stdout); + printf_unfiltered ("Sending packet: %s...", buf2); + gdb_flush(gdb_stdout); } if (SERIAL_WRITE (remote_desc, buf2, p - buf2)) perror_with_name ("putpkt: write failed"); @@ -1013,33 +1133,151 @@ putpkt (buf) /* read until either a timeout occurs (-2) or '+' is read */ while (1) { - ch = readchar (); + ch = readchar (remote_timeout); + + if (remote_debug) + { + switch (ch) + { + case '+': + case SERIAL_TIMEOUT: + case '$': + if (started_error_output) + { + putc_unfiltered ('\n'); + started_error_output = 0; + } + } + } switch (ch) { case '+': if (remote_debug) - printf("Ack\n"); + printf_unfiltered("Ack\n"); return; case SERIAL_TIMEOUT: break; /* Retransmit buffer */ - case SERIAL_ERROR: - perror_with_name ("putpkt: couldn't read ACK"); - case SERIAL_EOF: - error ("putpkt: EOF while trying to read ACK"); + case '$': + { + unsigned char junkbuf[PBUFSIZ]; + + /* It's probably an old response, and we're out of sync. Just + gobble up the packet and ignore it. */ + getpkt (junkbuf, 0); + continue; /* Now, go look for + */ + } default: if (remote_debug) - printf ("%02X %c ", ch&0xFF, ch); + { + if (!started_error_output) + { + started_error_output = 1; + printf_unfiltered ("putpkt: Junk: "); + } + putc_unfiltered (ch & 0177); + } continue; } break; /* Here to retransmit */ } +#if 0 + /* This is wrong. If doing a long backtrace, the user should be + able to get out next time we call QUIT, without anything as violent + as interrupt_query. If we want to provide a way out of here + without getting to the next QUIT, it should be based on hitting + ^C twice as in remote_wait. */ if (quit_flag) { quit_flag = 0; interrupt_query (); } +#endif + } +} + +/* Come here after finding the start of the frame. Collect the rest into BUF, + verifying the checksum, length, and handling run-length compression. + Returns 0 on any error, 1 on success. */ + +static int +read_frame (buf) + char *buf; +{ + unsigned char csum; + char *bp; + int c; + + csum = 0; + bp = buf; + + while (1) + { + c = readchar (remote_timeout); + + switch (c) + { + case SERIAL_TIMEOUT: + if (remote_debug) + puts_filtered ("Timeout in mid-packet, retrying\n"); + return 0; + case '$': + if (remote_debug) + puts_filtered ("Saw new packet start in middle of old one\n"); + return 0; /* Start a new packet, count retries */ + case '#': + { + unsigned char pktcsum; + + *bp = '\000'; + + pktcsum = fromhex (readchar (remote_timeout)) << 4 + | fromhex (readchar (remote_timeout)); + + if (csum == pktcsum) + return 1; + + printf_filtered ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=", + pktcsum, csum); + puts_filtered (buf); + puts_filtered ("\n"); + + return 0; + } + case '*': /* Run length encoding */ + c = readchar (remote_timeout); + csum += c; + c = c - ' ' + 3; /* Compute repeat count */ + + if (bp + c - 1 < buf + PBUFSIZ - 1) + { + memset (bp, *(bp - 1), c); + bp += c; + continue; + } + + *bp = '\0'; + printf_filtered ("Repeat count %d too large for buffer: ", c); + puts_filtered (buf); + puts_filtered ("\n"); + + return 0; + default: + if (bp < buf + PBUFSIZ - 1) + { + *bp++ = c; + csum += c; + continue; + } + + *bp = '\0'; + puts_filtered ("Remote packet too long: "); + puts_filtered (buf); + puts_filtered ("\n"); + + return 0; + } } } @@ -1054,104 +1292,62 @@ getpkt (buf, forever) int forever; { char *bp; - unsigned char csum; - int c = 0; - unsigned char c1, c2; - int retries = 0; -#define MAX_RETRIES 10 + int c; + int tries; + int timeout; + int val; - while (1) + if (forever) + timeout = -1; + else + timeout = remote_timeout; + +#define MAX_TRIES 10 + + for (tries = 1; tries <= MAX_TRIES; tries++) { - if (quit_flag) - { - quit_flag = 0; - interrupt_query (); - } - /* This can loop forever if the remote side sends us characters continuously, but if it pauses, we'll get a zero from readchar because of timeout. Then we'll count that as a retry. */ - c = readchar(); - if (c > 0 && c != '$') - continue; + /* Note that we will only wait forever prior to the start of a packet. + After that, we expect characters to arrive at a brisk pace. They + should show up within remote_timeout intervals. */ - if (c == SERIAL_TIMEOUT) + do { - if (forever) - continue; - if (++retries >= MAX_RETRIES) - if (remote_debug) puts_filtered ("Timed out.\n"); - goto out; - } + c = readchar (timeout); - if (c == SERIAL_EOF) - error ("Remote connection closed"); - if (c == SERIAL_ERROR) - perror_with_name ("Remote communication error"); - - /* Force csum to be zero here because of possible error retry. */ - csum = 0; - bp = buf; - - while (1) - { - c = readchar (); if (c == SERIAL_TIMEOUT) { if (remote_debug) - puts_filtered ("Timeout in mid-packet, retrying\n"); - goto whole; /* Start a new packet, count retries */ - } - if (c == '$') - { - if (remote_debug) - puts_filtered ("Saw new packet start in middle of old one\n"); - goto whole; /* Start a new packet, count retries */ + puts_filtered ("Timed out.\n"); + goto retry; } - if (c == '#') - break; - if (bp >= buf+PBUFSIZ-1) - { - *bp = '\0'; - puts_filtered ("Remote packet too long: "); - puts_filtered (buf); - puts_filtered ("\n"); - goto whole; - } - *bp++ = c; - csum += c; } - *bp = 0; + while (c != '$'); - c1 = fromhex (readchar ()); - c2 = fromhex (readchar ()); - if ((csum & 0xff) == (c1 << 4) + c2) - break; - printf_filtered ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=", - (c1 << 4) + c2, csum & 0xff); - puts_filtered (buf); - puts_filtered ("\n"); + /* We've found the start of a packet, now collect the data. */ + + val = read_frame (buf); + + if (val == 1) + { + if (remote_debug) + fprintf_unfiltered (gdb_stderr, "Packet received: %s\n", buf); + SERIAL_WRITE (remote_desc, "+", 1); + return; + } /* Try the whole thing again. */ -whole: - if (++retries < MAX_RETRIES) - { - SERIAL_WRITE (remote_desc, "-", 1); - } - else - { - printf ("Ignoring packet error, continuing...\n"); - break; - } +retry: + SERIAL_WRITE (remote_desc, "-", 1); } -out: + /* We have tried hard enough, and just can't receive the packet. Give up. */ + printf_unfiltered ("Ignoring packet error, continuing...\n"); SERIAL_WRITE (remote_desc, "+", 1); - - if (remote_debug) - fprintf (stderr,"Packet received: %s\n", buf); } static void @@ -1263,10 +1459,12 @@ Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */ NULL, /* sections_end */ OPS_MAGIC /* to_magic */ }; +#endif /* Use remote. */ void _initialize_remote () { +#if !defined(DONT_USE_REMOTE) add_target (&remote_ops); -} #endif +} diff --git a/gnu/usr.bin/gdb/gdb/ser-unix.c b/gnu/usr.bin/gdb/gdb/ser-unix.c index b306e8ace5b2..237384b3b7cd 100644 --- a/gnu/usr.bin/gdb/gdb/ser-unix.c +++ b/gnu/usr.bin/gdb/gdb/ser-unix.c @@ -1,5 +1,5 @@ /* Serial interface for local (hardwired) serial ports on Un*x like systems - Copyright 1992, 1993 Free Software Foundation, Inc. + Copyright 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -150,6 +150,12 @@ set_tty_state(scb, state) #ifdef HAVE_SGTTY if (ioctl (scb->fd, TIOCSETN, &state->sgttyb) < 0) return -1; + if (ioctl (scb->fd, TIOCSETC, &state->tc) < 0) + return -1; + if (ioctl (scb->fd, TIOCSLTC, &state->ltc) < 0) + return -1; + if (ioctl (scb->fd, TIOCLSET, &state->lmode) < 0) + return -1; return 0; #endif @@ -192,23 +198,9 @@ hardwire_noflush_set_tty_state (scb, new_ttystate, old_ttystate) new_state = *(struct hardwire_ttystate *)new_ttystate; -#ifdef HAVE_TERMIOS - /* I'm not sure whether this is necessary; the manpage makes no mention - of discarding input when switching to/from ICANON. */ - if (state->termios.c_lflag & ICANON) - new_state.termios.c_lflag |= ICANON; - else - new_state.termios.c_lflag &= ~ICANON; -#endif - -#ifdef HAVE_TERMIO - /* I'm not sure whether this is necessary; the manpage makes no mention - of discarding input when switching to/from ICANON. */ - if (state->termio.c_lflag & ICANON) - new_state.termio.c_lflag |= ICANON; - else - new_state.termio.c_lflag &= ~ICANON; -#endif + /* Don't change in or out of raw mode; we don't want to flush input. + termio and termios have no such restriction; for them flushing input + is separate from setting the attributes. */ #ifdef HAVE_SGTTY if (state->sgttyb.sg_flags & RAW) @@ -354,14 +346,14 @@ hardwire_raw(scb) struct hardwire_ttystate state; if (get_tty_state(scb, &state)) - fprintf(stderr, "get_tty_state failed: %s\n", safe_strerror(errno)); + fprintf_unfiltered(gdb_stderr, "get_tty_state failed: %s\n", safe_strerror(errno)); #ifdef HAVE_TERMIOS state.termios.c_iflag = 0; state.termios.c_oflag = 0; state.termios.c_lflag = 0; state.termios.c_cflag &= ~(CSIZE|PARENB); - state.termios.c_cflag |= CS8; + state.termios.c_cflag |= CLOCAL | CS8; state.termios.c_cc[VMIN] = 0; state.termios.c_cc[VTIME] = 0; #endif @@ -371,7 +363,7 @@ hardwire_raw(scb) state.termio.c_oflag = 0; state.termio.c_lflag = 0; state.termio.c_cflag &= ~(CSIZE|PARENB); - state.termio.c_cflag |= CS8; + state.termio.c_cflag |= CLOCAL | CS8; state.termio.c_cc[VMIN] = 0; state.termio.c_cc[VTIME] = 0; #endif @@ -384,7 +376,7 @@ hardwire_raw(scb) scb->current_timeout = 0; if (set_tty_state (scb, &state)) - fprintf(stderr, "set_tty_state failed: %s\n", safe_strerror(errno)); + fprintf_unfiltered(gdb_stderr, "set_tty_state failed: %s\n", safe_strerror(errno)); } /* Wait for input on scb, with timeout seconds. Returns 0 on success, @@ -399,61 +391,105 @@ wait_for(scb, timeout) serial_t scb; int timeout; { + scb->timeout_remaining = 0; + #ifdef HAVE_SGTTY - struct timeval tv; - fd_set readfds; + { + struct timeval tv; + fd_set readfds; - FD_ZERO (&readfds); + FD_ZERO (&readfds); - tv.tv_sec = timeout; - tv.tv_usec = 0; + tv.tv_sec = timeout; + tv.tv_usec = 0; - FD_SET(scb->fd, &readfds); + FD_SET(scb->fd, &readfds); - while (1) - { - int numfds; + while (1) + { + int numfds; - if (timeout >= 0) - numfds = select(scb->fd+1, &readfds, 0, 0, &tv); - else - numfds = select(scb->fd+1, &readfds, 0, 0, 0); - - if (numfds <= 0) - if (numfds == 0) - return SERIAL_TIMEOUT; - else if (errno == EINTR) - continue; + if (timeout >= 0) + numfds = select(scb->fd+1, &readfds, 0, 0, &tv); else - return SERIAL_ERROR; /* Got an error from select or poll */ + numfds = select(scb->fd+1, &readfds, 0, 0, 0); - return 0; - } + if (numfds <= 0) + if (numfds == 0) + return SERIAL_TIMEOUT; + else if (errno == EINTR) + continue; + else + return SERIAL_ERROR; /* Got an error from select or poll */ + return 0; + } + } #endif /* HAVE_SGTTY */ #if defined HAVE_TERMIO || defined HAVE_TERMIOS if (timeout == scb->current_timeout) return 0; + scb->current_timeout = timeout; + { struct hardwire_ttystate state; if (get_tty_state(scb, &state)) - fprintf(stderr, "get_tty_state failed: %s\n", safe_strerror(errno)); + fprintf_unfiltered(gdb_stderr, "get_tty_state failed: %s\n", safe_strerror(errno)); #ifdef HAVE_TERMIOS - state.termios.c_cc[VTIME] = timeout * 10; + if (timeout < 0) + { + /* No timeout. */ + state.termios.c_cc[VTIME] = 0; + state.termios.c_cc[VMIN] = 1; + } + else + { + state.termios.c_cc[VMIN] = 0; + state.termios.c_cc[VTIME] = timeout * 10; + if (state.termios.c_cc[VTIME] != timeout * 10) + { + + /* If c_cc is an 8-bit signed character, we can't go + bigger than this. If it is always unsigned, we could use + 25. */ + + scb->current_timeout = 12; + state.termios.c_cc[VTIME] = scb->current_timeout * 10; + scb->timeout_remaining = timeout - scb->current_timeout; + } + } #endif #ifdef HAVE_TERMIO - state.termio.c_cc[VTIME] = timeout * 10; + if (timeout < 0) + { + /* No timeout. */ + state.termio.c_cc[VTIME] = 0; + state.termio.c_cc[VMIN] = 1; + } + else + { + state.termio.c_cc[VMIN] = 0; + state.termio.c_cc[VTIME] = timeout * 10; + if (state.termio.c_cc[VTIME] != timeout * 10) + { + /* If c_cc is an 8-bit signed character, we can't go + bigger than this. If it is always unsigned, we could use + 25. */ + + scb->current_timeout = 12; + state.termio.c_cc[VTIME] = scb->current_timeout * 10; + scb->timeout_remaining = timeout - scb->current_timeout; + } + } #endif - scb->current_timeout = timeout; - if (set_tty_state (scb, &state)) - fprintf(stderr, "set_tty_state failed: %s\n", safe_strerror(errno)); + fprintf_unfiltered(gdb_stderr, "set_tty_state failed: %s\n", safe_strerror(errno)); return 0; } @@ -475,24 +511,39 @@ hardwire_readchar(scb, timeout) if (scb->bufcnt-- > 0) return *scb->bufp++; - status = wait_for(scb, timeout); + while (1) + { + status = wait_for (scb, timeout); - if (status < 0) - return status; + if (status < 0) + return status; - scb->bufcnt = read(scb->fd, scb->buf, BUFSIZ); + scb->bufcnt = read (scb->fd, scb->buf, BUFSIZ); - if (scb->bufcnt <= 0) - if (scb->bufcnt == 0) - return SERIAL_TIMEOUT; /* 0 chars means timeout [may need to - distinguish between EOF & timeouts - someday] */ - else - return SERIAL_ERROR; /* Got an error from read */ + if (scb->bufcnt <= 0) + { + if (scb->bufcnt == 0) + { + /* Zero characters means timeout (it could also be EOF, but + we don't (yet at least) distinguish). */ + if (scb->timeout_remaining > 0) + { + timeout = scb->timeout_remaining; + continue; + } + else + return SERIAL_TIMEOUT; + } + else if (errno == EINTR) + continue; + else + return SERIAL_ERROR; /* Got an error from read */ + } - scb->bufcnt--; - scb->bufp = scb->buf; - return *scb->bufp++; + scb->bufcnt--; + scb->bufp = scb->buf; + return *scb->bufp++; + } } #ifndef B19200 diff --git a/gnu/usr.bin/gdb/gdb/serial.c b/gnu/usr.bin/gdb/gdb/serial.c index 6913fd6e2398..631f0f3441e3 100644 --- a/gnu/usr.bin/gdb/gdb/serial.c +++ b/gnu/usr.bin/gdb/gdb/serial.c @@ -52,13 +52,15 @@ serial_add_interface(optable) /* Open up a device or a network socket, depending upon the syntax of NAME. */ serial_t -serial_open(name) +serial_open (name) const char *name; { serial_t scb; struct serial_ops *ops; - if (strchr (name, ':')) + if (strcmp (name, "pc") == 0) + ops = serial_interface_lookup ("pc"); + else if (strchr (name, ':')) ops = serial_interface_lookup ("tcp"); else ops = serial_interface_lookup ("hardwire"); @@ -152,7 +154,7 @@ static void cleanup_tty(ttystate) serial_ttystate ttystate; { - printf ("\r\n[Exiting connect mode]\r\n"); + printf_unfiltered ("\r\n[Exiting connect mode]\r\n"); SERIAL_SET_TTY_STATE (tty_desc, ttystate); free (ttystate); SERIAL_CLOSE (tty_desc); @@ -171,9 +173,9 @@ connect_command (args, fromtty) dont_repeat(); if (args) - fprintf(stderr, "This command takes no args. They have been ignored.\n"); + fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n"); - printf("[Entering connect mode. Use ~. or ~^D to escape]\n"); + printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n"); tty_desc = SERIAL_FDOPEN (0); port_desc = last_serial_opened; @@ -250,12 +252,14 @@ connect_command (args, fromtty) } } } +#endif /* 0 */ void _initialize_serial () { +#if 0 add_com ("connect", class_obscure, connect_command, "Connect the terminal directly up to the command monitor.\n\ Use ~. or ~^D to break out."); -} #endif /* 0 */ +} diff --git a/gnu/usr.bin/gdb/gdb/serial.h b/gnu/usr.bin/gdb/gdb/serial.h index 7e7e53066864..9e669cbb2bb1 100644 --- a/gnu/usr.bin/gdb/gdb/serial.h +++ b/gnu/usr.bin/gdb/gdb/serial.h @@ -33,6 +33,9 @@ struct _serial_t unsigned char *bufp; /* Current byte */ unsigned char buf[BUFSIZ]; /* Da buffer itself */ int current_timeout; /* (termio{s} only), last value of VTIME */ + /* ser-unix.c termio{,s} only, we still need to wait for this many more + seconds. */ + int timeout_remaining; }; typedef struct _serial_t *serial_t; @@ -62,7 +65,7 @@ void serial_add_interface PARAMS ((struct serial_ops *optable)); serial_t serial_open PARAMS ((const char *name)); -serial_t serial_fdopen PARAMS ((int fd)); +serial_t serial_fdopen PARAMS ((const int fd)); /* For most routines, if a failure is indicated, then errno should be examined. */ @@ -102,7 +105,9 @@ serial_t serial_fdopen PARAMS ((int fd)); #define SERIAL_GET_TTY_STATE(SERIAL_T) (SERIAL_T)->ops->get_tty_state((SERIAL_T)) /* Set the state of the tty to TTYSTATE. The change is immediate. - When changing to or from raw mode, input might be discarded. */ + When changing to or from raw mode, input might be discarded. + Returns 0 for success, negative value for error (in which case errno + contains the error). */ #define SERIAL_SET_TTY_STATE(SERIAL_T, TTYSTATE) (SERIAL_T)->ops->set_tty_state((SERIAL_T), (TTYSTATE)) /* printf_filtered a user-comprehensible description of ttystate. */ diff --git a/gnu/usr.bin/gdb/gdb/source.c b/gnu/usr.bin/gdb/gdb/source.c index 88781d7cbc91..1f60821fae61 100644 --- a/gnu/usr.bin/gdb/gdb/source.c +++ b/gnu/usr.bin/gdb/gdb/source.c @@ -25,10 +25,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gdbcmd.h" #include "frame.h" -#ifdef USG #include -#endif - #include #include #include @@ -37,6 +34,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "regex.h" #include "symfile.h" #include "objfiles.h" +#include "annotate.h" + +#ifndef DIRNAME_SEPARATOR +#define DIRNAME_SEPARATOR ':' +#endif /* Prototypes for local functions. */ @@ -237,7 +239,10 @@ forget_cached_source_info () void init_source_path () { - source_path = savestring ("$cdir:$cwd", /* strlen of it */ 10); + char buf[20]; + + sprintf (buf, "$cdir%c$cwd", DIRNAME_SEPARATOR); + source_path = strsave (buf); forget_cached_source_info (); } @@ -288,7 +293,7 @@ mod_path (dirname, which_path) struct stat st; { - char *colon = strchr (name, ':'); + char *colon = strchr (name, DIRNAME_SEPARATOR); char *space = strchr (name, ' '); char *tab = strchr (name, '\t'); if (colon == 0 && space == 0 && tab == 0) @@ -303,7 +308,7 @@ mod_path (dirname, which_path) if (tab != 0 && (p == 0 || tab < p)) p = tab; dirname = p + 1; - while (*dirname == ':' || *dirname == ' ' || *dirname == '\t') + while (*dirname == DIRNAME_SEPARATOR || *dirname == ' ' || *dirname == '\t') ++dirname; } } @@ -363,7 +368,7 @@ mod_path (dirname, which_path) if (stat (name, &st) < 0) { int save_errno = errno; - fprintf (stderr, "Warning: "); + fprintf_unfiltered (gdb_stderr, "Warning: "); print_sys_errmsg (name, save_errno); } else if ((st.st_mode & S_IFMT) != S_IFDIR) @@ -378,7 +383,7 @@ mod_path (dirname, which_path) while (1) { if (!strncmp (p, name, len) - && (p[len] == '\0' || p[len] == ':')) + && (p[len] == '\0' || p[len] == DIRNAME_SEPARATOR)) { /* Found it in the search path, remove old copy */ if (p > *which_path) @@ -387,7 +392,7 @@ mod_path (dirname, which_path) goto skip_dup; /* Same dir twice in one cmd */ strcpy (p, &p[len+1]); /* Copy from next \0 or : */ } - p = strchr (p, ':'); + p = strchr (p, DIRNAME_SEPARATOR); if (p != 0) ++p; else @@ -395,6 +400,11 @@ mod_path (dirname, which_path) } if (p == 0) { + char tinybuf[2]; + + tinybuf[0] = DIRNAME_SEPARATOR; + tinybuf[1] = '\0'; + /* If we have already tacked on a name(s) in this command, be sure they stay on the front as we tack on some more. */ if (prefix) { @@ -402,7 +412,7 @@ mod_path (dirname, which_path) c = old[prefix]; old[prefix] = '\0'; - temp = concat (old, ":", name, NULL); + temp = concat (old, tinybuf, name, NULL); old[prefix] = c; *which_path = concat (temp, "", &old[prefix], NULL); prefix = strlen (temp); @@ -410,7 +420,7 @@ mod_path (dirname, which_path) } else { - *which_path = concat (name, (old[0]? ":" : old), old, NULL); + *which_path = concat (name, (old[0] ? tinybuf : old), old, NULL); prefix = strlen (name); } free (old); @@ -448,7 +458,7 @@ source_info (ignore, from_tty) -/* Open a file named STRING, searching path PATH (dir names sep by colons) +/* Open a file named STRING, searching path PATH (dir names sep by some char) using mode MODE and protection bits PROT in the calls to open. If TRY_CWD_FIRST, try to open ./STRING before searching PATH. @@ -503,7 +513,7 @@ openp (path, try_cwd_first, string, mode, prot, filename_opened) fd = -1; for (p = path; p; p = p1 ? p1 + 1 : 0) { - p1 = (char *) strchr (p, ':'); + p1 = (char *) strchr (p, DIRNAME_SEPARATOR); if (p1) len = p1 - p; else @@ -535,7 +545,7 @@ openp (path, try_cwd_first, string, mode, prot, filename_opened) strcat (filename+len, "/"); strcat (filename, string); - fd = open (filename, mode, prot); + fd = open (filename, mode); if (fd >= 0) break; } @@ -587,8 +597,8 @@ open_source_file (s) /* We cast strstr's result in case an ANSIhole has made it const, which produces a "required warning" when assigned to a nonconst. */ p = (char *)strstr (source_path, "$cdir"); - if (p && (p == path || p[-1] == ':') - && (p[cdir_len] == ':' || p[cdir_len] == '\0')) { + if (p && (p == path || p[-1] == DIRNAME_SEPARATOR) + && (p[cdir_len] == DIRNAME_SEPARATOR || p[cdir_len] == '\0')) { int len; path = (char *) @@ -606,12 +616,12 @@ open_source_file (s) /* Didn't work. Try using just the basename. */ p = basename (s->filename); if (p != s->filename) - result = openp(path, 0, p, O_RDONLY,0, &s->fullname); + result = openp (path, 0, p, O_RDONLY, 0, &s->fullname); } if (result >= 0) { - fullname = s -> fullname; - s -> fullname = mstrsave (s -> objfile -> md, s -> fullname); + fullname = s->fullname; + s->fullname = mstrsave (s->objfile->md, s->fullname); free (fullname); } return result; @@ -635,75 +645,80 @@ find_source_lines (s, desc) int *line_charpos; long exec_mtime; int size; -#ifdef LSEEK_NOT_LINEAR - char c; -#endif line_charpos = (int *) xmmalloc (s -> objfile -> md, lines_allocated * sizeof (int)); if (fstat (desc, &st) < 0) - perror_with_name (s->filename); + perror_with_name (s->filename); - if (exec_bfd) { - exec_mtime = bfd_get_mtime(exec_bfd); - if (exec_mtime && exec_mtime < st.st_mtime) - printf_filtered ("Source file is more recent than executable.\n"); - } + if (exec_bfd) + { + exec_mtime = bfd_get_mtime(exec_bfd); + if (exec_mtime && exec_mtime < st.st_mtime) + printf_filtered ("Source file is more recent than executable.\n"); + } #ifdef LSEEK_NOT_LINEAR - /* Have to read it byte by byte to find out where the chars live */ - - line_charpos[0] = tell(desc); - nlines = 1; - while (myread(desc, &c, 1)>0) - { - if (c == '\n') - { - if (nlines == lines_allocated) - { - lines_allocated *= 2; - line_charpos = - (int *) xmrealloc (s -> objfile -> md, (char *) line_charpos, - sizeof (int) * lines_allocated); - } - line_charpos[nlines++] = tell(desc); - } - } - -#else - /* st_size might be a large type, but we only support source files whose - size fits in an int. FIXME. */ - size = (int) st.st_size; - -#ifdef BROKEN_LARGE_ALLOCA - data = (char *) xmalloc (size); - make_cleanup (free, data); -#else - data = (char *) alloca (size); -#endif - if (myread (desc, data, size) < 0) - perror_with_name (s->filename); - end = data + size; - p = data; - line_charpos[0] = 0; - nlines = 1; - while (p != end) { - if (*p++ == '\n' - /* A newline at the end does not start a new line. */ - && p != end) - { - if (nlines == lines_allocated) + char c; + + /* Have to read it byte by byte to find out where the chars live */ + + line_charpos[0] = tell(desc); + nlines = 1; + while (myread(desc, &c, 1)>0) { - lines_allocated *= 2; - line_charpos = - (int *) xmrealloc (s -> objfile -> md, (char *) line_charpos, - sizeof (int) * lines_allocated); + if (c == '\n') + { + if (nlines == lines_allocated) + { + lines_allocated *= 2; + line_charpos = + (int *) xmrealloc (s -> objfile -> md, (char *) line_charpos, + sizeof (int) * lines_allocated); + } + line_charpos[nlines++] = tell(desc); + } } - line_charpos[nlines++] = p - data; - } } -#endif +#else /* lseek linear. */ + { + struct cleanup *old_cleanups; + + /* st_size might be a large type, but we only support source files whose + size fits in an int. */ + size = (int) st.st_size; + + /* Use malloc, not alloca, because this may be pretty large, and we may + run into various kinds of limits on stack size. */ + data = (char *) xmalloc (size); + old_cleanups = make_cleanup (free, data); + + if (myread (desc, data, size) < 0) + perror_with_name (s->filename); + end = data + size; + p = data; + line_charpos[0] = 0; + nlines = 1; + while (p != end) + { + if (*p++ == '\n' + /* A newline at the end does not start a new line. */ + && p != end) + { + if (nlines == lines_allocated) + { + lines_allocated *= 2; + line_charpos = + (int *) xmrealloc (s -> objfile -> md, (char *) line_charpos, + sizeof (int) * lines_allocated); + } + line_charpos[nlines++] = p - data; + } + } + do_cleanups (old_cleanups); + } +#endif /* lseek linear. */ s->nlines = nlines; s->line_charpos = (int *) xmrealloc (s -> objfile -> md, (char *) line_charpos, @@ -804,10 +819,9 @@ identify_source_line (s, line, mid_statement, pc) if (line > s->nlines) /* Don't index off the end of the line_charpos array. */ return 0; - printf ("\032\032%s:%d:%d:%s:0x%lx\n", s->fullname, - line, s->line_charpos[line - 1], - mid_statement ? "middle" : "beg", - (unsigned long) pc); + annotate_source (s->fullname, line, s->line_charpos[line - 1], + mid_statement, pc); + current_source_line = line; first_line_listed = line; last_line_listed = line; @@ -1025,20 +1039,23 @@ list_command (arg, from_tty) if (*arg == '*') { if (sal.symtab == 0) + /* FIXME-32x64--assumes sal.pc fits in long. */ error ("No source file for address %s.", local_hex_string((unsigned long) sal.pc)); sym = find_pc_function (sal.pc); if (sym) { - printf_filtered ("%s is in ", - local_hex_string((unsigned long) sal.pc)); - fputs_filtered (SYMBOL_SOURCE_NAME (sym), stdout); + print_address_numeric (sal.pc, 1, gdb_stdout); + printf_filtered (" is in "); + fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout); printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line); } else - printf_filtered ("%s is at %s:%d.\n", - local_hex_string((unsigned long) sal.pc), - sal.symtab->filename, sal.line); + { + print_address_numeric (sal.pc, 1, gdb_stdout); + printf_filtered (" is at %s:%d.\n", + sal.symtab->filename, sal.line); + } } /* If line was not specified by just a line number, @@ -1118,14 +1135,14 @@ line_info (arg, from_tty) address. */ printf_filtered (" for address "); wrap_here (" "); - print_address (sal.pc, stdout); + print_address (sal.pc, gdb_stdout); } else printf_filtered ("."); printf_filtered ("\n"); } else if (sal.line > 0 - && find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc)) + && find_line_pc_range (sal, &start_pc, &end_pc)) { if (start_pc == end_pc) { @@ -1133,7 +1150,7 @@ line_info (arg, from_tty) sal.line, sal.symtab->filename); wrap_here (" "); printf_filtered (" is at address "); - print_address (start_pc, stdout); + print_address (start_pc, gdb_stdout); wrap_here (" "); printf_filtered (" but contains no code.\n"); } @@ -1143,10 +1160,10 @@ line_info (arg, from_tty) sal.line, sal.symtab->filename); wrap_here (" "); printf_filtered (" starts at address "); - print_address (start_pc, stdout); + print_address (start_pc, gdb_stdout); wrap_here (" "); printf_filtered (" and ends at "); - print_address (end_pc, stdout); + print_address (end_pc, gdb_stdout); printf_filtered (".\n"); } @@ -1158,7 +1175,7 @@ line_info (arg, from_tty) /* If this is the only line, show the source code. If it could not find the file, don't do anything special. */ - if (frame_file_full_name && sals.nelts == 1) + if (annotation_level && sals.nelts == 1) identify_source_line (sal.symtab, sal.line, 0, start_pc); } else diff --git a/gnu/usr.bin/gdb/gdb/stabsread.c b/gnu/usr.bin/gdb/gdb/stabsread.c index e81c314b6def..144554063a7c 100644 --- a/gnu/usr.bin/gdb/gdb/stabsread.c +++ b/gnu/usr.bin/gdb/gdb/stabsread.c @@ -1,5 +1,5 @@ /* Support routines for decoding "stabs" debugging information format. - Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993 + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -25,6 +25,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Avoid placing any object file format specific code in this file. */ #include "defs.h" +#include #include "bfd.h" #include "obstack.h" #include "symtab.h" @@ -32,6 +33,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "symfile.h" #include "objfiles.h" #include "aout/stab_gnu.h" /* We always use GNU stabs, not native */ +#include "libaout.h" +#include "aout/aout64.h" +#include "gdb-stabs.h" #include "buildsym.h" #include "complaints.h" #include "demangle.h" @@ -54,7 +58,12 @@ struct field_info struct nextfield { struct nextfield *next; + + /* This is the raw visibility from the stab. It is not checked + for being one of the visibilities we recognize, so code which + examines this field better be able to deal. */ int visibility; + struct field field; } *list; struct next_fnfieldlist @@ -144,30 +153,6 @@ static const char vb_name[] = { '_','v','b',CPLUS_MARKER,'\0' }; #define BELIEVE_PCC_PROMOTION 0 #endif -#if 0 -/* I think this can go away, all current uses have been removed. - GCC emits a few crazy types which can only be distinguished by the - name (complex, long long on some machines), but I'd say fix GCC. */ - -/* During some calls to read_type (and thus to read_range_type), this - contains the name of the type being defined. Range types are only - used in C as basic types. We use the name to distinguish the otherwise - identical basic types "int" and "long" and their unsigned versions. - FIXME, this should disappear with better type management. */ - -static char *long_kludge_name; -#endif - -#if 0 -struct complaint dbx_class_complaint = -{ - "encountered DBX-style class variable debugging information.\n\ -You seem to have compiled your program with \ -\"g++ -g0\" instead of \"g++ -g\".\n\ -Therefore GDB will not know about your class variables", 0, 0 -}; -#endif - struct complaint invalid_cpp_abbrev_complaint = {"invalid C++ abbreviation `%s'", 0, 0}; @@ -213,10 +198,39 @@ static int undef_types_length; /* Check for and handle cretinous stabs symbol name continuation! */ #define STABS_CONTINUE(pp) \ do { \ - if (**(pp) == '\\') *(pp) = next_symbol_text (); \ + if (**(pp) == '\\' || (**(pp) == '?' && (*(pp))[1] == '\0')) \ + *(pp) = next_symbol_text (); \ } while (0) - +/* FIXME: These probably should be our own types (like rs6000_builtin_type + has its own types) rather than builtin_type_*. */ +static struct type **os9k_type_vector[] = { + 0, + &builtin_type_int, + &builtin_type_char, + &builtin_type_long, + &builtin_type_short, + &builtin_type_unsigned_char, + &builtin_type_unsigned_short, + &builtin_type_unsigned_long, + &builtin_type_unsigned_int, + &builtin_type_float, + &builtin_type_double, + &builtin_type_void, + &builtin_type_long_double +}; + +static void os9k_init_type_vector PARAMS ((struct type **)); + +static void +os9k_init_type_vector(tv) + struct type **tv; +{ + int i; + for (i=0; istab[ii]; pp = (char*) strchr (name, ':'); + while (pp[1] == ':') + { + pp += 2; + pp = (char *)strchr(pp, ':'); + } sym = find_symbol_in_list (symbols, name, pp-name); if (!sym) { + /* FIXME-maybe: it would be nice if we noticed whether + the variable was defined *anywhere*, not just whether + it is defined in this compilation unit. But neither + xlc or GCC seem to need such a definition, and until + we do psymtabs (so that the minimal symbols from all + compilation units are available now), I'm not sure + how to get the information. */ + /* On xcoff, if a global is defined and never referenced, ld will remove it from the executable. There is then a N_GSYM stab for it, but no regular (C_EXT) symbol. */ @@ -464,6 +495,10 @@ read_type_number (pp, typenums) static char *type_synonym_name; +#if !defined (REG_STRUCT_HAS_ADDR) +#define REG_STRUCT_HAS_ADDR(gcc_p,type) 0 +#endif + /* ARGSUSED */ struct symbol * define_symbol (valu, string, desc, type, objfile) @@ -494,6 +529,12 @@ define_symbol (valu, string, desc, type, objfile) if (p == 0) return 0; + while (p[1] == ':') + { + p += 2; + p = strchr(p, ':'); + } + /* If a nameless stab entry, all we need is the type, not the symbol. e.g. ":t10=*2" or a nameless enum like " :T16=ered:0,green:1,blue:2,;" */ nameless = (p == string || ((string[0] == ' ') && (string[1] == ':'))); @@ -502,6 +543,19 @@ define_symbol (valu, string, desc, type, objfile) obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol)); memset (sym, 0, sizeof (struct symbol)); + switch (type & N_TYPE) + { + case N_TEXT: + SYMBOL_SECTION(sym) = SECT_OFF_TEXT; + break; + case N_DATA: + SYMBOL_SECTION(sym) = SECT_OFF_DATA; + break; + case N_BSS: + SYMBOL_SECTION(sym) = SECT_OFF_BSS; + break; + } + if (processing_gcc_compilation) { /* GCC 2.x puts the line number in desc. SunOS apparently puts in the @@ -613,11 +667,13 @@ define_symbol (valu, string, desc, type, objfile) double d = atof (p); char *dbl_valu; + /* FIXME-if-picky-about-floating-accuracy: Should be using + target arithmetic to get the value. real.c in GCC + probably has the necessary code. */ + /* FIXME: lookup_fundamental_type is a hack. We should be creating a type especially for the type of float constants. - Problem is, what type should it be? We currently have to - read this in host floating point format, but what type - represents a host format "double"? + Problem is, what type should it be? Also, what should the name of this type be? Should we be using 'S' constants (see stabs.texinfo) instead? */ @@ -625,11 +681,9 @@ define_symbol (valu, string, desc, type, objfile) SYMBOL_TYPE (sym) = lookup_fundamental_type (objfile, FT_DBL_PREC_FLOAT); dbl_valu = (char *) - obstack_alloc (&objfile -> symbol_obstack, sizeof (double)); - memcpy (dbl_valu, &d, sizeof (double)); - /* Put it in target byte order, but it's still in host - floating point format. */ - SWAP_TARGET_AND_HOST (dbl_valu, sizeof (double)); + obstack_alloc (&objfile -> symbol_obstack, + TYPE_LENGTH (SYMBOL_TYPE (sym))); + store_floating (dbl_valu, TYPE_LENGTH (SYMBOL_TYPE (sym)), d); SYMBOL_VALUE_BYTES (sym) = dbl_valu; SYMBOL_CLASS (sym) = LOC_CONST_BYTES; } @@ -775,6 +829,7 @@ define_symbol (valu, string, desc, type, objfile) /* This case is faked by a conditional above, when there is no code letter in the dbx data. Dbx data never actually contains 'l'. */ + case 's': case 'l': SYMBOL_TYPE (sym) = read_type (&p, objfile); SYMBOL_CLASS (sym) = LOC_LOCAL; @@ -843,9 +898,7 @@ define_symbol (valu, string, desc, type, objfile) /* This macro is defined on machines (e.g. sparc) where we should believe the type of a PCC 'short' argument, but shouldn't believe the address (the address is - the address of the corresponding int). Note that - this is only different from the BELIEVE_PCC_PROMOTION - case on big-endian machines. + the address of the corresponding int). My guess is that this correction, as opposed to changing the parameter to an 'int' (as done below, for PCC @@ -855,7 +908,7 @@ define_symbol (valu, string, desc, type, objfile) the sparc problem doesn't come up because the calling function has to zero the top bytes (not knowing whether the called function wants an int or a short), so there - is no practical difference between an int and a short + is little practical difference between an int and a short (except perhaps what happens when the GDB user types "print short_arg = 0x10000;"). @@ -940,20 +993,40 @@ define_symbol (valu, string, desc, type, objfile) /* Sun cc uses a pair of symbols, one 'p' and one 'r' with the same name to represent an argument passed in a register. GCC uses 'P' for the same case. So if we find such a symbol pair - we combine it into one 'P' symbol. + we combine it into one 'P' symbol. For Sun cc we need to do this + regardless of REG_STRUCT_HAS_ADDR, because the compiler puts out + the 'p' symbol even if it never saves the argument onto the stack. + + On most machines, we want to preserve both symbols, so that + we can still get information about what is going on with the + stack (VAX for computing args_printed, using stack slots instead + of saved registers in backtraces, etc.). + Note that this code illegally combines - main(argc) int argc; { register int argc = 1; } + main(argc) struct foo argc; { register struct foo argc; } but this case is considered pathological and causes a warning from a decent compiler. */ + if (local_symbols - && local_symbols->nsyms > 0) + && local_symbols->nsyms > 0 +#ifndef USE_REGISTER_NOT_ARG + && REG_STRUCT_HAS_ADDR (processing_gcc_compilation, + SYMBOL_TYPE (sym)) + && (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT + || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION) +#endif + ) { struct symbol *prev_sym; prev_sym = local_symbols->symbol[local_symbols->nsyms - 1]; - if (SYMBOL_CLASS (prev_sym) == LOC_ARG + if ((SYMBOL_CLASS (prev_sym) == LOC_REF_ARG + || SYMBOL_CLASS (prev_sym) == LOC_ARG) && STREQ (SYMBOL_NAME (prev_sym), SYMBOL_NAME(sym))) { SYMBOL_CLASS (prev_sym) = LOC_REGPARM; + /* Use the type from the LOC_REGISTER; that is the type + that is actually in that register. */ + SYMBOL_TYPE (prev_sym) = SYMBOL_TYPE (sym); SYMBOL_VALUE (prev_sym) = SYMBOL_VALUE (sym); sym = prev_sym; break; @@ -975,17 +1048,6 @@ define_symbol (valu, string, desc, type, objfile) break; case 't': -#if 0 - /* See comment where long_kludge_name is declared. */ - /* Here we save the name of the symbol for read_range_type, which - ends up reading in the basic types. In stabs, unfortunately there - is no distinction between "int" and "long" types except their - names. Until we work out a saner type policy (eliminating most - builtin types and using the names specified in the files), we - save away the name so that far away from here in read_range_type, - we can examine it to decide between "int" and "long". FIXME. */ - long_kludge_name = SYMBOL_NAME (sym); -#endif SYMBOL_TYPE (sym) = read_type (&p, objfile); /* For a nameless type, we don't want a create a symbol, thus we @@ -1013,7 +1075,13 @@ define_symbol (valu, string, desc, type, objfile) if (TYPE_NAME (SYMBOL_TYPE (sym)) == NULL) { - if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR + /* gcc-2.6 or later (when using -fvtable-thunks) + emits a unique named type for a vtable entry. + Some gdb code depends on that specific name. */ + extern const char vtbl_ptr_name[]; + + if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR + && strcmp (SYMBOL_NAME (sym), vtbl_ptr_name)) || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FUNC) { /* If we are giving a name to a type such as "pointer to @@ -1054,6 +1122,17 @@ define_symbol (valu, string, desc, type, objfile) strlen (SYMBOL_NAME (sym)), &objfile -> symbol_obstack); } + /* The semantics of C++ state that "struct foo { ... }" also defines + a typedef for "foo". Unfortunately, cfront never makes the typedef + when translating C++ into C. We make the typedef here so that + "ptype foo" works as expected for cfront translated code. */ + else if (current_subfile->language == language_cplus) + { + synonym = 1; + type_synonym_name = obsavestring (SYMBOL_NAME (sym), + strlen (SYMBOL_NAME (sym)), + &objfile -> symbol_obstack); + } SYMBOL_TYPE (sym) = read_type (&p, objfile); @@ -1091,7 +1170,10 @@ define_symbol (valu, string, desc, type, objfile) SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_VALUE_ADDRESS (sym) = valu; SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &local_symbols); + if (os9k_stabs) + add_symbol_to_list (sym, &global_symbols); + else + add_symbol_to_list (sym, &local_symbols); break; case 'v': @@ -1130,16 +1212,22 @@ define_symbol (valu, string, desc, type, objfile) If REG_STRUCT_HAS_ADDR yields non-zero we have to convert LOC_REGPARM to LOC_REGPARM_ADDR for structures and unions. */ -#if !defined (REG_STRUCT_HAS_ADDR) -#define REG_STRUCT_HAS_ADDR(gcc_p) 0 -#endif - if (SYMBOL_CLASS (sym) == LOC_REGPARM - && REG_STRUCT_HAS_ADDR (processing_gcc_compilation) - && ( (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT) + && REG_STRUCT_HAS_ADDR (processing_gcc_compilation, + SYMBOL_TYPE (sym)) + && ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT) || (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION))) SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR; + /* Likewise for converting LOC_ARG to LOC_REF_ARG (for the 7th and + subsequent arguments on the sparc, for example). */ + if (SYMBOL_CLASS (sym) == LOC_ARG + && REG_STRUCT_HAS_ADDR (processing_gcc_compilation, + SYMBOL_TYPE (sym)) + && ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT) + || (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION))) + SYMBOL_CLASS (sym) = LOC_REF_ARG; + return sym; } @@ -1187,7 +1275,7 @@ error_type (pp) } /* Check for and handle cretinous dbx symbol name continuation! */ - if ((*pp)[-1] == '\\') + if ((*pp)[-1] == '\\' || (*pp)[-1] == '?') { *pp = next_symbol_text (); } @@ -1221,6 +1309,9 @@ read_type (pp, objfile) there is no size attribute. */ int type_size = -1; + /* Used to distinguish string and bitstring from char-array and set. */ + int is_string = 0; + /* Read type number if present. The type number may be omitted. for instance in a two-dimensional array declared with type "ar1;1;10;ar1;1;10;4". */ @@ -1270,6 +1361,11 @@ read_type (pp, objfile) if (type_size <= 0) type_size = -1; break; + + case 'S': + is_string = 1; + break; + default: /* Ignore unrecognized type attributes, so future compilers can invent new ones. */ @@ -1303,7 +1399,7 @@ read_type (pp, objfile) char *type_name; { - char *from, *to; + char *from, *to, *p, *q1, *q2; /* Set the type code according to the following letter. */ switch ((*pp)[0]) @@ -1318,30 +1414,51 @@ read_type (pp, objfile) code = TYPE_CODE_ENUM; break; default: - return error_type (pp); + { + /* Complain and keep going, so compilers can invent new + cross-reference types. */ + static struct complaint msg = + {"Unrecognized cross-reference type `%c'", 0, 0}; + complain (&msg, (*pp)[0]); + code = TYPE_CODE_STRUCT; + break; + } } - - to = type_name = (char *) - obstack_alloc (&objfile -> type_obstack, - (((char *) strchr (*pp, ':') - (*pp)) + 1)); + + q1 = strchr(*pp, '<'); + p = strchr(*pp, ':'); + if (p == NULL) + return error_type (pp); + while (q1 && p > q1 && p[1] == ':') + { + q2 = strchr(q1, '>'); + if (!q2 || q2 < p) + break; + p += 2; + p = strchr(p, ':'); + if (p == NULL) + return error_type (pp); + } + to = type_name = + (char *)obstack_alloc (&objfile->type_obstack, p - *pp + 1); /* Copy the name. */ from = *pp + 1; - while ((*to++ = *from++) != ':') - ; - *--to = '\0'; + while (from < p) + *to++ = *from++; + *to = '\0'; - /* Set the pointer ahead of the name which we just read. */ - *pp = from; + /* Set the pointer ahead of the name which we just read, and + the colon. */ + *pp = from + 1; } - /* Now check to see whether the type has already been declared. */ - /* This is necessary at least in the case where the - program says something like - struct foo bar[5]; - The compiler puts out a cross-reference; we better find - set the length of the structure correctly so we can - set the length of the array. */ + /* Now check to see whether the type has already been + declared. This was written for arrays of cross-referenced + types before we had TYPE_CODE_TARGET_STUBBED, so I'm pretty + sure it is not necessary anymore. But it might be a good + idea, to save a little memory. */ + for (ppt = file_symbols; ppt; ppt = ppt->next) for (i = 0; i < ppt->nsyms; i++) { @@ -1357,7 +1474,7 @@ read_type (pp, objfile) return type; } } - + /* Didn't find the type to which this refers, so we must be dealing with a forward reference. Allocate a type structure for it, and keep track of it so we can @@ -1386,41 +1503,49 @@ read_type (pp, objfile) case '9': case '(': - (*pp)--; - if (read_type_number (pp, xtypenums) != 0) - return error_type (pp); + { + char *pp_saved; - if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1]) - /* It's being defined as itself. That means it is "void". */ - type = init_type (TYPE_CODE_VOID, 0, 0, NULL, objfile); - else - { - struct type *xtype = *dbx_lookup_type (xtypenums); + (*pp)--; + pp_saved = *pp; - /* This can happen if we had '-' followed by a garbage character, - for example. */ - if (xtype == NULL) - return error_type (pp); + /* Peek ahead at the number to detect void. */ + if (read_type_number (pp, xtypenums) != 0) + return error_type (pp); - /* The type is being defined to another type. So we copy the type. - This loses if we copy a C++ class and so we lose track of how - the names are mangled (but g++ doesn't output stabs like this - now anyway). */ + if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1]) + /* It's being defined as itself. That means it is "void". */ + type = init_type (TYPE_CODE_VOID, 1, 0, NULL, objfile); + else + { + struct type *xtype; - type = alloc_type (objfile); - memcpy (type, xtype, sizeof (struct type)); + /* Go back to the number and have read_type get it. This means + that we can deal with something like t(1,2)=(3,4)=... which + the Lucid compiler uses. */ + *pp = pp_saved; + xtype = read_type (pp, objfile); - /* The idea behind clearing the names is that the only purpose - for defining a type to another type is so that the name of - one can be different. So we probably don't need to worry much - about the case where the compiler doesn't give a name to the - new type. */ - TYPE_NAME (type) = NULL; - TYPE_TAG_NAME (type) = NULL; - } - if (typenums[0] != -1) - *dbx_lookup_type (typenums) = type; - break; + /* The type is being defined to another type. So we copy the type. + This loses if we copy a C++ class and so we lose track of how + the names are mangled (but g++ doesn't output stabs like this + now anyway). */ + + type = alloc_type (objfile); + memcpy (type, xtype, sizeof (struct type)); + + /* The idea behind clearing the names is that the only purpose + for defining a type to another type is so that the name of + one can be different. So we probably don't need to worry much + about the case where the compiler doesn't give a name to the + new type. */ + TYPE_NAME (type) = NULL; + TYPE_TAG_NAME (type) = NULL; + } + if (typenums[0] != -1) + *dbx_lookup_type (typenums) = type; + break; + } /* In the following types, we must be sure to overwrite any existing type that the typenums refer to, rather than allocating a new one @@ -1440,16 +1565,40 @@ read_type (pp, objfile) break; case 'f': /* Function returning another type */ + if (os9k_stabs && **pp == '(') + { + /* Function prototype; parse it. + We must conditionalize this on os9k_stabs because otherwise + it could be confused with a Sun-style (1,3) typenumber + (I think). */ + struct type *t; + ++*pp; + while (**pp != ')') + { + t = read_type(pp, objfile); + if (**pp == ',') ++*pp; + } + } type1 = read_type (pp, objfile); type = make_function_type (type1, dbx_lookup_type (typenums)); break; - case 'k': /* Const qualifier on some type (Sun) */ + case 'k': /* Const qualifier on some type (Sun) */ + case 'c': /* Const qualifier on some type (OS9000) */ + /* Because 'c' means other things to AIX and 'k' is perfectly good, + only accept 'c' in the os9k_stabs case. */ + if (type_descriptor == 'c' && !os9k_stabs) + return error_type (pp); type = read_type (pp, objfile); /* FIXME! For now, we ignore const and volatile qualifiers. */ break; - case 'B': /* Volatile qual on some type (Sun) */ + case 'B': /* Volatile qual on some type (Sun) */ + case 'i': /* Volatile qual on some type (OS9000) */ + /* Because 'i' means other things to AIX and 'B' is perfectly good, + only accept 'i' in the os9k_stabs case. */ + if (type_descriptor == 'i' && !os9k_stabs) + return error_type (pp); type = read_type (pp, objfile); /* FIXME! For now, we ignore const and volatile qualifiers. */ break; @@ -1510,10 +1659,17 @@ read_type (pp, objfile) *dbx_lookup_type (typenums) = type; break; - case 'b': /* Sun ACC builtin int type */ - type = read_sun_builtin_type (pp, typenums, objfile); - if (typenums[0] != -1) - *dbx_lookup_type (typenums) = type; + case 'b': + if (os9k_stabs) + /* Const and volatile qualified type. */ + type = read_type (pp, objfile); + else + { + /* Sun ACC builtin int type */ + type = read_sun_builtin_type (pp, typenums, objfile); + if (typenums[0] != -1) + *dbx_lookup_type (typenums) = type; + } break; case 'R': /* Sun ACC builtin float type */ @@ -1556,6 +1712,17 @@ read_type (pp, objfile) type = dbx_alloc_type (typenums, objfile); type = read_array_type (pp, type, objfile); + if (is_string) + TYPE_CODE (type) = TYPE_CODE_STRING; + break; + + case 'S': + type1 = read_type (pp, objfile); + type = create_set_type ((struct type*) NULL, type1); + if (is_string) + TYPE_CODE (type) = TYPE_CODE_BITSTRING; + if (typenums[0] != -1) + *dbx_lookup_type (typenums) = type; break; default: @@ -1648,7 +1815,7 @@ rs6000_builtin_type (typenum) "unsigned long", NULL); break; case 11: - rettype = init_type (TYPE_CODE_VOID, 0, 0, "void", NULL); + rettype = init_type (TYPE_CODE_VOID, 1, 0, "void", NULL); break; case 12: /* IEEE single precision (32 bit). */ @@ -1729,6 +1896,7 @@ rs6000_builtin_type (typenum) #define VISIBILITY_PRIVATE '0' /* Stabs character for private field */ #define VISIBILITY_PROTECTED '1' /* Stabs character for protected fld */ #define VISIBILITY_PUBLIC '2' /* Stabs character for public field */ +#define VISIBILITY_IGNORE '9' /* Optimized out or zero length */ /* Read member function stabs info for C++ classes. The form of each member function data is: @@ -2137,36 +2305,19 @@ read_one_struct_field (fip, pp, p, type, objfile) fip -> list -> field.name = obsavestring (*pp, p - *pp, &objfile -> type_obstack); *pp = p + 1; - + /* This means we have a visibility for a field coming. */ if (**pp == '/') { (*pp)++; fip -> list -> visibility = *(*pp)++; - switch (fip -> list -> visibility) - { - case VISIBILITY_PRIVATE: - case VISIBILITY_PROTECTED: - break; - - case VISIBILITY_PUBLIC: - /* Nothing to do */ - break; - - default: - /* Unknown visibility specifier. */ - complain (&stabs_general_complaint, - "unknown visibility specifier"); - return; - break; - } } else { /* normal dbx-style format, no explicit visibility */ fip -> list -> visibility = VISIBILITY_PUBLIC; } - + fip -> list -> field.type = read_type (pp, objfile); if (**pp == ':') { @@ -2216,41 +2367,33 @@ read_one_struct_field (fip, pp, p, type, objfile) return; } } -#if 0 - /* FIXME-tiemann: Can't the compiler put out something which - lets us distinguish these? (or maybe just not put out anything - for the field). What is the story here? What does the compiler - really do? Also, patch gdb.texinfo for this case; I document - it as a possible problem there. Search for "DBX-style". */ - - /* This is wrong because this is identical to the symbols - produced for GCC 0-size arrays. For example: - typedef union { - int num; - char str[0]; - } foo; - The code which dumped core in such circumstances should be - fixed not to dump core. */ - - /* g++ -g0 can put out bitpos & bitsize zero for a static - field. This does not give us any way of getting its - class, so we can't know its name. But we can just - ignore the field so we don't dump core and other nasty - stuff. */ + if (fip -> list -> field.bitpos == 0 && fip -> list -> field.bitsize == 0) { - complain (&dbx_class_complaint); + /* This can happen in two cases: (1) at least for gcc 2.4.5 or so, + it is a field which has been optimized out. The correct stab for + this case is to use VISIBILITY_IGNORE, but that is a recent + invention. (2) It is a 0-size array. For example + union { int num; char str[0]; } foo. Printing "" for + str in "p foo" is OK, since foo.str (and thus foo.str[3]) + will continue to work, and a 0-size array as a whole doesn't + have any contents to print. + + I suspect this probably could also happen with gcc -gstabs (not + -gstabs+) for static fields, and perhaps other C++ extensions. + Hopefully few people use -gstabs with gdb, since it is intended + for dbx compatibility. */ + /* Ignore this field. */ - fip -> list = fip -> list -> next; + fip -> list-> visibility = VISIBILITY_IGNORE; } else -#endif /* 0 */ { /* Detect an unpacked field and mark it as such. dbx gives a bit size for all fields. Note that forward refs cannot be packed, and treat enums as if they had the width of ints. */ - + if (TYPE_CODE (fip -> list -> field.type) != TYPE_CODE_INT && TYPE_CODE (fip -> list -> field.type) != TYPE_CODE_ENUM) { @@ -2286,11 +2429,12 @@ read_one_struct_field (fip, pp, p, type, objfile) '/0' (VISIBILITY_PRIVATE) '/1' (VISIBILITY_PROTECTED) '/2' (VISIBILITY_PUBLIC) + '/9' (VISIBILITY_IGNORE) or nothing, for C style fields with public visibility. Returns 1 for success, 0 for failure. */ - + static int read_struct_fields (fip, pp, type, objfile) struct field_info *fip; @@ -2311,6 +2455,7 @@ read_struct_fields (fip, pp, type, objfile) while (**pp != ';') { + if (os9k_stabs && **pp == ',') break; STABS_CONTINUE (pp); /* Get space to record the next field's data. */ new = (struct nextfield *) xmalloc (sizeof (struct nextfield)); @@ -2321,11 +2466,16 @@ read_struct_fields (fip, pp, type, objfile) /* Get the field name. */ p = *pp; - /* If is starts with CPLUS_MARKER it is a special abbreviation, unless - the CPLUS_MARKER is followed by an underscore, in which case it is - just the name of an anonymous type, which we should handle like any - other type name. */ - if (*p == CPLUS_MARKER && p[1] != '_') + + /* If is starts with CPLUS_MARKER it is a special abbreviation, + unless the CPLUS_MARKER is followed by an underscore, in + which case it is just the name of an anonymous type, which we + should handle like any other type name. We accept either '$' + or '.', because a field name can never contain one of these + characters except as a CPLUS_MARKER (we probably should be + doing that in most parts of GDB). */ + + if ((*p == '$' || *p == '.') && p[1] != '_') { if (!read_cpp_abbrev (fip, pp, type, objfile)) return 0; @@ -2351,7 +2501,7 @@ read_struct_fields (fip, pp, type, objfile) } read_one_struct_field (fip, pp, p, type, objfile); } - if (p[1] == ':') + if (p[0] == ':' && p[1] == ':') { /* chill the list of fields: the last entry (at the head) is a partially constructed entry which we now scrub. */ @@ -2439,7 +2589,7 @@ read_baseclasses (fip, pp, type, objfile) new -> field.bitsize = 0; /* this should be an unpacked field! */ STABS_CONTINUE (pp); - switch (*(*pp)++) + switch (**pp) { case '0': /* Nothing to do. */ @@ -2448,9 +2598,14 @@ read_baseclasses (fip, pp, type, objfile) SET_TYPE_FIELD_VIRTUAL (type, i); break; default: - /* Bad visibility format. */ - return 0; + /* Unknown character. Complain and treat it as non-virtual. */ + { + static struct complaint msg = { + "Unknown virtual character `%c' for baseclass", 0, 0}; + complain (&msg, **pp); + } } + ++(*pp); new -> visibility = *(*pp)++; switch (new -> visibility) @@ -2460,8 +2615,14 @@ read_baseclasses (fip, pp, type, objfile) case VISIBILITY_PUBLIC: break; default: - /* Bad visibility format. */ - return 0; + /* Bad visibility format. Complain and treat it as + public. */ + { + static struct complaint msg = { + "Unknown visibility `%c' for baseclass", 0, 0}; + complain (&msg, new -> visibility); + new -> visibility = VISIBILITY_PUBLIC; + } } { @@ -2658,6 +2819,10 @@ attach_fields_to_type (fip, type, objfile) TYPE_FIELD_PROTECTED_BITS (type) = (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields); + + TYPE_FIELD_IGNORE_BITS (type) = + (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); + B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields); } /* Copy the saved-up fields into the field vector. Start from the head @@ -2677,11 +2842,20 @@ attach_fields_to_type (fip, type, objfile) SET_TYPE_FIELD_PROTECTED (type, nfields); break; + case VISIBILITY_IGNORE: + SET_TYPE_FIELD_IGNORE (type, nfields); + break; + case VISIBILITY_PUBLIC: break; default: - /* Should warn about this unknown visibility? */ + /* Unknown visibility. Complain and treat it as public. */ + { + static struct complaint msg = { + "Unknown visibility `%c' for field", 0, 0}; + complain (&msg, fip -> list -> visibility); + } break; } fip -> list = fip -> list -> next; @@ -2766,28 +2940,33 @@ read_array_type (pp, type, objfile) int nbits; /* Format of an array type: - "ar;lower;upper;". Put code in - to handle this. + "ar;lower;upper;". + OS9000: "arlower,upper;". Fortran adjustable arrays use Adigits or Tdigits for lower or upper; for these, produce a type like float[][]. */ - index_type = read_type (pp, objfile); - if (**pp != ';') - /* Improper format of array type decl. */ - return error_type (pp); - ++*pp; + if (os9k_stabs) + index_type = builtin_type_int; + else + { + index_type = read_type (pp, objfile); + if (**pp != ';') + /* Improper format of array type decl. */ + return error_type (pp); + ++*pp; + } - if (!(**pp >= '0' && **pp <= '9')) + if (!(**pp >= '0' && **pp <= '9') && **pp != '-') { (*pp)++; adjustable = 1; } - lower = read_huge_number (pp, ';', &nbits); + lower = read_huge_number (pp, os9k_stabs ? ',' : ';', &nbits); if (nbits != 0) return error_type (pp); - if (!(**pp >= '0' && **pp <= '9')) + if (!(**pp >= '0' && **pp <= '9') && **pp != '-') { (*pp)++; adjustable = 1; @@ -2810,9 +2989,14 @@ read_array_type (pp, type, objfile) /* If we have an array whose element type is not yet known, but whose bounds *are* known, record it to be adjusted at the end of the file. */ + /* FIXME: Why check for zero length rather than TYPE_FLAG_STUB? I think + the two have the same effect except that the latter is cleaner and the + former would be wrong for types which really are zero-length (if we + have any). */ if (TYPE_LENGTH (element_type) == 0 && !adjustable) { + TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB; add_undefined_type (type); } @@ -2838,6 +3022,7 @@ read_enum_type (pp, type, objfile) struct pending **symlist; struct pending *osyms, *syms; int o_nsyms; + int nbits; #if 0 /* FIXME! The stabs produced by Sun CC merrily define things that ought @@ -2851,12 +3036,21 @@ read_enum_type (pp, type, objfile) osyms = *symlist; o_nsyms = osyms ? osyms->nsyms : 0; + if (os9k_stabs) + { + /* Size. Perhaps this does not have to be conditionalized on + os9k_stabs (assuming the name of an enum constant can't start + with a digit). */ + read_huge_number (pp, 0, &nbits); + if (nbits != 0) + return error_type (pp); + } + /* Read the value-names and their values. The input syntax is NAME:VALUE,NAME:VALUE, and so on. A semicolon or comma instead of a NAME means the end. */ while (**pp && **pp != ';' && **pp != ',') { - int nbits; STABS_CONTINUE (pp); p = *pp; while (*p != ':') p++; @@ -2883,7 +3077,7 @@ read_enum_type (pp, type, objfile) /* Now fill in the fields of the type-structure. */ - TYPE_LENGTH (type) = sizeof (int); + TYPE_LENGTH (type) = TARGET_INT_BIT / HOST_CHAR_BIT; TYPE_CODE (type) = TYPE_CODE_ENUM; TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB; TYPE_NFIELDS (type) = nsyms; @@ -2917,17 +3111,6 @@ read_enum_type (pp, type, objfile) break; } -#if 0 - /* This screws up perfectly good C programs with enums. FIXME. */ - /* Is this Modula-2's BOOLEAN type? Flag it as such if so. */ - if(TYPE_NFIELDS(type) == 2 && - ((STREQ(TYPE_FIELD_NAME(type,0),"TRUE") && - STREQ(TYPE_FIELD_NAME(type,1),"FALSE")) || - (STREQ(TYPE_FIELD_NAME(type,1),"TRUE") && - STREQ(TYPE_FIELD_NAME(type,0),"FALSE")))) - TYPE_CODE(type) = TYPE_CODE_BOOL; -#endif - return type; } @@ -2991,56 +3174,24 @@ read_sun_builtin_type (pp, typenums, objfile) type_bits = read_huge_number (pp, 0, &nbits); if (nbits != 0) return error_type (pp); + /* The type *should* end with a semicolon. If it are embedded + in a larger type the semicolon may be the only way to know where + the type ends. If this type is at the end of the stabstring we + can deal with the omitted semicolon (but we don't have to like + it). Don't bother to complain(), Sun's compiler omits the semicolon + for "void". */ + if (**pp == ';') + ++(*pp); -#if 0 - /* FIXME. Here we should just be able to make a type of the right - number of bits and signedness. FIXME. */ - - if (type_bits == TARGET_LONG_LONG_BIT) - return (lookup_fundamental_type (objfile, - signed_type? FT_LONG_LONG: FT_UNSIGNED_LONG_LONG)); - - if (type_bits == TARGET_INT_BIT) - { - /* FIXME -- the only way to distinguish `int' from `long' - is to look at its name! */ - if (signed_type) - { - if (long_kludge_name && long_kludge_name[0] == 'l' /* long */) - return lookup_fundamental_type (objfile, FT_LONG); - else - return lookup_fundamental_type (objfile, FT_INTEGER); - } - else - { - if (long_kludge_name - && ((long_kludge_name[0] == 'u' /* unsigned */ && - long_kludge_name[9] == 'l' /* long */) - || (long_kludge_name[0] == 'l' /* long unsigned */))) - return lookup_fundamental_type (objfile, FT_UNSIGNED_LONG); - else - return lookup_fundamental_type (objfile, FT_UNSIGNED_INTEGER); - } - } - - if (type_bits == TARGET_SHORT_BIT) - return (lookup_fundamental_type (objfile, - signed_type? FT_SHORT: FT_UNSIGNED_SHORT)); - - if (type_bits == TARGET_CHAR_BIT) - return (lookup_fundamental_type (objfile, - signed_type? FT_CHAR: FT_UNSIGNED_CHAR)); - if (type_bits == 0) - return lookup_fundamental_type (objfile, FT_VOID); - - return error_type (pp); -#else - return init_type (type_bits == 0 ? TYPE_CODE_VOID : TYPE_CODE_INT, - type_bits / TARGET_CHAR_BIT, - signed_type ? 0 : TYPE_FLAG_UNSIGNED, (char *)NULL, - objfile); -#endif + return init_type (TYPE_CODE_VOID, 1, + signed_type ? 0 : TYPE_FLAG_UNSIGNED, (char *)NULL, + objfile); + else + return init_type (TYPE_CODE_INT, + type_bits / TARGET_CHAR_BIT, + signed_type ? 0 : TYPE_FLAG_UNSIGNED, (char *)NULL, + objfile); } static struct type * @@ -3114,7 +3265,11 @@ read_huge_number (pp, end, bits) p++; } - upper_limit = LONG_MAX / radix; + if (os9k_stabs) + upper_limit = ULONG_MAX / radix; + else + upper_limit = LONG_MAX / radix; + while ((c = *p++) >= '0' && c < ('0' + radix)) { if (n <= upper_limit) @@ -3258,7 +3413,7 @@ read_range_type (pp, typenums, objfile) /* A type defined as a subrange of itself, with bounds both 0, is void. */ if (self_subrange && n2 == 0 && n3 == 0) - return init_type (TYPE_CODE_VOID, 0, 0, NULL, objfile); + return init_type (TYPE_CODE_VOID, 1, 0, NULL, objfile); /* If n3 is zero and n2 is not, we want a floating type, and n2 is the width in bytes. @@ -3482,7 +3637,7 @@ common_block_end (objfile) for (j = common_block_i; j < common_block->nsyms; j++) add_symbol_to_list (common_block->symbol[j], &new); - SYMBOL_NAMESPACE (sym) = (enum namespace)((long) new); + SYMBOL_TYPE (sym) = (struct type *) new; /* Should we be putting local_symbols back to what it was? Does it matter? */ @@ -3502,7 +3657,7 @@ fix_common_block (sym, valu) struct symbol *sym; int valu; { - struct pending *next = (struct pending *) SYMBOL_NAMESPACE (sym); + struct pending *next = (struct pending *) SYMBOL_TYPE (sym); for ( ; next; next = next->next) { register int j; @@ -3555,7 +3710,10 @@ cleanup_undefined_types () case TYPE_CODE_UNION: case TYPE_CODE_ENUM: { - /* Check if it has been defined since. */ + /* Check if it has been defined since. Need to do this here + as well as in check_stub_type to deal with the (legitimate in + C though not C++) case of several types with the same name + in different source files. */ if (TYPE_FLAGS (*type) & TYPE_FLAG_STUB) { struct pending *ppt; @@ -3590,8 +3748,20 @@ cleanup_undefined_types () } break; - case TYPE_CODE_ARRAY: + case TYPE_CODE_ARRAY: { + /* This is a kludge which is here for historical reasons + because I suspect that check_stub_type does not get + called everywhere it needs to be called for arrays. Even + with this kludge, those places are broken for the case + where the stub type is defined in another compilation + unit, but this kludge at least deals with it for the case + in which it is the same compilation unit. + + Don't try to do this by calling check_stub_type; it might + cause symbols to be read in lookup_symbol, and the symbol + reader is not reentrant. */ + struct type *range_type; int lower, upper; @@ -3609,6 +3779,9 @@ cleanup_undefined_types () upper = TYPE_FIELD_BITPOS (range_type, 1); TYPE_LENGTH (*type) = (upper - lower + 1) * TYPE_LENGTH (TYPE_TARGET_TYPE (*type)); + + /* If the target type is not a stub, we could be clearing + TYPE_FLAG_TARGET_STUB for *type. */ } break; @@ -3622,6 +3795,7 @@ GDB internal error. cleanup_undefined_types with bad type %d.", 0, 0}; break; } } + undef_types_length = 0; } @@ -3679,6 +3853,8 @@ scan_file_globals (objfile) { SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msymbol); } + + SYMBOL_SECTION (sym) = SYMBOL_SECTION (msymbol); if (prev) { @@ -3731,6 +3907,8 @@ void start_stabs () /* FIXME: If common_block_name is not already NULL, we should complain(). */ common_block_name = NULL; + + os9k_stabs = 0; } /* Call after end_symtab() */ diff --git a/gnu/usr.bin/gdb/gdb/stabsread.h b/gnu/usr.bin/gdb/gdb/stabsread.h index 3b890d805840..a5a0de71b497 100644 --- a/gnu/usr.bin/gdb/gdb/stabsread.h +++ b/gnu/usr.bin/gdb/gdb/stabsread.h @@ -40,7 +40,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ have the correct data for that slot yet. The use of the LOC_BLOCK code in this chain is nonstandard-- - it refers to a FORTRAN common block rather than the usual meaning. */ + it refers to a FORTRAN common block rather than the usual meaning, and + the such LOC_BLOCK symbols use their fields in nonstandard ways. */ EXTERN struct symbol *global_sym_chain[HASHSIZE]; @@ -163,6 +164,8 @@ end_stabs PARAMS ((void)); extern void finish_global_stabs PARAMS ((struct objfile *objfile)); +EXTERN int os9k_stabs; + /* Functions exported by dbxread.c. These are not in stabsread.h because they are only used by some stabs readers. */ @@ -179,16 +182,31 @@ extern void process_one_symbol PARAMS ((int, int, CORE_ADDR, char *, struct section_offsets *, struct objfile *)); -extern void -elfstab_build_psymtabs PARAMS ((struct objfile *objfile, - struct section_offsets *section_offsets, - int mainline, - file_ptr staboff, unsigned int stabsize, - file_ptr stabstroffset, - unsigned int stabstrsize)); +extern void elfstab_build_psymtabs + PARAMS ((struct objfile *objfile, + struct section_offsets *section_offsets, + int mainline, + file_ptr staboff, unsigned int stabsize, + file_ptr stabstroffset, + unsigned int stabstrsize)); -extern void -pastab_build_psymtabs PARAMS ((struct objfile *, struct section_offsets *, - int)); +extern void coffstab_build_psymtabs + PARAMS ((struct objfile *objfile, + struct section_offsets *section_offsets, + int mainline, + file_ptr staboff, unsigned int stabsize, + file_ptr stabstroffset, + unsigned int stabstrsize)); + +extern void stabsect_build_psymtabs + PARAMS ((struct objfile *objfile, + struct section_offsets *section_offsets, + int mainline, + char *stab_name, + char *stabstr_name, + char *text_name)); + +extern void elfstab_offset_sections PARAMS ((struct objfile *, + struct partial_symtab *)); #undef EXTERN diff --git a/gnu/usr.bin/gdb/gdb/stack.c b/gnu/usr.bin/gdb/gdb/stack.c index 6fdd8c181245..34f0d8331a56 100644 --- a/gnu/usr.bin/gdb/gdb/stack.c +++ b/gnu/usr.bin/gdb/gdb/stack.c @@ -30,6 +30,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "breakpoint.h" #include "demangle.h" #include "inferior.h" +#include "annotate.h" static void return_command PARAMS ((char *, int)); @@ -56,7 +57,7 @@ static void args_info PARAMS ((char *, int)); static void -print_frame_arg_vars PARAMS ((FRAME, FILE *)); +print_frame_arg_vars PARAMS ((FRAME, GDB_FILE *)); static void catch_info PARAMS ((char *, int)); @@ -65,16 +66,16 @@ static void locals_info PARAMS ((char *, int)); static void -print_frame_label_vars PARAMS ((FRAME, int, FILE *)); +print_frame_label_vars PARAMS ((FRAME, int, GDB_FILE *)); static void -print_frame_local_vars PARAMS ((FRAME, FILE *)); +print_frame_local_vars PARAMS ((FRAME, GDB_FILE *)); static int -print_block_frame_labels PARAMS ((struct block *, int *, FILE *)); +print_block_frame_labels PARAMS ((struct block *, int *, GDB_FILE *)); static int -print_block_frame_locals PARAMS ((struct block *, FRAME, FILE *)); +print_block_frame_locals PARAMS ((struct block *, FRAME, GDB_FILE *)); static void backtrace_command PARAMS ((char *, int)); @@ -101,10 +102,13 @@ FRAME selected_frame; int selected_frame_level; -/* Nonzero means print the full filename and linenumber - when a frame is printed, and do so in a format programs can parse. */ +/* Zero means do things normally; we are interacting directly with the + user. One means print the full filename and linenumber when a + frame is printed, and do so in a format emacs18/emacs19.22 can + parse. Two means print similar annotations, but in many more + cases and in a slightly different syntax. */ -int frame_file_full_name = 0; +int annotation_level = 0; struct print_stack_frame_args { @@ -167,10 +171,12 @@ print_args_stub (args) int numargs; struct print_args_args *p = (struct print_args_args *)args; FRAME_NUM_ARGS (numargs, (p->fi)); - print_frame_args (p->func, p->fi, numargs, stdout); + print_frame_args (p->func, p->fi, numargs, gdb_stdout); return 0; } +/* LEVEL is the level of the frame, or -1 if it is the innermost frame + but we don't want to print the level. */ void print_frame_info (fi, level, source, args) struct frame_info *fi; @@ -182,9 +188,13 @@ print_frame_info (fi, level, source, args) struct symbol *func; register char *funname = 0; enum language funlang = language_unknown; + +#if 0 char buf[MAX_REGISTER_RAW_SIZE]; CORE_ADDR sp; + /* On the 68k, this spends too much time in m68k_find_saved_regs. */ + /* Get the value of SP_REGNUM relative to the frame. */ get_saved_register (buf, (int *)NULL, (CORE_ADDR *)NULL, FRAME_INFO_ID (fi), SP_REGNUM, (enum lval_type *)NULL); @@ -195,33 +205,46 @@ print_frame_info (fi, level, source, args) will succeed even though there is no call dummy. Probably best is to check for a bp_call_dummy breakpoint. */ if (PC_IN_CALL_DUMMY (fi->pc, sp, fi->frame)) +#else + if (frame_in_dummy (fi)) +#endif { + annotate_frame_begin (level == -1 ? 0 : level, fi->pc); + /* Do this regardless of SOURCE because we don't have any source to list for this frame. */ if (level >= 0) printf_filtered ("#%-2d ", level); + annotate_function_call (); printf_filtered ("\n"); + annotate_frame_end (); return; } if (fi->signal_handler_caller) { + annotate_frame_begin (level == -1 ? 0 : level, fi->pc); + /* Do this regardless of SOURCE because we don't have any source to list for this frame. */ if (level >= 0) printf_filtered ("#%-2d ", level); + annotate_signal_handler_caller (); printf_filtered ("\n"); + annotate_frame_end (); return; } /* If fi is not the innermost frame, that normally means that fi->pc points to *after* the call instruction, and we want to get the line containing the call, never the next line. But if the next frame is - a signal_handler_caller frame, then the next frame was not entered - as the result of a call, and we want to get the line containing - fi->pc. */ + a signal_handler_caller or a dummy frame, then the next frame was + not entered as the result of a call, and we want to get the line + containing fi->pc. */ sal = find_pc_line (fi->pc, - fi->next != NULL && fi->next->signal_handler_caller == 0); + fi->next != NULL + && !fi->next->signal_handler_caller + && !frame_in_dummy (fi->next)); func = find_pc_function (fi->pc); if (func) @@ -247,9 +270,14 @@ print_frame_info (fi, level, source, args) && (SYMBOL_VALUE_ADDRESS (msymbol) > BLOCK_START (SYMBOL_BLOCK_VALUE (func)))) { +#if 0 + /* There is no particular reason to think the line number + information is wrong. Someone might have just put in + a label with asm() but left the line numbers alone. */ /* In this case we have no way of knowing the source file and line number, so don't print them. */ sal.symtab = 0; +#endif /* We also don't know anything about the function besides its address and name. */ func = 0; @@ -274,15 +302,24 @@ print_frame_info (fi, level, source, args) if (source >= 0 || !sal.symtab) { + annotate_frame_begin (level == -1 ? 0 : level, fi->pc); + if (level >= 0) printf_filtered ("#%-2d ", level); if (addressprint) if (fi->pc != sal.pc || !sal.symtab) - printf_filtered ("%s in ", local_hex_string((unsigned long) fi->pc)); - fprintf_symbol_filtered (stdout, funname ? funname : "??", funlang, - DMGL_NO_OPTS); + { + annotate_frame_address (); + print_address_numeric (fi->pc, 1, gdb_stdout); + annotate_frame_address_end (); + printf_filtered (" in "); + } + annotate_frame_function_name (); + fprintf_symbol_filtered (gdb_stdout, funname ? funname : "??", funlang, + DMGL_ANSI); wrap_here (" "); - fputs_filtered (" (", stdout); + annotate_frame_args (); + fputs_filtered (" (", gdb_stdout); if (args) { struct print_args_args args; @@ -293,18 +330,28 @@ print_frame_info (fi, level, source, args) printf_filtered (")"); if (sal.symtab && sal.symtab->filename) { + annotate_frame_source_begin (); wrap_here (" "); - printf_filtered (" at %s:%d", sal.symtab->filename, sal.line); + printf_filtered (" at "); + annotate_frame_source_file (); + printf_filtered ("%s", sal.symtab->filename); + annotate_frame_source_file_end (); + printf_filtered (":"); + annotate_frame_source_line (); + printf_filtered ("%d", sal.line); + annotate_frame_source_end (); } #ifdef PC_LOAD_SEGMENT /* If we couldn't print out function name but if can figure out what load segment this pc value is from, at least print out some info about its load segment. */ - if (!funname) { - wrap_here (" "); - printf_filtered (" from %s", PC_LOAD_SEGMENT (fi->pc)); - } + if (!funname) + { + annotate_frame_where (); + wrap_here (" "); + printf_filtered (" from %s", PC_LOAD_SEGMENT (fi->pc)); + } #endif printf_filtered ("\n"); } @@ -313,13 +360,16 @@ print_frame_info (fi, level, source, args) { int done = 0; int mid_statement = source < 0 && fi->pc != sal.pc; - if (frame_file_full_name) + if (annotation_level) done = identify_source_line (sal.symtab, sal.line, mid_statement, fi->pc); if (!done) { if (addressprint && mid_statement) - printf_filtered ("%s\t", local_hex_string((unsigned long) fi->pc)); + { + print_address_numeric (fi->pc, 1, gdb_stdout); + printf_filtered ("\t"); + } print_source_lines (sal.symtab, sal.line, sal.line + 1, 0); } current_source_line = max (sal.line - lines_to_list/2, 1); @@ -327,7 +377,9 @@ print_frame_info (fi, level, source, args) if (source != 0) set_default_breakpoint (1, fi->pc, sal.symtab, sal.line); - fflush (stdout); + annotate_frame_end (); + + gdb_flush (gdb_stdout); } /* @@ -388,6 +440,22 @@ parse_frame_specification (frame_exp) /* find_relative_frame was successful */ return fid; + /* If SETUP_ARBITRARY_FRAME is defined, then frame specifications + take at least 2 addresses. It is important to detect this case + here so that "frame 100" does not give a confusing error message + like "frame specification requires two addresses". This of course + does not solve the "frame 100" problem for machines on which + a frame specification can be made with one address. To solve + that, we need a new syntax for a specifying a frame by address. + I think the cleanest syntax is $frame(0x45) ($frame(0x23,0x45) for + two args, etc.), but people might think that is too much typing, + so I guess *0x23,0x45 would be a possible alternative (commas + really should be used instead of spaces to delimit; using spaces + normally works in an expression). */ +#ifdef SETUP_ARBITRARY_FRAME + error ("No frame %d", args[0]); +#endif + /* If (s)he specifies the frame with an address, he deserves what (s)he gets. Still, give the highest one that matches. */ @@ -402,9 +470,7 @@ parse_frame_specification (frame_exp) fid = tfid; /* We couldn't identify the frame as an existing frame, but - perhaps we can create one with a single argument. - Fall through to default case; it's up to SETUP_ARBITRARY_FRAME - to complain if it doesn't like a single arg. */ + perhaps we can create one with a single argument. */ } default: @@ -447,7 +513,7 @@ frame_info (addr_exp, from_tty) struct symbol *func; struct symtab *s; FRAME calling_frame; - int i, count; + int i, count, numregs; char *funname = 0; enum language funlang = language_unknown; @@ -460,7 +526,9 @@ frame_info (addr_exp, from_tty) fi = get_frame_info (frame); sal = find_pc_line (fi->pc, - fi->next != NULL && fi->next->signal_handler_caller == 0); + fi->next != NULL + && !fi->next->signal_handler_caller + && !frame_in_dummy (fi->next)); func = get_frame_function (frame); s = find_pc_symtab(fi->pc); if (func) @@ -479,23 +547,27 @@ frame_info (addr_exp, from_tty) } calling_frame = get_prev_frame (frame); - if (!addr_exp && selected_frame_level >= 0) { - printf_filtered ("Stack level %d, frame at %s:\n", - selected_frame_level, - local_hex_string((unsigned long) FRAME_FP(frame))); - } else { - printf_filtered ("Stack frame at %s:\n", - local_hex_string((unsigned long) FRAME_FP(frame))); - } - printf_filtered (" %s = %s", - reg_names[PC_REGNUM], - local_hex_string((unsigned long) fi->pc)); + if (!addr_exp && selected_frame_level >= 0) + { + printf_filtered ("Stack level %d, frame at ", selected_frame_level); + print_address_numeric (FRAME_FP(frame), 1, gdb_stdout); + printf_filtered (":\n"); + } + else + { + printf_filtered ("Stack frame at "); + print_address_numeric (FRAME_FP(frame), 1, gdb_stdout); + printf_filtered (":\n"); + } + printf_filtered (" %s = ", + reg_names[PC_REGNUM]); + print_address_numeric (fi->pc, 1, gdb_stdout); wrap_here (" "); if (funname) { printf_filtered (" in "); - fprintf_symbol_filtered (stdout, funname, funlang, + fprintf_symbol_filtered (gdb_stdout, funname, funlang, DMGL_ANSI | DMGL_PARAMS); } wrap_here (" "); @@ -503,8 +575,9 @@ frame_info (addr_exp, from_tty) printf_filtered (" (%s:%d)", sal.symtab->filename, sal.line); puts_filtered ("; "); wrap_here (" "); - printf_filtered ("saved %s %s\n", reg_names[PC_REGNUM], - local_hex_string((unsigned long) FRAME_SAVED_PC (frame))); + printf_filtered ("saved %s ", reg_names[PC_REGNUM]); + print_address_numeric (FRAME_SAVED_PC (frame), 1, gdb_stdout); + printf_filtered ("\n"); { int frameless = 0; @@ -516,18 +589,22 @@ frame_info (addr_exp, from_tty) } if (calling_frame) - printf_filtered (" called by frame at %s", - local_hex_string((unsigned long) FRAME_FP (calling_frame))); + { + printf_filtered (" called by frame at "); + print_address_numeric (FRAME_FP (calling_frame), 1, gdb_stdout); + } if (fi->next && calling_frame) puts_filtered (","); wrap_here (" "); if (fi->next) - printf_filtered (" caller of frame at %s", - local_hex_string ((unsigned long) fi->next->frame)); + { + printf_filtered (" caller of frame at "); + print_address_numeric (fi->next->frame, 1, gdb_stdout); + } if (fi->next || calling_frame) puts_filtered ("\n"); if (s) - printf_filtered(" source language %s.\n", language_str(s->language)); + printf_filtered (" source language %s.\n", language_str (s->language)); #ifdef PRINT_EXTRA_FRAME_INFO PRINT_EXTRA_FRAME_INFO (fi); @@ -540,11 +617,12 @@ frame_info (addr_exp, from_tty) int numargs; if (arg_list == 0) - printf_filtered (" Arglist at unknown address.\n"); + printf_filtered (" Arglist at unknown address.\n"); else { - printf_filtered (" Arglist at %s,", - local_hex_string((unsigned long) arg_list)); + printf_filtered (" Arglist at "); + print_address_numeric (arg_list, 1, gdb_stdout); + printf_filtered (","); FRAME_NUM_ARGS (numargs, fi); if (numargs < 0) @@ -555,7 +633,7 @@ frame_info (addr_exp, from_tty) puts_filtered (" 1 arg: "); else printf_filtered (" %d args: ", numargs); - print_frame_args (func, fi, numargs, stdout); + print_frame_args (func, fi, numargs, gdb_stdout); puts_filtered ("\n"); } } @@ -564,20 +642,25 @@ frame_info (addr_exp, from_tty) CORE_ADDR arg_list = FRAME_LOCALS_ADDRESS (fi); if (arg_list == 0) - printf_filtered (" Locals at unknown address,"); + printf_filtered (" Locals at unknown address,"); else - printf_filtered (" Locals at %s,", - local_hex_string((unsigned long) arg_list)); + { + printf_filtered (" Locals at "); + print_address_numeric (arg_list, 1, gdb_stdout); + printf_filtered (","); + } } #if defined (FRAME_FIND_SAVED_REGS) get_frame_saved_regs (fi, &fsr); /* The sp is special; what's returned isn't the save address, but actually the value of the previous frame's sp. */ - printf_filtered (" Previous frame's sp is %s\n", - local_hex_string((unsigned long) fsr.regs[SP_REGNUM])); + printf_filtered (" Previous frame's sp is "); + print_address_numeric (fsr.regs[SP_REGNUM], 1, gdb_stdout); + printf_filtered ("\n"); count = 0; - for (i = 0; i < NUM_REGS; i++) + numregs = ARCH_NUM_REGS; + for (i = 0; i < numregs; i++) if (fsr.regs[i] && i != SP_REGNUM) { if (count == 0) @@ -585,12 +668,14 @@ frame_info (addr_exp, from_tty) else puts_filtered (","); wrap_here (" "); - printf_filtered (" %s at %s", reg_names[i], - local_hex_string((unsigned long) fsr.regs[i])); + printf_filtered (" %s at ", reg_names[i]); + print_address_numeric (fsr.regs[i], 1, gdb_stdout); count++; } if (count) puts_filtered ("\n"); +#else /* Have FRAME_FIND_SAVED_REGS. */ + puts_filtered ("\n"); #endif /* Have FRAME_FIND_SAVED_REGS. */ } @@ -621,7 +706,7 @@ backtrace_limit_info (arg, from_tty) if (arg) error ("\"Info backtrace-limit\" takes no arguments."); - printf ("Backtrace limit: %d.\n", backtrace_limit); + printf_unfiltered ("Backtrace limit: %d.\n", backtrace_limit); } #endif @@ -728,7 +813,7 @@ static int print_block_frame_locals (b, frame, stream) struct block *b; register FRAME frame; - register FILE *stream; + register GDB_FILE *stream; { int nsyms; register int i; @@ -740,15 +825,22 @@ print_block_frame_locals (b, frame, stream) for (i = 0; i < nsyms; i++) { sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (sym) == LOC_LOCAL - || SYMBOL_CLASS (sym) == LOC_REGISTER - || SYMBOL_CLASS (sym) == LOC_STATIC) + switch (SYMBOL_CLASS (sym)) { + case LOC_LOCAL: + case LOC_REGISTER: + case LOC_STATIC: + case LOC_BASEREG: values_printed = 1; fputs_filtered (SYMBOL_SOURCE_NAME (sym), stream); fputs_filtered (" = ", stream); print_variable_value (sym, frame, stream); fprintf_filtered (stream, "\n"); + break; + + default: + /* Ignore symbols which are not locals. */ + break; } } return values_printed; @@ -760,7 +852,7 @@ static int print_block_frame_labels (b, have_default, stream) struct block *b; int *have_default; - register FILE *stream; + register GDB_FILE *stream; { int nsyms; register int i; @@ -785,8 +877,10 @@ print_block_frame_labels (b, have_default, stream) values_printed = 1; fputs_filtered (SYMBOL_SOURCE_NAME (sym), stream); if (addressprint) - fprintf_filtered (stream, " %s", - local_hex_string((unsigned long) SYMBOL_VALUE_ADDRESS (sym))); + { + fprintf_filtered (stream, " "); + print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, stream); + } fprintf_filtered (stream, " in file %s, line %d\n", sal.symtab->filename, sal.line); } @@ -805,7 +899,7 @@ print_block_frame_labels (b, have_default, stream) static void print_frame_local_vars (frame, stream) register FRAME frame; - register FILE *stream; + register GDB_FILE *stream; { register struct block *block = get_frame_block (frame); register int values_printed = 0; @@ -840,7 +934,7 @@ static void print_frame_label_vars (frame, this_level_only, stream) register FRAME frame; int this_level_only; - register FILE *stream; + register GDB_FILE *stream; { register struct blockvector *bl; register struct block *block = get_frame_block (frame); @@ -915,7 +1009,7 @@ locals_info (args, from_tty) { if (!selected_frame) error ("No frame selected."); - print_frame_local_vars (selected_frame, stdout); + print_frame_local_vars (selected_frame, gdb_stdout); } static void @@ -925,13 +1019,13 @@ catch_info (ignore, from_tty) { if (!selected_frame) error ("No frame selected."); - print_frame_label_vars (selected_frame, 0, stdout); + print_frame_label_vars (selected_frame, 0, gdb_stdout); } static void print_frame_arg_vars (frame, stream) register FRAME frame; - register FILE *stream; + register GDB_FILE *stream; { struct symbol *func = get_frame_function (frame); register struct block *b; @@ -1000,7 +1094,7 @@ args_info (ignore, from_tty) { if (!selected_frame) error ("No frame selected."); - print_frame_arg_vars (selected_frame, stdout); + print_frame_arg_vars (selected_frame, gdb_stdout); } /* Select frame FRAME, and note that its stack level is LEVEL. @@ -1199,7 +1293,16 @@ down_silently_command (count_exp, from_tty) frame = find_relative_frame (selected_frame, &count1); if (count1 != 0 && count_exp == 0) - error ("Bottom (i.e., innermost) frame selected; you cannot go down."); + { + + /* We only do this if count_exp is not specified. That way "down" + means to really go down (and let me know if that is + impossible), but "down 9999" can be used to mean go all the way + down without getting an error. */ + + error ("Bottom (i.e., innermost) frame selected; you cannot go down."); + } + select_frame (frame, selected_frame_level + count - count1); } @@ -1222,7 +1325,7 @@ return_command (retval_exp, from_tty) FRAME_ADDR selected_frame_addr; CORE_ADDR selected_frame_pc; FRAME frame; - value return_value = NULL; + value_ptr return_value = NULL; if (selected_frame == NULL) error ("No selected frame."); diff --git a/gnu/usr.bin/gdb/gdb/symfile.c b/gnu/usr.bin/gdb/gdb/symfile.c index 197c0c3a6221..a56e2339e123 100644 --- a/gnu/usr.bin/gdb/gdb/symfile.c +++ b/gnu/usr.bin/gdb/gdb/symfile.c @@ -1,5 +1,5 @@ /* Generic symbol file reading for the GNU debugger, GDB. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. This file is part of GDB. @@ -48,7 +48,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #endif /* Global variables owned by this file */ - int readnow_symbol_files; /* Read full symbols immediately */ struct complaint oldsyms_complaint = { @@ -74,6 +73,9 @@ load_command PARAMS ((char *, int)); static void add_symbol_file_command PARAMS ((char *, int)); +static void +add_shared_symbol_files_command PARAMS ((char *, int)); + static void cashier_psymtab PARAMS ((struct partial_symtab *)); @@ -215,21 +217,6 @@ sort_symtab_syms (s) } } -void -sort_all_symtab_syms () -{ - register struct symtab *s; - register struct objfile *objfile; - - for (objfile = object_files; objfile != NULL; objfile = objfile -> next) - { - for (s = objfile -> symtabs; s != NULL; s = s -> next) - { - sort_symtab_syms (s); - } - } -} - /* Make a copy of the string at PTR with SIZE characters in the symbol obstack (and add a null character at the end in the copy). Returns the address of the copy. */ @@ -310,11 +297,9 @@ init_entry_point_info (objfile) else { /* Examination of non-executable.o files. Short-circuit this stuff. */ - /* ~0 will not be in any file, we hope. */ - objfile -> ei.entry_point = ~0; - /* set the startup file to be an empty range. */ - objfile -> ei.entry_file_lowpc = 0; - objfile -> ei.entry_file_highpc = 0; + objfile -> ei.entry_point = INVALID_ENTRY_POINT; + objfile -> ei.entry_file_lowpc = INVALID_ENTRY_LOWPC; + objfile -> ei.entry_file_highpc = INVALID_ENTRY_HIGHPC; } } @@ -391,6 +376,11 @@ syms_from_objfile (objfile, addr, mainline, verbo) symfile_objfile = NULL; } + /* Currently we keep symbols from the add-symbol-file command. + If the user wants to get rid of them, they should do "symbol-file" + without arguments first. Not sure this is the best behavior + (PR 2207). */ + (*objfile -> sf -> sym_new_init) (objfile); } @@ -419,6 +409,7 @@ syms_from_objfile (objfile, addr, mainline, verbo) else if (0 == bfd_get_section_name (objfile->obfd, lowest_sect) || !STREQ (".text", bfd_get_section_name (objfile->obfd, lowest_sect))) + /* FIXME-32x64--assumes bfd_vma fits in long. */ warning ("Lowest section in %s is %s at 0x%lx", objfile->name, bfd_section_name (objfile->obfd, lowest_sect), @@ -435,9 +426,6 @@ syms_from_objfile (objfile, addr, mainline, verbo) (*objfile -> sf -> sym_init) (objfile); clear_complaints (1, verbo); - /* If objfile->sf->sym_offsets doesn't set this, we don't care - (currently). */ - objfile->num_sections = 0; /* krp-FIXME: why zero? */ section_offsets = (*objfile -> sf -> sym_offsets) (objfile, addr); objfile->section_offsets = section_offsets; @@ -477,8 +465,17 @@ syms_from_objfile (objfile, addr, mainline, verbo) (*objfile -> sf -> sym_read) (objfile, section_offsets, mainline); - /* Don't allow char * to have a typename (else would get caddr_t.) */ - /* Ditto void *. FIXME should do this for all the builtin types. */ + if (!have_partial_symbols () && !have_full_symbols ()) + { + wrap_here (""); + printf_filtered ("(no debugging symbols found)..."); + wrap_here (""); + } + + /* Don't allow char * to have a typename (else would get caddr_t). + Ditto void *. FIXME: Check whether this is now done by all the + symbol readers themselves (many of them now do), and if so remove + it from here. */ TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; TYPE_NAME (lookup_pointer_type (builtin_type_void)) = 0; @@ -575,7 +572,7 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) { printf_filtered ("Mapped symbols for %s...", name); wrap_here (""); - fflush (stdout); + gdb_flush (gdb_stdout); } init_entry_point_info (objfile); find_sym_fns (objfile); @@ -589,7 +586,7 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) { printf_filtered ("Reading symbols from %s...", name); wrap_here (""); - fflush (stdout); + gdb_flush (gdb_stdout); } syms_from_objfile (objfile, addr, mainline, from_tty); } @@ -605,7 +602,7 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) { printf_filtered ("expanding to full symbols..."); wrap_here (""); - fflush (stdout); + gdb_flush (gdb_stdout); } for (psymtab = objfile -> psymtabs; @@ -619,7 +616,7 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) if (from_tty || info_verbose) { printf_filtered ("done.\n"); - fflush (stdout); + gdb_flush (gdb_stdout); } new_symfile_objfile (objfile, mainline, from_tty); @@ -632,8 +629,15 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) return (objfile); } -/* This is the symbol-file command. Read the file, analyze its symbols, - and add a struct symtab to a symtab list. */ +/* This is the symbol-file command. Read the file, analyze its + symbols, and add a struct symtab to a symtab list. The syntax of + the command is rather bizarre--(1) buildargv implements various + quoting conventions which are undocumented and have little or + nothing in common with the way things are quoted (or not quoted) + elsewhere in GDB, (2) options are used, which are not generally + used in GDB (perhaps "set mapped on", "set readnow on" would be + better), (3) the order of options matters, which is contrary to GNU + conventions (because it is confusing and inconvenient). */ void symbol_file_command (args, from_tty) @@ -642,6 +646,7 @@ symbol_file_command (args, from_tty) { char **argv; char *name = NULL; + CORE_ADDR text_relocation = 0; /* text_relocation */ struct cleanup *cleanups; int mapped = 0; int readnow = 0; @@ -659,7 +664,7 @@ symbol_file_command (args, from_tty) symfile_objfile = NULL; if (from_tty) { - printf ("No symbol file now.\n"); + printf_unfiltered ("No symbol file now.\n"); } } else @@ -685,7 +690,27 @@ symbol_file_command (args, from_tty) } else { - name = *argv; + char *p; + + name = *argv; + + /* this is for rombug remote only, to get the text relocation by + using link command */ + p = strrchr(name, '/'); + if (p != NULL) p++; + else p = name; + + target_link(p, &text_relocation); + + if (text_relocation == (CORE_ADDR)0) + return; + else if (text_relocation == (CORE_ADDR)-1) + symbol_file_add (name, from_tty, (CORE_ADDR)0, 1, mapped, + readnow); + else + symbol_file_add (name, from_tty, (CORE_ADDR)text_relocation, + 0, mapped, readnow); + set_initial_language (); } argv++; } @@ -694,11 +719,6 @@ symbol_file_command (args, from_tty) { error ("no symbol file name was specified"); } - else - { - symbol_file_add (name, from_tty, (CORE_ADDR)0, 1, mapped, readnow); - set_initial_language (); - } do_cleanups (cleanups); } } @@ -768,7 +788,7 @@ symfile_bfd_open (name) close (desc); make_cleanup (free, name); error ("\"%s\": can't open to read symbols: %s.", name, - bfd_errmsg (bfd_error)); + bfd_errmsg (bfd_get_error ())); } sym_bfd->cacheable = true; @@ -777,7 +797,7 @@ symfile_bfd_open (name) bfd_close (sym_bfd); /* This also closes desc */ make_cleanup (free, name); error ("\"%s\": can't read symbols: %s.", name, - bfd_errmsg (bfd_error)); + bfd_errmsg (bfd_get_error ())); } return (sym_bfd); @@ -807,11 +827,20 @@ find_sym_fns (objfile) struct objfile *objfile; { struct sym_fns *sf; + enum bfd_flavour our_flavour = bfd_get_flavour (objfile -> obfd); + char *our_target = bfd_get_target (objfile -> obfd); + + /* Special kludge for RS/6000. See xcoffread.c. */ + if (STREQ (our_target, "aixcoff-rs6000")) + our_flavour = (enum bfd_flavour)-1; + + /* Special kludge for apollo. See dstread.c. */ + if (STREQN (our_target, "apollo", 6)) + our_flavour = (enum bfd_flavour)-2; for (sf = symtab_fns; sf != NULL; sf = sf -> next) { - if (strncmp (bfd_get_target (objfile -> obfd), - sf -> sym_name, sf -> sym_namelen) == 0) + if (our_flavour == sf -> sym_flavour) { objfile -> sf = sf; return; @@ -846,7 +875,12 @@ generic_load (filename, from_tty) { struct cleanup *old_cleanups; asection *s; - bfd *loadfile_bfd = bfd_openr (filename, gnutarget); + bfd *loadfile_bfd; + + if (filename == NULL) + filename = get_exec_file (1); + + loadfile_bfd = bfd_openr (filename, gnutarget); if (loadfile_bfd == NULL) { perror_with_name (filename); @@ -857,7 +891,7 @@ generic_load (filename, from_tty) if (!bfd_check_format (loadfile_bfd, bfd_object)) { error ("\"%s\" is not an object file: %s", filename, - bfd_errmsg (bfd_error)); + bfd_errmsg (bfd_get_error ())); } for (s = loadfile_bfd->sections; s; s = s->next) @@ -880,9 +914,11 @@ generic_load (filename, from_tty) /* Is this really necessary? I guess it gives the user something to look at during a long download. */ - printf_filtered ("Loading section %s, size 0x%lx vma 0x%lx\n", + printf_filtered ("Loading section %s, size 0x%lx vma ", bfd_get_section_name (loadfile_bfd, s), - (unsigned long) size, (unsigned long) vma); + (unsigned long) size); + print_address_numeric (vma, 1, gdb_stdout); + printf_filtered ("\n"); bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size); @@ -966,15 +1002,25 @@ add_symbol_file_command (args, from_tty) left pointing at the remainder of the command line, which should be the address expression to evaluate. */ - if ((name == NULL) || (*args == '\000') ) + if (name == NULL) { - error ("add-symbol-file takes a file name and an address"); + error ("add-symbol-file takes a file name"); } name = tilde_expand (name); make_cleanup (free, name); - text_addr = parse_and_eval_address (args); + if (*args != '\000') + { + text_addr = parse_and_eval_address (args); + } + else + { + target_link(name, &text_addr); + if (text_addr == (CORE_ADDR)-1) + error("Don't know how to get text start location for this file"); + } + /* FIXME-32x64: Assumes text_addr fits in a long. */ if (!query ("add symbol table from file \"%s\" at text_addr = %s?\n", name, local_hex_string ((unsigned long)text_addr))) error ("Not confirmed."); @@ -982,6 +1028,18 @@ add_symbol_file_command (args, from_tty) symbol_file_add (name, 0, text_addr, 0, mapped, readnow); } +static void +add_shared_symbol_files_command (args, from_tty) + char *args; + int from_tty; +{ +#ifdef ADD_SHARED_SYMBOL_FILES + ADD_SHARED_SYMBOL_FILES (args, from_tty); +#else + error ("This command is not available in this configuration of GDB."); +#endif +} + /* Re-read symbols if a symbol-file has changed. */ void reread_symbols () @@ -998,7 +1056,6 @@ reread_symbols () This routine should then walk down each partial symbol table and see if the symbol table that it originates from has been changed */ -the_big_top: for (objfile = object_files; objfile; objfile = objfile->next) { if (objfile->obfd) { #ifdef IBM6000_TARGET @@ -1017,24 +1074,150 @@ reread_symbols () continue; } new_modtime = new_statbuf.st_mtime; - if (new_modtime != objfile->mtime) { - printf_filtered ("`%s' has changed; re-reading symbols.\n", - objfile->name); - /* FIXME, this should use a different command...that would only - affect this objfile's symbols, and would reset objfile->mtime. - (objfile->mtime = new_modtime;) - HOWEVER, that command isn't written yet -- so call symbol_file_ - command, and restart the scan from the top, because it munges - the object_files list. */ - symbol_file_command (objfile->name, 0); - reread_one = 1; - goto the_big_top; /* Start over. */ - } + if (new_modtime != objfile->mtime) + { + struct cleanup *old_cleanups; + struct section_offsets *offsets; + int num_offsets; + int section_offsets_size; + + printf_filtered ("`%s' has changed; re-reading symbols.\n", + objfile->name); + + /* There are various functions like symbol_file_add, + symfile_bfd_open, syms_from_objfile, etc., which might + appear to do what we want. But they have various other + effects which we *don't* want. So we just do stuff + ourselves. We don't worry about mapped files (for one thing, + any mapped file will be out of date). */ + + /* If we get an error, blow away this objfile (not sure if + that is the correct response for things like shared + libraries). */ + old_cleanups = make_cleanup (free_objfile, objfile); + /* We need to do this whenever any symbols go away. */ + make_cleanup (clear_symtab_users, 0); + + /* Clean up any state BFD has sitting around. We don't need + to close the descriptor but BFD lacks a way of closing the + BFD without closing the descriptor. */ + if (!bfd_close (objfile->obfd)) + error ("Can't close BFD for %s.", objfile->name); + objfile->obfd = bfd_openr (objfile->name, gnutarget); + if (objfile->obfd == NULL) + error ("Can't open %s to read symbols.", objfile->name); + /* bfd_openr sets cacheable to true, which is what we want. */ + if (!bfd_check_format (objfile->obfd, bfd_object)) + error ("Can't read symbols from %s: %s.", objfile->name, + bfd_errmsg (bfd_get_error ())); + + /* Save the offsets, we will nuke them with the rest of the + psymbol_obstack. */ + num_offsets = objfile->num_sections; + section_offsets_size = + sizeof (struct section_offsets) + + sizeof (objfile->section_offsets->offsets) * num_offsets; + offsets = (struct section_offsets *) alloca (section_offsets_size); + memcpy (offsets, objfile->section_offsets, section_offsets_size); + + /* Nuke all the state that we will re-read. Much of the following + code which sets things to NULL really is necessary to tell + other parts of GDB that there is nothing currently there. */ + + /* FIXME: Do we have to free a whole linked list, or is this + enough? */ + if (objfile->global_psymbols.list) + mfree (objfile->md, objfile->global_psymbols.list); + objfile->global_psymbols.list = NULL; + objfile->global_psymbols.next = NULL; + objfile->global_psymbols.size = 0; + if (objfile->static_psymbols.list) + mfree (objfile->md, objfile->static_psymbols.list); + objfile->static_psymbols.list = NULL; + objfile->static_psymbols.next = NULL; + objfile->static_psymbols.size = 0; + + /* Free the obstacks for non-reusable objfiles */ + obstack_free (&objfile -> psymbol_obstack, 0); + obstack_free (&objfile -> symbol_obstack, 0); + obstack_free (&objfile -> type_obstack, 0); + objfile->sections = NULL; + objfile->symtabs = NULL; + objfile->psymtabs = NULL; + objfile->free_psymtabs = NULL; + objfile->msymbols = NULL; + objfile->minimal_symbol_count= 0; + objfile->fundamental_types = NULL; + if (objfile -> sf != NULL) + { + (*objfile -> sf -> sym_finish) (objfile); + } + + /* We never make this a mapped file. */ + objfile -> md = NULL; + /* obstack_specify_allocation also initializes the obstack so + it is empty. */ + obstack_specify_allocation (&objfile -> psymbol_obstack, 0, 0, + xmalloc, free); + obstack_specify_allocation (&objfile -> symbol_obstack, 0, 0, + xmalloc, free); + obstack_specify_allocation (&objfile -> type_obstack, 0, 0, + xmalloc, free); + if (build_objfile_section_table (objfile)) + { + error ("Can't find the file sections in `%s': %s", + objfile -> name, bfd_errmsg (bfd_get_error ())); + } + + /* We use the same section offsets as from last time. I'm not + sure whether that is always correct for shared libraries. */ + objfile->section_offsets = (struct section_offsets *) + obstack_alloc (&objfile -> psymbol_obstack, section_offsets_size); + memcpy (objfile->section_offsets, offsets, section_offsets_size); + objfile->num_sections = num_offsets; + + /* What the hell is sym_new_init for, anyway? The concept of + distinguishing between the main file and additional files + in this way seems rather dubious. */ + if (objfile == symfile_objfile) + (*objfile->sf->sym_new_init) (objfile); + + (*objfile->sf->sym_init) (objfile); + clear_complaints (1, 1); + /* The "mainline" parameter is a hideous hack; I think leaving it + zero is OK since dbxread.c also does what it needs to do if + objfile->global_psymbols.size is 0. */ + (*objfile->sf->sym_read) (objfile, objfile->section_offsets, 0); + if (!have_partial_symbols () && !have_full_symbols ()) + { + wrap_here (""); + printf_filtered ("(no debugging symbols found)\n"); + wrap_here (""); + } + objfile -> flags |= OBJF_SYMS; + + /* We're done reading the symbol file; finish off complaints. */ + clear_complaints (0, 1); + + /* Getting new symbols may change our opinion about what is + frameless. */ + + reinit_frame_cache (); + + /* Discard cleanups as symbol reading was successful. */ + discard_cleanups (old_cleanups); + + /* If the mtime has changed between the time we set new_modtime + and now, we *want* this to be out of date, so don't call stat + again now. */ + objfile->mtime = new_modtime; + reread_one = 1; + } } } if (reread_one) - breakpoint_re_set (); + clear_symtab_users (); } @@ -1052,7 +1235,10 @@ deduce_language_from_filename (filename) return language_m2; else if (STREQ(c,".c")) return language_c; - else if (STREQ (c,".cc") || STREQ (c,".C") || STREQ (c, ".cxx")) + else if (STREQ(c,".s")) + return language_asm; + else if (STREQ (c,".cc") || STREQ (c,".C") || STREQ (c, ".cxx") + || STREQ (c, ".cpp")) return language_cplus; else if (STREQ (c,".ch") || STREQ (c,".c186") || STREQ (c,".c286")) return language_chill; @@ -1150,6 +1336,7 @@ clear_symtab_users () set_default_breakpoint (0, 0, 0, 0); current_source_symtab = 0; current_source_line = 0; + clear_pc_function_cache (); } /* clear_symtab_users_once: @@ -1469,11 +1656,19 @@ to execute.", &cmdlist); c->completer = filename_completer; c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command, - "Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\ -The second argument provides the starting address of the file's text.", + "Usage: add-symbol-file FILE ADDR\n\ +Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\ +ADDR is the starting address of the file's text.", &cmdlist); c->completer = filename_completer; + c = add_cmd ("add-shared-symbol-files", class_files, + add_shared_symbol_files_command, + "Load the symbols from shared objects in the dynamic linker's link map.", + &cmdlist); + c = add_alias_cmd ("assf", "add-shared-symbol-files", class_files, 1, + &cmdlist); + c = add_cmd ("load", class_files, load_command, "Dynamically load FILE into the running program, and record its symbols\n\ for access from GDB.", &cmdlist); diff --git a/gnu/usr.bin/gdb/gdb/symfile.h b/gnu/usr.bin/gdb/gdb/symfile.h index 70bc73db4b00..ed43049d588a 100644 --- a/gnu/usr.bin/gdb/gdb/symfile.h +++ b/gnu/usr.bin/gdb/gdb/symfile.h @@ -33,18 +33,10 @@ struct psymbol_allocation_list { struct sym_fns { - /* is the name, or name prefix, of the BFD "target type" that this - set of functions handles. E.g. "a.out" or "sunOs" or "coff" or "elf". */ + /* BFD flavour that we handle, or (as a special kludge, see xcoffread.c, + (enum bfd_flavour)-1 for xcoff). */ - char *sym_name; - - /* counts how many bytes of sym_name should be checked against the - BFD target type of the file being read. If an exact match is - desired, specify the number of characters in sym_name plus 1 for - the '\0'. If a prefix match is desired, specify the number of - characters in sym_name. */ - - int sym_namelen; + enum bfd_flavour sym_flavour; /* Initializes anything that is global to the entire symbol table. It is called during symbol_file_add, when we begin debugging an entirely new @@ -133,7 +125,7 @@ extend_psymbol_list PARAMS ((struct psymbol_allocation_list *, VT (psym) = (VALUE); \ SYMBOL_LANGUAGE (psym) = (LANGUAGE); \ SYMBOL_INIT_DEMANGLED_NAME (psym, &objfile->psymbol_obstack); \ - } while (0); + } while (0) /* Add a symbol with an integer value to a psymtab. */ @@ -187,9 +179,6 @@ sort_block_syms PARAMS ((struct block *)); extern void sort_symtab_syms PARAMS ((struct symtab *)); -extern void -sort_all_symtab_syms PARAMS ((void)); - /* Make a copy of the string at PTR with SIZE characters in the symbol obstack (and add a null character at the end in the copy). Returns the address of the copy. */ @@ -220,9 +209,42 @@ extern void dwarf_build_psymtabs PARAMS ((struct objfile *, struct section_offsets *, int, file_ptr, unsigned int, file_ptr, unsigned int)); +/* From mdebugread.c */ + +/* Hack to force structures to exist before use in parameter list. */ +struct ecoff_debug_hack +{ + struct ecoff_debug_swap *a; + struct ecoff_debug_info *b; +}; +extern void +mdebug_build_psymtabs PARAMS ((struct objfile *, + const struct ecoff_debug_swap *, + struct ecoff_debug_info *, + struct section_offsets *)); + +extern void +elfmdebug_build_psymtabs PARAMS ((struct objfile *, + const struct ecoff_debug_swap *, + asection *, + struct section_offsets *)); + /* From demangle.c */ extern void set_demangling_style PARAMS ((char *)); + +/* Stuff shared between coffread.c and xcoffread.c. Eventually we want + to merge coffread.c and xcoffread.c so this part of this header can + go away. */ + +#if 0 +extern char *coff_getfilename PARAMS ((union internal_auxent *)); +#else +/* Don't declare the arguments; if union internal_auxent has not been + declared here, gcc1 will give warnings. */ +extern char *coff_getfilename (); +#endif + #endif /* !defined(SYMFILE_H) */ diff --git a/gnu/usr.bin/gdb/gdb/symmisc.c b/gnu/usr.bin/gdb/gdb/symmisc.c index 411a53bef96a..4185c8a15193 100644 --- a/gnu/usr.bin/gdb/gdb/symmisc.c +++ b/gnu/usr.bin/gdb/gdb/symmisc.c @@ -1,5 +1,6 @@ /* Do various things to symbol tables (other than lookup), for GDB. - Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -47,13 +48,13 @@ FILE *std_err; /* Prototypes for local functions */ static void -dump_symtab PARAMS ((struct objfile *, struct symtab *, FILE *)); +dump_symtab PARAMS ((struct objfile *, struct symtab *, GDB_FILE *)); static void -dump_psymtab PARAMS ((struct objfile *, struct partial_symtab *, FILE *)); +dump_psymtab PARAMS ((struct objfile *, struct partial_symtab *, GDB_FILE *)); static void -dump_msymbols PARAMS ((struct objfile *, FILE *)); +dump_msymbols PARAMS ((struct objfile *, GDB_FILE *)); static void dump_objfile PARAMS ((struct objfile *)); @@ -62,12 +63,12 @@ static int block_depth PARAMS ((struct block *)); static void -print_partial_symbol PARAMS ((struct partial_symbol *, int, char *, FILE *)); +print_partial_symbol PARAMS ((struct partial_symbol *, int, char *, GDB_FILE *)); struct print_symbol_args { struct symbol *symbol; int depth; - FILE *outfile; + GDB_FILE *outfile; }; static int print_symbol PARAMS ((char *)); @@ -159,9 +160,11 @@ dump_objfile (objfile) struct partial_symtab *psymtab; printf_filtered ("\nObject file %s: ", objfile -> name); - printf_filtered ("Objfile at %lx, bfd at %lx, %d minsyms\n\n", - (unsigned long) objfile, - (unsigned long) objfile -> obfd, + printf_filtered ("Objfile at "); + gdb_print_address (objfile, gdb_stdout); + printf_filtered (", bfd at "); + gdb_print_address (objfile->obfd, gdb_stdout); + printf_filtered (", %d minsyms\n\n", objfile->minimal_symbol_count); if (objfile -> psymtabs) @@ -171,8 +174,10 @@ dump_objfile (objfile) psymtab != NULL; psymtab = psymtab -> next) { - printf_filtered ("%s at %lx, ", - psymtab -> filename, (unsigned long) psymtab); + printf_filtered ("%s at ", + psymtab -> filename); + gdb_print_address (psymtab, gdb_stdout); + printf_filtered (", "); if (psymtab -> objfile != objfile) { printf_filtered ("NOT ON CHAIN! "); @@ -189,8 +194,9 @@ dump_objfile (objfile) symtab != NULL; symtab = symtab->next) { - printf_filtered ("%s at %lx, ", - symtab -> filename, (unsigned long) symtab); + printf_filtered ("%s at ", symtab -> filename); + gdb_print_address (symtab, gdb_stdout); + printf_filtered (", "); if (symtab -> objfile != objfile) { printf_filtered ("NOT ON CHAIN! "); @@ -206,7 +212,7 @@ dump_objfile (objfile) static void dump_msymbols (objfile, outfile) struct objfile *objfile; - FILE *outfile; + GDB_FILE *outfile; { struct minimal_symbol *msymbol; int index; @@ -229,6 +235,9 @@ dump_msymbols (objfile, outfile) case mst_text: ms_type = 'T'; break; + case mst_solib_trampoline: + ms_type = 'S'; + break; case mst_data: ms_type = 'D'; break; @@ -271,43 +280,54 @@ static void dump_psymtab (objfile, psymtab, outfile) struct objfile *objfile; struct partial_symtab *psymtab; - FILE *outfile; + GDB_FILE *outfile; { int i; fprintf_filtered (outfile, "\nPartial symtab for source file %s ", psymtab -> filename); - fprintf_filtered (outfile, "(object 0x%lx)\n\n", (unsigned long) psymtab); - fprintf (outfile, " Read from object file %s (0x%lx)\n", - objfile -> name, (unsigned long) objfile); - + fprintf_filtered (outfile, "(object "); + gdb_print_address (psymtab, outfile); + fprintf_filtered (outfile, ")\n\n"); + fprintf_unfiltered (outfile, " Read from object file %s (", + objfile -> name); + gdb_print_address (objfile, outfile); + fprintf_unfiltered (outfile, ")\n"); + if (psymtab -> readin) { fprintf_filtered (outfile, - " Full symtab was read (at 0x%lx by function at 0x%lx)\n", - (unsigned long) psymtab -> symtab, - (unsigned long) psymtab -> read_symtab); + " Full symtab was read (at "); + gdb_print_address (psymtab->symtab, outfile); + fprintf_filtered (outfile, " by function at "); + gdb_print_address ((PTR)psymtab->read_symtab, outfile); + fprintf_filtered (outfile, ")\n"); } - /* FIXME, we need to be able to print the relocation stuff. */ - /* This prints some garbage for anything but stabs right now. FIXME. */ - if (psymtab->section_offsets) - fprintf_filtered (outfile, - " Relocate symbols by 0x%lx, 0x%lx, 0x%lx, 0x%lx.\n", - (unsigned long) ANOFFSET (psymtab->section_offsets, 0), - (unsigned long) ANOFFSET (psymtab->section_offsets, 1), - (unsigned long) ANOFFSET (psymtab->section_offsets, 2), - (unsigned long) ANOFFSET (psymtab->section_offsets, 3)); + fprintf_filtered (outfile, " Relocate symbols by "); + for (i = 0; i < psymtab->objfile->num_sections; ++i) + { + if (i != 0) + fprintf_filtered (outfile, ", "); + wrap_here (" "); + print_address_numeric (ANOFFSET (psymtab->section_offsets, i), + 1, + outfile); + } + fprintf_filtered (outfile, "\n"); - fprintf_filtered (outfile, " Symbols cover text addresses 0x%lx-0x%lx\n", - (unsigned long) psymtab -> textlow, - (unsigned long) psymtab -> texthigh); + fprintf_filtered (outfile, " Symbols cover text addresses "); + print_address_numeric (psymtab->textlow, 1, outfile); + fprintf_filtered (outfile, "-"); + print_address_numeric (psymtab->texthigh, 1, outfile); + fprintf_filtered (outfile, "\n"); fprintf_filtered (outfile, " Depends on %d other partial symtabs.\n", psymtab -> number_of_dependencies); for (i = 0; i < psymtab -> number_of_dependencies; i++) { - fprintf_filtered (outfile, " %d 0x%lx %s\n", i, - (unsigned long) psymtab -> dependencies[i], + fprintf_filtered (outfile, " %d ", i); + gdb_print_address (psymtab -> dependencies[i], outfile); + fprintf_filtered (outfile, " %s\n", psymtab -> dependencies[i] -> filename); } if (psymtab -> n_global_syms > 0) @@ -329,7 +349,7 @@ static void dump_symtab (objfile, symtab, outfile) struct objfile *objfile; struct symtab *symtab; - FILE *outfile; + GDB_FILE *outfile; { register int i, j; int len, blen; @@ -338,22 +358,27 @@ dump_symtab (objfile, symtab, outfile) register struct block *b; int depth; - fprintf (outfile, "\nSymtab for file %s\n", symtab->filename); - fprintf (outfile, "Read from object file %s (%lx)\n", objfile->name, - (unsigned long) objfile); - fprintf (outfile, "Language: %s\n", language_str (symtab -> language)); - + fprintf_filtered (outfile, "\nSymtab for file %s\n", symtab->filename); + fprintf_filtered (outfile, "Read from object file %s (", objfile->name); + gdb_print_address (objfile, outfile); + fprintf_filtered (outfile, ")\n"); + fprintf_filtered (outfile, "Language: %s\n", language_str (symtab -> language)); + /* First print the line table. */ l = LINETABLE (symtab); - if (l) { - fprintf (outfile, "\nLine table:\n\n"); - len = l->nitems; - for (i = 0; i < len; i++) - fprintf (outfile, " line %ld at %lx\n", l->item[i].line, - (unsigned long) l->item[i].pc); - } + if (l) + { + fprintf_filtered (outfile, "\nLine table:\n\n"); + len = l->nitems; + for (i = 0; i < len; i++) + { + fprintf_filtered (outfile, " line %d at ", l->item[i].line); + print_address_numeric (l->item[i].pc, 1, outfile); + fprintf_filtered (outfile, "\n"); + } + } /* Now print the block info. */ - fprintf (outfile, "\nBlockvector:\n\n"); + fprintf_filtered (outfile, "\nBlockvector:\n\n"); bv = BLOCKVECTOR (symtab); len = BLOCKVECTOR_NBLOCKS (bv); for (i = 0; i < len; i++) @@ -361,25 +386,32 @@ dump_symtab (objfile, symtab, outfile) b = BLOCKVECTOR_BLOCK (bv, i); depth = block_depth (b) * 2; print_spaces (depth, outfile); - fprintf (outfile, "block #%03d (object 0x%lx) ", i, (unsigned long) b); - fprintf (outfile, "[0x%lx..0x%lx]", - (unsigned long) BLOCK_START (b), - (unsigned long) BLOCK_END (b)); + fprintf_filtered (outfile, "block #%03d (object ", i); + gdb_print_address (b, outfile); + fprintf_filtered (outfile, ") "); + fprintf_filtered (outfile, "["); + print_address_numeric (BLOCK_START (b), 1, outfile); + fprintf_filtered (outfile, ".."); + print_address_numeric (BLOCK_END (b), 1, outfile); + fprintf_filtered (outfile, "]"); if (BLOCK_SUPERBLOCK (b)) - fprintf (outfile, " (under 0x%lx)", - (unsigned long) BLOCK_SUPERBLOCK (b)); + { + fprintf_filtered (outfile, " (under "); + gdb_print_address (BLOCK_SUPERBLOCK (b), outfile); + fprintf_filtered (outfile, ")"); + } if (BLOCK_FUNCTION (b)) { - fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b))); + fprintf_filtered (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b))); if (SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b)) != NULL) { - fprintf (outfile, " %s", + fprintf_filtered (outfile, " %s", SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b))); } } if (BLOCK_GCC_COMPILED(b)) - fprintf (outfile, " gcc%d compiled", BLOCK_GCC_COMPILED(b)); - fputc ('\n', outfile); + fprintf_filtered (outfile, " gcc%d compiled", BLOCK_GCC_COMPILED(b)); + fprintf_filtered (outfile, "\n"); blen = BLOCK_NSYMS (b); for (j = 0; j < blen; j++) { @@ -391,7 +423,7 @@ dump_symtab (objfile, symtab, outfile) RETURN_MASK_ERROR); } } - fprintf (outfile, "\n"); + fprintf_filtered (outfile, "\n"); } void @@ -400,7 +432,7 @@ maintenance_print_symbols (args, from_tty) int from_tty; { char **argv; - FILE *outfile; + GDB_FILE *outfile; struct cleanup *cleanups; char *symname = NULL; char *filename = DEV_TTY; @@ -411,7 +443,8 @@ maintenance_print_symbols (args, from_tty) if (args == NULL) { - error ("print-symbols takes an output file name and optional symbol file name"); + error ("\ +Arguments missing: an output file name and an optional symbol file name"); } else if ((argv = buildargv (args)) == NULL) { @@ -432,7 +465,7 @@ maintenance_print_symbols (args, from_tty) filename = tilde_expand (filename); make_cleanup (free, filename); - outfile = fopen (filename, FOPEN_WT); + outfile = gdb_fopen (filename, FOPEN_WT); if (outfile == 0) perror_with_name (filename); make_cleanup (fclose, (char *) outfile); @@ -456,13 +489,14 @@ print_symbol (args) { struct symbol *symbol = ((struct print_symbol_args *)args)->symbol; int depth = ((struct print_symbol_args *)args)->depth; - FILE *outfile = ((struct print_symbol_args *)args)->outfile; + GDB_FILE *outfile = ((struct print_symbol_args *)args)->outfile; print_spaces (depth, outfile); if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE) { - fprintf (outfile, "label %s at 0x%lx\n", SYMBOL_SOURCE_NAME (symbol), - (unsigned long) SYMBOL_VALUE_ADDRESS (symbol)); + fprintf_filtered (outfile, "label %s at ", SYMBOL_SOURCE_NAME (symbol)); + print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1, outfile); + fprintf_filtered (outfile, "\n"); return 1; } if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE) @@ -473,7 +507,7 @@ print_symbol (args) } else { - fprintf (outfile, "%s %s = ", + fprintf_filtered (outfile, "%s %s = ", (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_ENUM ? "enum" : (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT @@ -481,12 +515,12 @@ print_symbol (args) SYMBOL_NAME (symbol)); LA_PRINT_TYPE (SYMBOL_TYPE (symbol), "", outfile, 1, depth); } - fprintf (outfile, ";\n"); + fprintf_filtered (outfile, ";\n"); } else { if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF) - fprintf (outfile, "typedef "); + fprintf_filtered (outfile, "typedef "); if (SYMBOL_TYPE (symbol)) { /* Print details of types, except for enums where it's clutter. */ @@ -494,72 +528,75 @@ print_symbol (args) outfile, TYPE_CODE (SYMBOL_TYPE (symbol)) != TYPE_CODE_ENUM, depth); - fprintf (outfile, "; "); + fprintf_filtered (outfile, "; "); } else - fprintf (outfile, "%s ", SYMBOL_SOURCE_NAME (symbol)); + fprintf_filtered (outfile, "%s ", SYMBOL_SOURCE_NAME (symbol)); switch (SYMBOL_CLASS (symbol)) { case LOC_CONST: - fprintf (outfile, "const %ld (0x%lx),", - SYMBOL_VALUE (symbol), - (unsigned long) SYMBOL_VALUE (symbol)); + fprintf_filtered (outfile, "const %ld (0x%lx),", + SYMBOL_VALUE (symbol), + SYMBOL_VALUE (symbol)); break; case LOC_CONST_BYTES: - fprintf (outfile, "const %u hex bytes:", + fprintf_filtered (outfile, "const %u hex bytes:", TYPE_LENGTH (SYMBOL_TYPE (symbol))); { unsigned i; for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (symbol)); i++) - fprintf (outfile, " %02x", + fprintf_filtered (outfile, " %02x", (unsigned)SYMBOL_VALUE_BYTES (symbol) [i]); - fprintf (outfile, ","); + fprintf_filtered (outfile, ","); } break; case LOC_STATIC: - fprintf (outfile, "static at 0x%lx,", - (unsigned long) SYMBOL_VALUE_ADDRESS (symbol)); + fprintf_filtered (outfile, "static at "); + print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1,outfile); + fprintf_filtered (outfile, ","); break; case LOC_REGISTER: - fprintf (outfile, "register %ld,", SYMBOL_VALUE (symbol)); + fprintf_filtered (outfile, "register %ld,", SYMBOL_VALUE (symbol)); break; case LOC_ARG: - fprintf (outfile, "arg at 0x%lx,", SYMBOL_VALUE (symbol)); + fprintf_filtered (outfile, "arg at offset 0x%lx,", + SYMBOL_VALUE (symbol)); break; case LOC_LOCAL_ARG: - fprintf (outfile, "arg at offset 0x%lx from fp,", + fprintf_filtered (outfile, "arg at offset 0x%lx from fp,", SYMBOL_VALUE (symbol)); break; case LOC_REF_ARG: - fprintf (outfile, "reference arg at 0x%lx,", SYMBOL_VALUE (symbol)); + fprintf_filtered (outfile, "reference arg at 0x%lx,", SYMBOL_VALUE (symbol)); break; case LOC_REGPARM: - fprintf (outfile, "parameter register %ld,", SYMBOL_VALUE (symbol)); + fprintf_filtered (outfile, "parameter register %ld,", SYMBOL_VALUE (symbol)); break; case LOC_REGPARM_ADDR: - fprintf (outfile, "address parameter register %ld,", SYMBOL_VALUE (symbol)); + fprintf_filtered (outfile, "address parameter register %ld,", SYMBOL_VALUE (symbol)); break; case LOC_LOCAL: - fprintf (outfile, "local at 0x%lx,", SYMBOL_VALUE (symbol)); + fprintf_filtered (outfile, "local at offset 0x%lx,", + SYMBOL_VALUE (symbol)); break; case LOC_BASEREG: - fprintf (outfile, "local at 0x%lx from register %d", + fprintf_filtered (outfile, "local at 0x%lx from register %d", SYMBOL_VALUE (symbol), SYMBOL_BASEREG (symbol)); break; case LOC_BASEREG_ARG: - fprintf (outfile, "arg at 0x%lx from register %d,", + fprintf_filtered (outfile, "arg at 0x%lx from register %d,", SYMBOL_VALUE (symbol), SYMBOL_BASEREG (symbol)); break; @@ -567,26 +604,31 @@ print_symbol (args) break; case LOC_LABEL: - fprintf (outfile, "label at 0x%lx", - (unsigned long) SYMBOL_VALUE_ADDRESS (symbol)); + fprintf_filtered (outfile, "label at "); + print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1, outfile); break; case LOC_BLOCK: - fprintf (outfile, "block (object 0x%lx) starting at 0x%lx,", - (unsigned long) SYMBOL_BLOCK_VALUE (symbol), - (unsigned long) BLOCK_START (SYMBOL_BLOCK_VALUE (symbol))); + fprintf_filtered (outfile, "block (object "); + gdb_print_address (SYMBOL_BLOCK_VALUE (symbol), outfile); + fprintf_filtered (outfile, ") starting at "); + print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)), + 1, + outfile); + fprintf_filtered (outfile, ","); break; case LOC_OPTIMIZED_OUT: - fprintf (outfile, "optimized out"); + fprintf_filtered (outfile, "optimized out"); break; default: - fprintf (outfile, "botched symbol class %x", SYMBOL_CLASS (symbol)); + fprintf_filtered (outfile, "botched symbol class %x", + SYMBOL_CLASS (symbol)); break; } } - fprintf (outfile, "\n"); + fprintf_filtered (outfile, "\n"); return 1; } @@ -596,7 +638,7 @@ maintenance_print_psymbols (args, from_tty) int from_tty; { char **argv; - FILE *outfile; + GDB_FILE *outfile; struct cleanup *cleanups; char *symname = NULL; char *filename = DEV_TTY; @@ -628,7 +670,7 @@ maintenance_print_psymbols (args, from_tty) filename = tilde_expand (filename); make_cleanup (free, filename); - outfile = fopen (filename, FOPEN_WT); + outfile = gdb_fopen (filename, FOPEN_WT); if (outfile == 0) perror_with_name (filename); make_cleanup (fclose, outfile); @@ -646,7 +688,7 @@ print_partial_symbol (p, count, what, outfile) struct partial_symbol *p; int count; char *what; - FILE *outfile; + GDB_FILE *outfile; { fprintf_filtered (outfile, " %s partial symbols:\n", what); @@ -728,6 +770,9 @@ print_partial_symbol (p, count, what, outfile) break; } fputs_filtered (", ", outfile); + /* FIXME-32x64: Need to use SYMBOL_VALUE_ADDRESS, etc.; this + could be 32 bits when some of the other fields in the union + are 64. */ fprintf_filtered (outfile, "0x%lx\n", SYMBOL_VALUE (p)); p++; } @@ -739,7 +784,7 @@ maintenance_print_msymbols (args, from_tty) int from_tty; { char **argv; - FILE *outfile; + GDB_FILE *outfile; struct cleanup *cleanups; char *filename = DEV_TTY; char *symname = NULL; @@ -770,7 +815,7 @@ maintenance_print_msymbols (args, from_tty) filename = tilde_expand (filename); make_cleanup (free, filename); - outfile = fopen (filename, FOPEN_WT); + outfile = gdb_fopen (filename, FOPEN_WT); if (outfile == 0) perror_with_name (filename); make_cleanup (fclose, outfile); @@ -799,6 +844,92 @@ maintenance_print_objfiles (ignore, from_tty) immediate_quit--; } +/* Check consistency of psymtabs and symtabs. */ + +void +maintenance_check_symtabs (ignore, from_tty) + char *ignore; + int from_tty; +{ + register struct symbol *sym; + register struct partial_symbol *psym; + register struct symtab *s = NULL; + register struct partial_symtab *ps; + struct blockvector *bv; + register struct objfile *objfile; + register struct block *b; + int length; + + ALL_PSYMTABS (objfile, ps) + { + s = PSYMTAB_TO_SYMTAB(ps); + if (s == NULL) + continue; + bv = BLOCKVECTOR (s); + b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + psym = ps->objfile->static_psymbols.list + ps->statics_offset; + length = ps->n_static_syms; + while (length--) + { + sym = lookup_block_symbol (b, SYMBOL_NAME (psym), + SYMBOL_NAMESPACE (psym)); + if (!sym) + { + printf_filtered ("Static symbol `"); + puts_filtered (SYMBOL_NAME (psym)); + printf_filtered ("' only found in "); + puts_filtered (ps->filename); + printf_filtered (" psymtab\n"); + } + psym++; + } + b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + psym = ps->objfile->global_psymbols.list + ps->globals_offset; + length = ps->n_global_syms; + while (length--) + { + sym = lookup_block_symbol (b, SYMBOL_NAME (psym), + SYMBOL_NAMESPACE (psym)); + if (!sym) + { + printf_filtered ("Global symbol `"); + puts_filtered (SYMBOL_NAME (psym)); + printf_filtered ("' only found in "); + puts_filtered (ps->filename); + printf_filtered (" psymtab\n"); + } + psym++; + } + if (ps->texthigh < ps->textlow) + { + printf_filtered ("Psymtab "); + puts_filtered (ps->filename); + printf_filtered (" covers bad range "); + print_address_numeric (ps->textlow, 1, stdout); + printf_filtered (" - "); + print_address_numeric (ps->texthigh, 1, stdout); + printf_filtered ("\n"); + continue; + } + if (ps->texthigh == 0) + continue; + if (ps->textlow < BLOCK_START (b) || ps->texthigh > BLOCK_END (b)) + { + printf_filtered ("Psymtab "); + puts_filtered (ps->filename); + printf_filtered (" covers "); + print_address_numeric (ps->textlow, 1, stdout); + printf_filtered (" - "); + print_address_numeric (ps->texthigh, 1, stdout); + printf_filtered (" but symtab covers only "); + print_address_numeric (BLOCK_START (b), 1, stdout); + printf_filtered (" - "); + print_address_numeric (BLOCK_END (b), 1, stdout); + printf_filtered ("\n"); + } + } +} + /* Return the nexting depth of a block within other blocks in its symtab. */ diff --git a/gnu/usr.bin/gdb/gdb/symtab.c b/gnu/usr.bin/gdb/gdb/symtab.c index 0d0255c73175..e08807c43e3a 100644 --- a/gnu/usr.bin/gdb/gdb/symtab.c +++ b/gnu/usr.bin/gdb/gdb/symtab.c @@ -1,6 +1,6 @@ /* Symbol table lookup for the GNU debugger, GDB. - Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992 - Free Software Foundation, Inc. + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -35,7 +35,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "demangle.h" #include -#include #include #include @@ -73,7 +72,7 @@ static void sources_info PARAMS ((char *, int)); static void -list_symbols PARAMS ((char *, int, int)); +list_symbols PARAMS ((char *, int, int, int)); static void output_source_filename PARAMS ((char *, int *)); @@ -111,8 +110,8 @@ void cplusplus_hint (name) char *name; { - printf ("Hint: try '%s or '%s\n", name, name); - printf ("(Note leading single quote.)\n"); + printf_filtered ("Hint: try '%s or '%s\n", name, name); + printf_filtered ("(Note leading single quote.)\n"); } /* Check for a symtab of a specific name; first in symtabs, then in @@ -188,11 +187,17 @@ lookup_symtab (name) char *name; { register struct symtab *s; +#if 0 register char *copy; +#endif s = lookup_symtab_1 (name); if (s) return s; +#if 0 + /* This screws c-exp.y:yylex if there is both a type "tree" and a symtab + "tree.c". */ + /* If name not found as specified, see if adding ".c" helps. */ /* Why is this? Is it just a user convenience? (If so, it's pretty questionable in the presence of C++, FORTRAN, etc.). It's not in @@ -203,6 +208,7 @@ lookup_symtab (name) strcat (copy, ".c"); s = lookup_symtab_1 (copy); if (s) return s; +#endif /* 0 */ /* We didn't find anything; die. */ return 0; @@ -260,6 +266,11 @@ gdb_mangle_name (type, i, j) char *field_name = TYPE_FN_FIELDLIST_NAME (type, i); char *physname = TYPE_FN_FIELD_PHYSNAME (f, j); char *newname = type_name_no_tag (type); + + /* Does the form of physname indicate that it is the full mangled name + of a constructor (not just the args)? */ + int is_full_physname_constructor; + int is_constructor; int is_destructor = DESTRUCTOR_PREFIX_P (physname); /* Need a new type prefix. */ @@ -267,19 +278,20 @@ gdb_mangle_name (type, i, j) char *volatile_prefix = method->is_volatile ? "V" : ""; char buf[20]; int len = (newname == NULL ? 0 : strlen (newname)); - char *opname; - is_constructor = newname && STREQ(field_name, newname); - if (!is_constructor) - is_constructor = (physname[0]=='_' && physname[1]=='_' && - (isdigit(physname[2]) || physname[2]=='Q' || physname[2]=='t')); - if (!is_constructor) - is_constructor = (strncmp(physname, "__ct", 4) == 0); + is_full_physname_constructor = + ((physname[0]=='_' && physname[1]=='_' && + (isdigit(physname[2]) || physname[2]=='Q' || physname[2]=='t')) + || (strncmp(physname, "__ct", 4) == 0)); + + is_constructor = + is_full_physname_constructor || (newname && STREQ(field_name, newname)); + if (!is_destructor) is_destructor = (strncmp(physname, "__dt", 4) == 0); #ifndef GCC_MANGLE_BUG - if (is_destructor) + if (is_destructor || is_full_physname_constructor) { mangled_name = (char*) xmalloc(strlen(physname)+1); strcpy(mangled_name, physname); @@ -348,6 +360,7 @@ gdb_mangle_name (type, i, j) work with the normal mechanisms. */ if (OPNAME_PREFIX_P (field_name)) { + char *opname; opname = cplus_mangle_opname (field_name + 3, 0); if (opname == NULL) { @@ -413,6 +426,21 @@ find_pc_psymbol (psymtab, pc) best_pc = psymtab->textlow - 1; + /* Search the global symbols as well as the static symbols, so that + find_pc_partial_function doesn't use a minimal symbol and thus + cache a bad endaddr. */ + for (p = psymtab->objfile->global_psymbols.list + psymtab->globals_offset; + (p - (psymtab->objfile->global_psymbols.list + psymtab->globals_offset) + < psymtab->n_global_syms); + p++) + if (SYMBOL_NAMESPACE (p) == VAR_NAMESPACE + && SYMBOL_CLASS (p) == LOC_BLOCK + && pc >= SYMBOL_VALUE_ADDRESS (p) + && SYMBOL_VALUE_ADDRESS (p) > best_pc) + { + best_pc = SYMBOL_VALUE_ADDRESS (p); + best = p; + } for (p = psymtab->objfile->static_psymbols.list + psymtab->statics_offset; (p - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset) < psymtab->n_static_syms); @@ -442,6 +470,16 @@ find_pc_psymbol (psymtab, pc) BLOCK_FOUND is set to the block in which NAME is found (in the case of a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */ +/* This function has a bunch of loops in it and it would seem to be + attractive to put in some QUIT's (though I'm not really sure + whether it can run long enough to be really important). But there + are a few calls for which it would appear to be bad news to quit + out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c, and + nindy_frame_chain_valid in nindy-tdep.c. (Note that there is C++ + code below which can error(), but that probably doesn't affect + these calls since they are looking for a known variable and thus + can probably assume it will never hit the C++ code). */ + struct symbol * lookup_symbol (name, block, namespace, is_a_field_of_this, symtab) const char *name; @@ -726,7 +764,8 @@ lookup_partial_symbol (pst, name, global, namespace) while (top > bottom) { center = bottom + (top - bottom) / 2; - assert (center < top); + if (!(center < top)) + abort (); if (!do_linear_search && SYMBOL_LANGUAGE (center) == language_cplus) { do_linear_search = 1; @@ -740,7 +779,8 @@ lookup_partial_symbol (pst, name, global, namespace) bottom = center + 1; } } - assert (top == bottom); + if (!(top == bottom)) + abort (); while (STREQ (SYMBOL_NAME (top), name)) { if (SYMBOL_NAMESPACE (top) == namespace) @@ -992,6 +1032,7 @@ find_pc_symtab (pc) /* Might want to error() here (in case symtab is corrupt and will cause a core dump), but maybe we can successfully continue, so let's not. */ + /* FIXME-32x64: assumes pc fits in a long */ warning ("\ (Internal error: pc 0x%lx in read in psymtab, but not in symtab.)\n", (unsigned long) pc); @@ -999,6 +1040,86 @@ find_pc_symtab (pc) } return (s); } + +#if 0 + +/* Find the closest symbol value (of any sort -- function or variable) + for a given address value. Slow but complete. (currently unused, + mainly because it is too slow. We could fix it if each symtab and + psymtab had contained in it the addresses ranges of each of its + sections, which also would be required to make things like "info + line *0x2345" cause psymtabs to be converted to symtabs). */ + +struct symbol * +find_addr_symbol (addr, symtabp, symaddrp) + CORE_ADDR addr; + struct symtab **symtabp; + CORE_ADDR *symaddrp; +{ + struct symtab *symtab, *best_symtab; + struct objfile *objfile; + register int bot, top; + register struct symbol *sym; + register CORE_ADDR sym_addr; + struct block *block; + int blocknum; + + /* Info on best symbol seen so far */ + + register CORE_ADDR best_sym_addr = 0; + struct symbol *best_sym = 0; + + /* FIXME -- we should pull in all the psymtabs, too! */ + ALL_SYMTABS (objfile, symtab) + { + /* Search the global and static blocks in this symtab for + the closest symbol-address to the desired address. */ + + for (blocknum = GLOBAL_BLOCK; blocknum <= STATIC_BLOCK; blocknum++) + { + QUIT; + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), blocknum); + top = BLOCK_NSYMS (block); + for (bot = 0; bot < top; bot++) + { + sym = BLOCK_SYM (block, bot); + switch (SYMBOL_CLASS (sym)) + { + case LOC_STATIC: + case LOC_LABEL: + sym_addr = SYMBOL_VALUE_ADDRESS (sym); + break; + + case LOC_BLOCK: + sym_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); + break; + + default: + continue; + } + + if (sym_addr <= addr) + if (sym_addr > best_sym_addr) + { + /* Quit if we found an exact match. */ + best_sym = sym; + best_sym_addr = sym_addr; + best_symtab = symtab; + if (sym_addr == addr) + goto done; + } + } + } + } + + done: + if (symtabp) + *symtabp = best_symtab; + if (symaddrp) + *symaddrp = best_sym_addr; + return best_sym; +} +#endif /* 0 */ /* Find the source file and line number for a given PC value. Return a structure containing a symtab pointer, a line number, @@ -1280,37 +1401,41 @@ find_line_pc (symtab, line) Returns 0 if could not find the specified line. */ int -find_line_pc_range (symtab, thisline, startptr, endptr) - struct symtab *symtab; - int thisline; +find_line_pc_range (sal, startptr, endptr) + struct symtab_and_line sal; CORE_ADDR *startptr, *endptr; { - struct linetable *l; - int ind; - int exact_match; /* did we get an exact linenumber match */ + CORE_ADDR startaddr; + struct symtab_and_line found_sal; - if (symtab == 0) + startaddr = sal.pc; + if (startaddr == 0) + { + startaddr = find_line_pc (sal.symtab, sal.line); + } + if (startaddr == 0) return 0; - if (find_line_symtab (symtab, thisline, &l, &ind, &exact_match)) - { - *startptr = l->item[ind].pc; - /* If we have not seen an entry for the specified line, - assume that means the specified line has zero bytes. */ - if (!exact_match || ind == l->nitems-1) - *endptr = *startptr; - else - /* Perhaps the following entry is for the following line. - It's worth a try. */ - if (ind+1 < l->nitems - && l->item[ind+1].line == thisline + 1) - *endptr = l->item[ind+1].pc; - else - *endptr = find_line_pc (symtab, thisline+1); - return 1; - } + /* This whole function is based on address. For example, if line 10 has + two parts, one from 0x100 to 0x200 and one from 0x300 to 0x400, then + "info line *0x123" should say the line goes from 0x100 to 0x200 + and "info line *0x355" should say the line goes from 0x300 to 0x400. + This also insures that we never give a range like "starts at 0x134 + and ends at 0x12c". */ - return 0; + found_sal = find_pc_line (startaddr, 0); + if (found_sal.line != sal.line) + { + /* The specified line (sal) has zero bytes. */ + *startptr = found_sal.pc; + *endptr = found_sal.pc; + } + else + { + *startptr = found_sal.pc; + *endptr = found_sal.end; + } + return 1; } /* Given a line table and a line number, return the index into the line @@ -1376,6 +1501,51 @@ find_pc_line_pc_range (pc, startptr, endptr) *endptr = sal.end; return sal.symtab != 0; } + +/* Given a function symbol SYM, find the symtab and line for the start + of the function. + If the argument FUNFIRSTLINE is nonzero, we want the first line + of real code inside the function. */ + +static struct symtab_and_line +find_function_start_sal PARAMS ((struct symbol *sym, int)); + +static struct symtab_and_line +find_function_start_sal (sym, funfirstline) + struct symbol *sym; + int funfirstline; +{ + CORE_ADDR pc; + struct symtab_and_line sal; + + pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); + if (funfirstline) + { + pc += FUNCTION_START_OFFSET; + SKIP_PROLOGUE (pc); + } + sal = find_pc_line (pc, 0); + +#ifdef PROLOGUE_FIRSTLINE_OVERLAP + /* Convex: no need to suppress code on first line, if any */ + sal.pc = pc; +#else + /* Check if SKIP_PROLOGUE left us in mid-line, and the next + line is still part of the same function. */ + if (sal.pc != pc + && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= sal.end + && sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym))) + { + /* First pc of next line */ + pc = sal.end; + /* Recalculate the line number (might not be N+1). */ + sal = find_pc_line (pc, 0); + } + sal.pc = pc; +#endif + + return sal; +} /* If P is of the form "operator[ \t]+..." where `...' is some legitimate operator text, return a pointer to the @@ -1500,8 +1670,18 @@ find_methods (t, name, sym_arr) { int field_counter; struct fn_field *f = TYPE_FN_FIELDLIST1 (t, method_counter); - char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter); + char dem_opname[64]; + + if (strncmp(method_name, "__", 2)==0 || + strncmp(method_name, "op", 2)==0 || + strncmp(method_name, "type", 4)==0 ) + { + if (cplus_demangle_opname(method_name, dem_opname, DMGL_ANSI)) + method_name = dem_opname; + else if (cplus_demangle_opname(method_name, dem_opname, 0)) + method_name = dem_opname; + } if (STREQ (name, method_name)) /* Find all the fields with that name. */ for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1; @@ -1531,10 +1711,11 @@ find_methods (t, name, sym_arr) if (sym_arr[i1]) i1++; else { - fputs_filtered("(Cannot find method ", stdout); - fprintf_symbol_filtered (stdout, phys_name, - language_cplus, DMGL_PARAMS); - fputs_filtered(" - possibly inlined.)\n", stdout); + fputs_filtered("(Cannot find method ", gdb_stdout); + fprintf_symbol_filtered (gdb_stdout, phys_name, + language_cplus, + DMGL_PARAMS | DMGL_ANSI); + fputs_filtered(" - possibly inlined.)\n", gdb_stdout); } } } @@ -1633,6 +1814,11 @@ build_canonical_line_spec (sal, symname, canonical) if no file is validly specified. Callers must check that. Also, the line number returned may be invalid. */ +/* We allow single quotes in various places. This is a hideous + kludge, which exists because the completer can't yet deal with the + lack of single quotes. FIXME: write a linespec_completer which we + can use as appropriate instead of make_symbol_completion_list. */ + struct symtabs_and_lines decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) char **argptr; @@ -1673,7 +1859,10 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) struct symtab_and_line val; #endif register char *p, *p1; - char *q, *q1; + char *q, *pp; +#if 0 + char *q1; +#endif register struct symtab *s; register struct symbol *sym; @@ -1685,7 +1874,7 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) char *copy; struct symbol *sym_class; int i1; - int is_quoted; + int is_quoted, has_parens; struct symbol **sym_arr; struct type *t; char *saved_arg = *argptr; @@ -1720,19 +1909,30 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */ s = NULL; - is_quoted = (strchr (gdb_completer_quote_characters, **argptr) != NULL); + is_quoted = (strchr(gdb_completer_quote_characters, **argptr) != NULL); + has_parens = (( pp = strchr(*argptr, '(')) != NULL && + (pp = strchr(pp, ')')) != NULL); for (p = *argptr; *p; p++) { + if (p[0] == '<') + { + while(++p && *p != '>'); + if (!p) + { + error ("non-matching '<' and '>' in command"); + } + } if (p[0] == ':' || p[0] == ' ' || p[0] == '\t') break; } while (p[0] == ' ' || p[0] == '\t') p++; - if ((p[0] == ':') && !is_quoted) + if ((p[0] == ':') && !has_parens) { /* C++ */ + if (is_quoted) *argptr = *argptr+1; if (p[1] ==':') { /* Extract the class name. */ @@ -1755,11 +1955,19 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) || TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_UNION)) { /* Arg token is not digits => try it as a function name - Find the next token (everything up to end or next whitespace). */ - p = *argptr; - while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p !=':') p++; + Find the next token(everything up to end or next blank). */ + if (strchr(gdb_completer_quote_characters, **argptr) != NULL) + { + p = skip_quoted(*argptr); + *argptr = *argptr + 1; + } + else + { + p = *argptr; + while (*p && *p!=' ' && *p!='\t' && *p!=',' && *p!=':') p++; + } +/* q = operator_chars (*argptr, &q1); - if (q1 - q) { char *opname; @@ -1769,7 +1977,8 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) opname = cplus_mangle_opname (tmp, DMGL_ANSI); if (opname == NULL) { - warning ("no mangling for \"%s\"", tmp); + error_begin (); + printf_filtered ("no mangling for \"%s\"\n", tmp); cplusplus_hint (saved_arg); return_to_top_level (RETURN_ERROR); } @@ -1778,10 +1987,13 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) p = q1; } else +*/ { - copy = (char *) alloca (p - *argptr + 1 + (q1 - q)); + copy = (char *) alloca (p - *argptr + 1 ); memcpy (copy, *argptr, p - *argptr); copy[p - *argptr] = '\0'; + if (strchr(gdb_completer_quote_characters, copy[p-*argptr-1]) != NULL) + copy[p - *argptr -1] = '\0'; } /* no line number may be specified */ @@ -1822,14 +2034,10 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) { - /* Arg is the name of a function */ - pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET; - if (funfirstline) - SKIP_PROLOGUE (pc); values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line)); values.nelts = 1; - values.sals[0] = find_pc_line (pc, 0); - values.sals[0].pc = (values.sals[0].end && values.sals[0].pc != pc) ? values.sals[0].end : pc; + values.sals[0] = find_function_start_sal (sym, + funfirstline); } else { @@ -1855,21 +2063,25 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) } else tmp = copy; + error_begin (); if (tmp[0] == '~') - warning ("the class `%s' does not have destructor defined", - SYMBOL_SOURCE_NAME(sym_class)); + printf_filtered + ("the class `%s' does not have destructor defined\n", + SYMBOL_SOURCE_NAME(sym_class)); else - warning ("the class %s does not have any method named %s", - SYMBOL_SOURCE_NAME(sym_class), tmp); + printf_filtered + ("the class %s does not have any method named %s\n", + SYMBOL_SOURCE_NAME(sym_class), tmp); cplusplus_hint (saved_arg); return_to_top_level (RETURN_ERROR); } } else { + error_begin (); /* The quotes are important if copy is empty. */ - warning ("can't find class, struct, or union named \"%s\"", - copy); + printf_filtered + ("can't find class, struct, or union named \"%s\"\n", copy); cplusplus_hint (saved_arg); return_to_top_level (RETURN_ERROR); } @@ -1904,12 +2116,12 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) /* Check whether arg is all digits (and sign) */ - p = *argptr; - if (*p == '-' || *p == '+') p++; - while (*p >= '0' && *p <= '9') - p++; + q = *argptr; + if (*q == '-' || *q == '+') q++; + while (*q >= '0' && *q <= '9') + q++; - if (p != *argptr && (*p == 0 || *p == ' ' || *p == '\t' || *p == ',')) + if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ',')) { /* We found a token consisting of all digits -- at least one digit. */ enum sign {none, plus, minus} sign = none; @@ -1937,13 +2149,13 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) switch (sign) { case plus: - if (p == *argptr) + if (q == *argptr) val.line = 5; if (s == 0) val.line = default_line + val.line; break; case minus: - if (p == *argptr) + if (q == *argptr) val.line = 15; if (s == 0) val.line = default_line - val.line; @@ -1954,8 +2166,8 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) break; /* No need to adjust val.line. */ } - while (*p == ' ' || *p == '\t') p++; - *argptr = p; + while (*q == ' ' || *q == '\t') q++; + *argptr = q; if (s == 0) s = default_symtab; val.symtab = s; @@ -1971,13 +2183,26 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) /* Arg token is not digits => try it as a variable name Find the next token (everything up to end or next whitespace). */ - p = skip_quoted (*argptr); - if (is_quoted && p[-1] != '\'') - error ("Unmatched single quote."); + if (is_quoted) + { + p = skip_quoted (*argptr); + if (p[-1] != '\'') + error ("Unmatched single quote."); + } + else if (has_parens) + { + p = pp+1; + } + else + { + p = skip_quoted(*argptr); + } + copy = (char *) alloca (p - *argptr + 1); memcpy (copy, *argptr, p - *argptr); copy[p - *argptr] = '\0'; - if ((copy[0] == copy [p - *argptr - 1]) + if (p != *argptr + && (copy[0] == copy [p - *argptr - 1]) && strchr (gdb_completer_quote_characters, copy[0]) != NULL) { copy [p - *argptr - 1] = '\0'; @@ -1999,39 +2224,16 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) if (SYMBOL_CLASS (sym) == LOC_BLOCK) { /* Arg is the name of a function */ - pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET; - if (funfirstline) - SKIP_PROLOGUE (pc); - val = find_pc_line (pc, 0); -#ifdef PROLOGUE_FIRSTLINE_OVERLAP - /* Convex: no need to suppress code on first line, if any */ - val.pc = pc; -#else - /* Check if SKIP_PROLOGUE left us in mid-line, and the next - line is still part of the same function. */ - if (val.pc != pc - && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= val.end - && val.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym))) - { - /* First pc of next line */ - pc = val.end; - /* Recalculate the line number (might not be N+1). */ - val = find_pc_line (pc, 0); - } - val.pc = pc; -#endif values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line)); - values.sals[0] = val; + values.sals[0] = find_function_start_sal (sym, funfirstline); values.nelts = 1; - - /* I think this is always the same as the line that - we calculate above, but the general principle is - "trust the symbols more than stuff like - SKIP_PROLOGUE". */ - if (SYMBOL_LINE (sym) != 0) - values.sals[0].line = SYMBOL_LINE (sym); - /* We might need a canonical line spec if it is a static function. */ + /* Don't use the SYMBOL_LINE; if used at all it points to + the line containing the parameters or thereabouts, not + the first line of code. */ + + /* We might need a canonical line spec if it is a static + function. */ if (s == 0) { struct blockvector *bv = BLOCKVECTOR (sym_symtab); @@ -2065,9 +2267,12 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) { val.symtab = 0; val.line = 0; - val.pc = SYMBOL_VALUE_ADDRESS (msymbol) + FUNCTION_START_OFFSET; + val.pc = SYMBOL_VALUE_ADDRESS (msymbol); if (funfirstline) - SKIP_PROLOGUE (val.pc); + { + val.pc += FUNCTION_START_OFFSET; + SKIP_PROLOGUE (val.pc); + } values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line)); values.sals[0] = val; values.nelts = 1; @@ -2111,7 +2316,6 @@ decode_line_2 (sym_arr, nelts, funfirstline, canonical) char ***canonical; { struct symtabs_and_lines values, return_values; - register CORE_ADDR pc; char *args, *arg1; int i; char *prompt; @@ -2132,23 +2336,20 @@ decode_line_2 (sym_arr, nelts, funfirstline, canonical) } i = 0; - printf("[0] cancel\n[1] all\n"); + printf_unfiltered("[0] cancel\n[1] all\n"); while (i < nelts) { if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK) { - /* Arg is the name of a function */ - pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym_arr[i])) - + FUNCTION_START_OFFSET; - if (funfirstline) - SKIP_PROLOGUE (pc); - values.sals[i] = find_pc_line (pc, 0); - values.sals[i].pc = (values.sals[i].end && values.sals[i].pc != pc) ? - values.sals[i].end : pc; - printf("[%d] %s at %s:%d\n", (i+2), SYMBOL_SOURCE_NAME (sym_arr[i]), - values.sals[i].symtab->filename, values.sals[i].line); + values.sals[i] = find_function_start_sal (sym_arr[i], funfirstline); + printf_unfiltered ("[%d] %s at %s:%d\n", + (i+2), + SYMBOL_SOURCE_NAME (sym_arr[i]), + values.sals[i].symtab->filename, + values.sals[i].line); } - else printf ("?HERE\n"); + else + printf_unfiltered ("?HERE\n"); i++; } @@ -2156,10 +2357,10 @@ decode_line_2 (sym_arr, nelts, funfirstline, canonical) { prompt = ">"; } - printf("%s ",prompt); - fflush(stdout); + printf_unfiltered("%s ",prompt); + gdb_flush(gdb_stdout); - args = command_line_input ((char *) NULL, 0); + args = command_line_input ((char *) NULL, 0, "overload-choice"); if (args == 0 || *args == 0) error_no_arg ("one or more choice numbers"); @@ -2200,7 +2401,7 @@ decode_line_2 (sym_arr, nelts, funfirstline, canonical) if (num > nelts + 2) { - printf ("No choice number %d.\n", num); + printf_unfiltered ("No choice number %d.\n", num); } else { @@ -2218,7 +2419,7 @@ decode_line_2 (sym_arr, nelts, funfirstline, canonical) } else { - printf ("duplicate request for %d ignored.\n", num); + printf_unfiltered ("duplicate request for %d ignored.\n", num); } } @@ -2287,7 +2488,7 @@ output_source_filename (name, first) } wrap_here (""); - fputs_filtered (name, stdout); + fputs_filtered (name, gdb_stdout); } static void @@ -2338,10 +2539,11 @@ sources_info (ignore, from_tty) we find. */ static void -list_symbols (regexp, class, bpt) +list_symbols (regexp, class, bpt, from_tty) char *regexp; int class; int bpt; + int from_tty; { register struct symtab *s; register struct partial_symtab *ps; @@ -2361,9 +2563,15 @@ list_symbols (regexp, class, bpt) static enum minimal_symbol_type types[] = {mst_data, mst_text, mst_abs, mst_unknown}; static enum minimal_symbol_type types2[] - = {mst_bss, mst_text, mst_abs, mst_unknown}; + = {mst_bss, mst_file_text, mst_abs, mst_unknown}; + static enum minimal_symbol_type types3[] + = {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown}; + static enum minimal_symbol_type types4[] + = {mst_file_bss, mst_text, mst_abs, mst_unknown}; enum minimal_symbol_type ourtype = types[class]; enum minimal_symbol_type ourtype2 = types2[class]; + enum minimal_symbol_type ourtype3 = types3[class]; + enum minimal_symbol_type ourtype4 = types4[class]; if (regexp != NULL) { @@ -2464,7 +2672,9 @@ list_symbols (regexp, class, bpt) ALL_MSYMBOLS (objfile, msymbol) { if (MSYMBOL_TYPE (msymbol) == ourtype || - MSYMBOL_TYPE (msymbol) == ourtype2) + MSYMBOL_TYPE (msymbol) == ourtype2 || + MSYMBOL_TYPE (msymbol) == ourtype3 || + MSYMBOL_TYPE (msymbol) == ourtype4) { if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol)) { @@ -2523,22 +2733,26 @@ list_symbols (regexp, class, bpt) same name but in different files. In order to set breakpoints on all of them, we must give both the file name and the function name to - break_command. */ + break_command. + Quoting the symbol name gets rid of problems + with mangled symbol names that contain + CPLUS_MARKER characters. */ char *string = (char *) alloca (strlen (s->filename) + strlen (SYMBOL_NAME(sym)) - + 2); + + 4); strcpy (string, s->filename); - strcat (string, ":"); + strcat (string, ":'"); strcat (string, SYMBOL_NAME(sym)); - break_command (string, 0); + strcat (string, "'"); + break_command (string, from_tty); } } else if (!found_in_file) { - fputs_filtered ("\nFile ", stdout); - fputs_filtered (s->filename, stdout); - fputs_filtered (":\n", stdout); + fputs_filtered ("\nFile ", gdb_stdout); + fputs_filtered (s->filename, gdb_stdout); + fputs_filtered (":\n", gdb_stdout); } found_in_file = 1; @@ -2548,7 +2762,7 @@ list_symbols (regexp, class, bpt) /* Typedef that is not a C++ class */ if (class == 2 && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE) - c_typedef_print (SYMBOL_TYPE(sym), sym, stdout); + c_typedef_print (SYMBOL_TYPE(sym), sym, gdb_stdout); /* variable, func, or typedef-that-is-c++-class */ else if (class < 2 || (class == 2 && @@ -2557,7 +2771,7 @@ list_symbols (regexp, class, bpt) type_print (SYMBOL_TYPE (sym), (SYMBOL_CLASS (sym) == LOC_TYPEDEF ? "" : SYMBOL_SOURCE_NAME (sym)), - stdout, 0); + gdb_stdout, 0); printf_filtered (";\n"); } @@ -2566,12 +2780,12 @@ list_symbols (regexp, class, bpt) # if 0 /* FIXME, why is this zapped out? */ char buf[1024]; c_type_print_base (TYPE_FN_FIELD_TYPE(t, i), - stdout, 0, 0); + gdb_stdout, 0, 0); c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE(t, i), - stdout, 0); + gdb_stdout, 0); sprintf (buf, " %s::", type_name_no_tag (t)); cp_type_print_method_args (TYPE_FN_FIELD_ARGS (t, i), - buf, name, stdout); + buf, name, gdb_stdout); # endif } } @@ -2589,7 +2803,9 @@ list_symbols (regexp, class, bpt) ALL_MSYMBOLS (objfile, msymbol) { if (MSYMBOL_TYPE (msymbol) == ourtype || - MSYMBOL_TYPE (msymbol) == ourtype2) + MSYMBOL_TYPE (msymbol) == ourtype2 || + MSYMBOL_TYPE (msymbol) == ourtype3 || + MSYMBOL_TYPE (msymbol) == ourtype4) { if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol)) { @@ -2623,7 +2839,7 @@ variables_info (regexp, from_tty) char *regexp; int from_tty; { - list_symbols (regexp, 0, 0); + list_symbols (regexp, 0, 0, from_tty); } static void @@ -2631,7 +2847,7 @@ functions_info (regexp, from_tty) char *regexp; int from_tty; { - list_symbols (regexp, 1, 0); + list_symbols (regexp, 1, 0, from_tty); } static void @@ -2639,7 +2855,7 @@ types_info (regexp, from_tty) char *regexp; int from_tty; { - list_symbols (regexp, 2, 0); + list_symbols (regexp, 2, 0, from_tty); } #if 0 @@ -2648,7 +2864,7 @@ static void methods_info (regexp) char *regexp; { - list_symbols (regexp, 3, 0); + list_symbols (regexp, 3, 0, from_tty); } #endif /* 0 */ @@ -2658,7 +2874,7 @@ rbreak_command (regexp, from_tty) char *regexp; int from_tty; { - list_symbols (regexp, 1, 1); + list_symbols (regexp, 1, 1, from_tty); } diff --git a/gnu/usr.bin/gdb/gdb/symtab.h b/gnu/usr.bin/gdb/gdb/symtab.h index 9570b393adbf..058b9e7c01f4 100644 --- a/gnu/usr.bin/gdb/gdb/symtab.h +++ b/gnu/usr.bin/gdb/gdb/symtab.h @@ -1,5 +1,5 @@ /* Symbol table definitions for GDB. - Copyright (C) 1986, 1989, 1991, 1992 Free Software Foundation, Inc. + Copyright 1986, 1989, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -26,10 +26,24 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free +/* Don't do this; it means that if some .o's are compiled with GNU C + and some are not (easy to do accidentally the way we configure + things; also it is a pain to have to "make clean" every time you + want to switch compilers), then GDB dies a horrible death. */ +/* GNU C supports enums that are bitfields. Some compilers don't. */ +#if 0 && defined(__GNUC__) && !defined(BYTE_BITFIELD) +#define BYTE_BITFIELD :8; +#else +#define BYTE_BITFIELD /*nothing*/ +#endif + /* Define a structure for the information that is common to all symbol types, including minimal symbols, partial symbols, and full symbols. In a multilanguage environment, some language specific information may need to - be recorded along with each symbol. */ + be recorded along with each symbol. + + These fields are ordered to encourage good packing, since we frequently + have tens or hundreds of thousands of these. */ struct general_symbol_info { @@ -47,7 +61,10 @@ struct general_symbol_info union { - long value; + /* The fact that this is a long not a LONGEST mainly limits the + range of a LOC_CONST. Since LOC_CONST_BYTES exists, I'm not + sure that is a big deal. */ + long ivalue; struct block *block; @@ -61,12 +78,6 @@ struct general_symbol_info } value; - /* Record the source code language that applies to this symbol. - This is used to select one of the fields from the language specific - union below. */ - - enum language language; - /* Since one and only one language can apply, wrap the language specific information inside a union. */ @@ -82,6 +93,12 @@ struct general_symbol_info } chill_specific; } language_specific; + /* Record the source code language that applies to this symbol. + This is used to select one of the fields from the language specific + union above. */ + + enum language language BYTE_BITFIELD; + /* Which section is this symbol in? This is an index into section_offsets for this objfile. Negative means that the symbol does not get relocated relative to a section. @@ -89,11 +106,11 @@ struct general_symbol_info expect all symbol-reading code to set it correctly (the ELF code also tries to set it correctly). */ - int section; + short section; }; #define SYMBOL_NAME(symbol) (symbol)->ginfo.name -#define SYMBOL_VALUE(symbol) (symbol)->ginfo.value.value +#define SYMBOL_VALUE(symbol) (symbol)->ginfo.value.ivalue #define SYMBOL_VALUE_ADDRESS(symbol) (symbol)->ginfo.value.address #define SYMBOL_VALUE_BYTES(symbol) (symbol)->ginfo.value.bytes #define SYMBOL_BLOCK_VALUE(symbol) (symbol)->ginfo.value.block @@ -104,9 +121,6 @@ struct general_symbol_info #define SYMBOL_CPLUS_DEMANGLED_NAME(symbol) \ (symbol)->ginfo.language_specific.cplus_specific.demangled_name - -extern int demangle; /* We reference it, so go ahead and declare it. */ - /* Macro that initializes the language dependent portion of a symbol depending upon the language for the symbol. */ @@ -215,10 +229,6 @@ extern int demangle; /* We reference it, so go ahead and declare it. */ ? SYMBOL_DEMANGLED_NAME (symbol) \ : SYMBOL_NAME (symbol)) -/* From utils.c. */ -extern int demangle; -extern int asm_demangle; - /* Macro that tests a symbol for a match against a specified name string. First test the unencoded name, then looks for and test a C++ encoded name if it exists. Note that whitespace is ignored while attempting to @@ -289,12 +299,21 @@ struct minimal_symbol mst_data, /* Generally initialized data */ mst_bss, /* Generally uninitialized data */ mst_abs, /* Generally absolute (nonrelocatable) */ + /* GDB uses mst_solib_trampoline for the start address of a shared + library trampoline entry. Breakpoints for shared library functions + are put there if the shared library is not yet loaded. + After the shared library is loaded, lookup_minimal_symbol will + prefer the minimal symbol from the shared library (usually + a mst_text symbol) over the mst_solib_trampoline symbol, and the + breakpoints will be moved to their true address in the shared + library via breakpoint_re_set. */ + mst_solib_trampoline, /* Shared library trampoline code */ /* For the mst_file* types, the names are only guaranteed to be unique within a given .o file. */ mst_file_text, /* Static version of mst_text */ mst_file_data, /* Static version of mst_data */ mst_file_bss /* Static version of mst_bss */ - } type; + } type BYTE_BITFIELD; }; @@ -548,18 +567,18 @@ struct symbol struct general_symbol_info ginfo; - /* Name space code. */ - - enum namespace namespace; - - /* Address class */ - - enum address_class class; - /* Data type of value */ struct type *type; + /* Name space code. */ + + enum namespace namespace BYTE_BITFIELD; + + /* Address class */ + + enum address_class class BYTE_BITFIELD; + /* Line number of definition. FIXME: Should we really make the assumption that nobody will try to debug files longer than 64K lines? What about machine generated programs? */ @@ -575,7 +594,6 @@ struct symbol short basereg; } aux_value; - }; #define SYMBOL_NAMESPACE(symbol) (symbol)->namespace @@ -600,11 +618,11 @@ struct partial_symbol /* Name space code. */ - enum namespace namespace; + enum namespace namespace BYTE_BITFIELD; /* Address class (for info_symbols) */ - enum address_class class; + enum address_class class BYTE_BITFIELD; }; @@ -899,10 +917,14 @@ struct partial_symtab ((NAME)[0] == 'o' && (NAME)[1] == 'p' && (NAME)[2] == CPLUS_MARKER) /* Macro that yields non-zero value iff NAME is the prefix for C++ vtbl - names. Note that this macro is g++ specific (FIXME). */ + names. Note that this macro is g++ specific (FIXME). + '_vt$' is the old cfront-style vtables; '_VT$' is the new + style, using thunks (where '$' is really CPLUS_MARKER). */ #define VTBL_PREFIX_P(NAME) \ - ((NAME)[3] == CPLUS_MARKER && !strncmp ((NAME), "_vt", 3)) + ((NAME)[3] == CPLUS_MARKER && (NAME)[0] == '_' \ + && (((NAME)[1] == 'V' && (NAME)[2] == 'T') \ + || ((NAME)[1] == 'v' && (NAME)[2] == 't'))) /* Macro that yields non-zero value iff NAME is the prefix for C++ destructor names. Note that this macro is g++ specific (FIXME). */ @@ -925,6 +947,10 @@ extern int current_source_line; extern struct objfile *current_objfile; +/* From utils.c. */ +extern int demangle; +extern int asm_demangle; + extern struct symtab * lookup_symtab PARAMS ((char *)); @@ -978,17 +1004,28 @@ contained_in PARAMS ((struct block *, struct block *)); extern void reread_symbols PARAMS ((void)); +/* Macro for name of symbol to indicate a file compiled with gcc. */ +#ifndef GCC_COMPILED_FLAG_SYMBOL +#define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled." +#endif + +/* Macro for name of symbol to indicate a file compiled with gcc2. */ +#ifndef GCC2_COMPILED_FLAG_SYMBOL +#define GCC2_COMPILED_FLAG_SYMBOL "gcc2_compiled." +#endif + /* Functions for dealing with the minimal symbol table, really a misc address<->symbol mapping for things we don't have debug symbols for. */ -extern void -prim_record_minimal_symbol PARAMS ((const char *, CORE_ADDR, - enum minimal_symbol_type)); +extern void prim_record_minimal_symbol PARAMS ((const char *, CORE_ADDR, + enum minimal_symbol_type, + struct objfile *)); -extern void -prim_record_minimal_symbol_and_info PARAMS ((const char *, CORE_ADDR, - enum minimal_symbol_type, - char *info, int section)); +extern void prim_record_minimal_symbol_and_info + PARAMS ((const char *, CORE_ADDR, + enum minimal_symbol_type, + char *info, int section, + struct objfile *)); extern struct minimal_symbol * lookup_minimal_symbol PARAMS ((const char *, struct objfile *)); @@ -996,6 +1033,12 @@ lookup_minimal_symbol PARAMS ((const char *, struct objfile *)); extern struct minimal_symbol * lookup_minimal_symbol_by_pc PARAMS ((CORE_ADDR)); +extern struct minimal_symbol * +lookup_solib_trampoline_symbol_by_pc PARAMS ((CORE_ADDR)); + +extern CORE_ADDR +find_solib_trampoline_target PARAMS ((CORE_ADDR)); + extern void init_minimal_symbol_collection PARAMS ((void)); @@ -1030,13 +1073,21 @@ struct symtabs_and_lines extern struct symtab_and_line find_pc_line PARAMS ((CORE_ADDR, int)); +/* Given an address, return the nearest symbol at or below it in memory. + Optionally return the symtab it's from through 2nd arg, and the + address in inferior memory of the symbol through 3rd arg. */ + +extern struct symbol * +find_addr_symbol PARAMS ((CORE_ADDR, struct symtab **, CORE_ADDR *)); + /* Given a symtab and line number, return the pc there. */ extern CORE_ADDR find_line_pc PARAMS ((struct symtab *, int)); extern int -find_line_pc_range PARAMS ((struct symtab *, int, CORE_ADDR *, CORE_ADDR *)); +find_line_pc_range PARAMS ((struct symtab_and_line, + CORE_ADDR *, CORE_ADDR *)); extern void resolve_sal_pc PARAMS ((struct symtab_and_line *)); @@ -1069,6 +1120,9 @@ maintenance_print_msymbols PARAMS ((char *, int)); void maintenance_print_objfiles PARAMS ((char *, int)); +void +maintenance_check_symtabs PARAMS ((char *, int)); + #endif extern void @@ -1087,8 +1141,6 @@ symbol_file_add PARAMS ((char *, int, CORE_ADDR, int, int, int)); /* source.c */ -extern int frame_file_full_name; /* in stack.c */ - extern int identify_source_line PARAMS ((struct symtab *, int, int, CORE_ADDR)); diff --git a/gnu/usr.bin/gdb/gdb/target.c b/gnu/usr.bin/gdb/gdb/target.c index ea1bd93ca3b6..4cf54f596eeb 100644 --- a/gnu/usr.bin/gdb/gdb/target.c +++ b/gnu/usr.bin/gdb/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 extern int errno; @@ -115,6 +117,11 @@ struct target_ops **current_target_stack; static struct cmd_list_element *targetlist = NULL; +/* Nonzero if we are debugging an attached outside process + rather than an inferior. */ + +int attach_flag; + /* The user just typed 'target' without the name of a target. */ /* ARGSUSED */ @@ -124,7 +131,7 @@ target_command (arg, from_tty) int from_tty; { fputs_filtered ("Argument required (target name). Try `help target'\n", - stdout); + gdb_stdout); } /* Add a possible target architecture to the list. */ @@ -135,7 +142,7 @@ add_target (t) { if (t->to_magic != OPS_MAGIC) { - fprintf(stderr, "Magic number of %s target struct wrong\n", + fprintf_unfiltered(gdb_stderr, "Magic number of %s target struct wrong\n", t->to_shortname); abort(); } @@ -214,7 +221,7 @@ default_terminal_info (args, from_tty) char *args; int from_tty; { - printf("No saved terminal information.\n"); + printf_unfiltered("No saved terminal information.\n"); } #if 0 @@ -257,7 +264,7 @@ kill_or_be_killed (from_tty) { if (target_has_execution) { - printf ("You are already running a program:\n"); + printf_unfiltered ("You are already running a program:\n"); target_files_info (); if (query ("Kill it? ")) { target_kill (); @@ -302,7 +309,7 @@ cleanup_target (t) the struct definition, but not all the places that initialize one. */ if (t->to_magic != OPS_MAGIC) { - fprintf(stderr, "Magic number of %s target struct wrong\n", + fprintf_unfiltered(gdb_stderr, "Magic number of %s target struct wrong\n", t->to_shortname); abort(); } @@ -434,22 +441,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 +474,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 @@ -621,7 +656,7 @@ target_info (args, from_tty) int has_all_mem = 0; if (symfile_objfile != NULL) - printf ("Symbols from \"%s\".\n", symfile_objfile->name); + printf_unfiltered ("Symbols from \"%s\".\n", symfile_objfile->name); #ifdef FILES_INFO_HOOK if (FILES_INFO_HOOK ()) @@ -635,8 +670,8 @@ target_info (args, from_tty) if ((int)(t->to_stratum) <= (int)dummy_stratum) continue; if (has_all_mem) - printf("\tWhile running this, gdb does not access memory from...\n"); - printf("%s:\n", t->to_longname); + printf_unfiltered("\tWhile running this, GDB does not access memory from...\n"); + printf_unfiltered("%s:\n", t->to_longname); (t->to_files_info)(t); has_all_mem = t->to_has_all_memory; } @@ -658,6 +693,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. */ @@ -674,6 +715,21 @@ target_detach (args, from_tty) (current_target->to_detach) (args, from_tty); } +void +target_link (modname, t_reloc) + char *modname; + CORE_ADDR *t_reloc; +{ + if (STREQ(current_target->to_shortname, "rombug")) + { + (current_target->to_lookup_symbol) (modname, t_reloc); + if (*t_reloc == 0) + error("Unable to link to %s and get relocation in rombug", modname); + } + else + *t_reloc = (CORE_ADDR)-1; +} + /* Look through the list of possible targets for a target that can execute a run or attach command without any other data. This is used to locate the default process stratum. @@ -749,7 +805,11 @@ find_core_target () for (t = target_structs; t < target_structs + target_struct_size; ++t) { +#ifdef KERNEL_DEBUG + if ((*t)->to_stratum == (kernel_debugging ? kcore_stratum : core_stratum)) +#else if ((*t)->to_stratum == core_stratum) +#endif { runable = *t; ++count; @@ -758,7 +818,471 @@ find_core_target () return(count == 1 ? runable : NULL); } - + +/* The inferior process has died. Long live the inferior! */ + +void +generic_mourn_inferior () +{ + extern int show_breakpoint_hit_counts; + + inferior_pid = 0; + attach_flag = 0; + breakpoint_init_inferior (); + registers_changed (); + +#ifdef CLEAR_DEFERRED_STORES + /* Delete any pending stores to the inferior... */ + CLEAR_DEFERRED_STORES; +#endif + + reopen_exec_file (); + reinit_frame_cache (); + + /* It is confusing to the user for ignore counts to stick around + from previous runs of the inferior. So clear them. */ + /* However, it is more confusing for the ignore counts to disappear when + using hit counts. So don't clear them if we're counting hits. */ + if (!show_breakpoint_hit_counts) + breakpoint_clear_ignore_counts (); +} + +/* This table must match in order and size the signals in enum target_signal + in target.h. */ +static struct { + char *name; + char *string; + } signals [] = +{ + {"0", "Signal 0"}, + {"SIGHUP", "Hangup"}, + {"SIGINT", "Interrupt"}, + {"SIGQUIT", "Quit"}, + {"SIGILL", "Illegal instruction"}, + {"SIGTRAP", "Trace/breakpoint trap"}, + {"SIGABRT", "Aborted"}, + {"SIGEMT", "Emulation trap"}, + {"SIGFPE", "Arithmetic exception"}, + {"SIGKILL", "Killed"}, + {"SIGBUS", "Bus error"}, + {"SIGSEGV", "Segmentation fault"}, + {"SIGSYS", "Bad system call"}, + {"SIGPIPE", "Broken pipe"}, + {"SIGALRM", "Alarm clock"}, + {"SIGTERM", "Terminated"}, + {"SIGURG", "Urgent I/O condition"}, + {"SIGSTOP", "Stopped (signal)"}, + {"SIGTSTP", "Stopped (user)"}, + {"SIGCONT", "Continued"}, + {"SIGCHLD", "Child status changed"}, + {"SIGTTIN", "Stopped (tty input)"}, + {"SIGTTOU", "Stopped (tty output)"}, + {"SIGIO", "I/O possible"}, + {"SIGXCPU", "CPU time limit exceeded"}, + {"SIGXFSZ", "File size limit exceeded"}, + {"SIGVTALRM", "Virtual timer expired"}, + {"SIGPROF", "Profiling timer expired"}, + {"SIGWINCH", "Window size changed"}, + {"SIGLOST", "Resource lost"}, + {"SIGUSR1", "User defined signal 1"}, + {"SIGUSR2", "User defined signal 2"}, + {"SIGPWR", "Power fail/restart"}, + {"SIGPOLL", "Pollable event occurred"}, + {"SIGWIND", "SIGWIND"}, + {"SIGPHONE", "SIGPHONE"}, + {"SIGWAITING", "Process's LWPs are blocked"}, + {"SIGLWP", "Signal LWP"}, + {"SIGDANGER", "Swap space dangerously low"}, + {"SIGGRANT", "Monitor mode granted"}, + {"SIGRETRACT", "Need to relinguish monitor mode"}, + {"SIGMSG", "Monitor mode data available"}, + {"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"} +}; + +/* Return the string for a signal. */ +char * +target_signal_to_string (sig) + enum target_signal sig; +{ + return signals[sig].string; +} + +/* Return the name for a signal. */ +char * +target_signal_to_name (sig) + enum target_signal sig; +{ + if (sig == TARGET_SIGNAL_UNKNOWN) + /* I think the code which prints this will always print it along with + the string, so no need to be verbose. */ + return "?"; + return signals[sig].name; +} + +/* Given a name, return its signal. */ +enum target_signal +target_signal_from_name (name) + char *name; +{ + enum target_signal sig; + + /* It's possible we also should allow "SIGCLD" as well as "SIGCHLD" + for TARGET_SIGNAL_SIGCHLD. SIGIOT, on the other hand, is more + questionable; seems like by now people should call it SIGABRT + instead. */ + + /* 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)); + } +} + + +/* Returns zero to leave the inferior alone, one to interrupt it. */ +int (*target_activity_function) PARAMS ((void)); +int target_activity_fd; + /* Convert a normal process ID to a string. Returns the string in a static buffer. */ @@ -772,7 +1296,7 @@ normal_pid_to_str (pid) return buf; } - + static char targ_desc[] = "Names of targets and files being debugged.\n\ Shows the entire stack of targets currently in use (including the exec-file,\n\ @@ -786,4 +1310,7 @@ _initialize_targets () add_info ("target", target_info, targ_desc); add_info ("files", target_info, targ_desc); + + if (!STREQ (signals[TARGET_SIGNAL_LAST].string, "TARGET_SIGNAL_MAGIC")) + abort (); } diff --git a/gnu/usr.bin/gdb/gdb/target.h b/gnu/usr.bin/gdb/gdb/target.h index c112b4ac122f..79a125292b04 100644 --- a/gnu/usr.bin/gdb/gdb/target.h +++ b/gnu/usr.bin/gdb/gdb/target.h @@ -1,5 +1,5 @@ /* Interface between GDB and target environments, including files and processes - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by John Gilmore. This file is part of GDB. @@ -46,9 +46,146 @@ enum strata { dummy_stratum, /* The lowest of the low */ file_stratum, /* Executable files, etc */ core_stratum, /* Core dump files */ +#ifdef KERNEL_DEBUG + kcore_stratum, /* Kernel core files */ +#endif process_stratum /* Executing processes */ }; +/* Stuff for target_wait. */ + +/* Generally, what has the program done? */ +enum target_waitkind { + /* The program has exited. The exit status is in value.integer. */ + TARGET_WAITKIND_EXITED, + + /* The program has stopped with a signal. Which signal is in value.sig. */ + TARGET_WAITKIND_STOPPED, + + /* The program has terminated with a signal. Which signal is in + value.sig. */ + TARGET_WAITKIND_SIGNALLED, + + /* The program is letting us know that it dynamically loaded something + (e.g. it called load(2) on AIX). */ + TARGET_WAITKIND_LOADED, + + /* Nothing happened, but we stopped anyway. This perhaps should be handled + within target_wait, but I'm not sure target_wait should be resuming the + inferior. */ + TARGET_WAITKIND_SPURIOUS + }; + +/* The numbering of these signals is chosen to match traditional unix + signals (insofar as various unices use the same numbers, anyway). + It is also the numbering of the GDB remote protocol. Other remote + protocols, if they use a different numbering, should make sure to + translate appropriately. */ + +/* This is based strongly on Unix/POSIX signals for several reasons: + (1) This set of signals represents a widely-accepted attempt to + represent events of this sort in a portable fashion, (2) we want a + signal to make it from wait to child_wait to the user intact, (3) many + remote protocols use a similar encoding. However, it is + recognized that this set of signals has limitations (such as not + distinguishing between various kinds of SIGSEGV, or not + distinguishing hitting a breakpoint from finishing a single step). + So in the future we may get around this either by adding additional + signals for breakpoint, single-step, etc., or by adding signal + codes; the latter seems more in the spirit of what BSD, System V, + etc. are doing to address these issues. */ + +/* For an explanation of what each signal means, see + target_signal_to_string. */ + +enum target_signal { + /* Used some places (e.g. stop_signal) to record the concept that + there is no signal. */ + TARGET_SIGNAL_0 = 0, + TARGET_SIGNAL_FIRST = 0, + TARGET_SIGNAL_HUP = 1, + TARGET_SIGNAL_INT = 2, + TARGET_SIGNAL_QUIT = 3, + TARGET_SIGNAL_ILL = 4, + TARGET_SIGNAL_TRAP = 5, + TARGET_SIGNAL_ABRT = 6, + TARGET_SIGNAL_EMT = 7, + TARGET_SIGNAL_FPE = 8, + TARGET_SIGNAL_KILL = 9, + TARGET_SIGNAL_BUS = 10, + TARGET_SIGNAL_SEGV = 11, + TARGET_SIGNAL_SYS = 12, + TARGET_SIGNAL_PIPE = 13, + TARGET_SIGNAL_ALRM = 14, + TARGET_SIGNAL_TERM = 15, + TARGET_SIGNAL_URG = 16, + TARGET_SIGNAL_STOP = 17, + TARGET_SIGNAL_TSTP = 18, + TARGET_SIGNAL_CONT = 19, + TARGET_SIGNAL_CHLD = 20, + TARGET_SIGNAL_TTIN = 21, + TARGET_SIGNAL_TTOU = 22, + TARGET_SIGNAL_IO = 23, + TARGET_SIGNAL_XCPU = 24, + TARGET_SIGNAL_XFSZ = 25, + TARGET_SIGNAL_VTALRM = 26, + TARGET_SIGNAL_PROF = 27, + TARGET_SIGNAL_WINCH = 28, + TARGET_SIGNAL_LOST = 29, + TARGET_SIGNAL_USR1 = 30, + TARGET_SIGNAL_USR2 = 31, + TARGET_SIGNAL_PWR = 32, + /* Similar to SIGIO. Perhaps they should have the same number. */ + TARGET_SIGNAL_POLL = 33, + TARGET_SIGNAL_WIND = 34, + TARGET_SIGNAL_PHONE = 35, + TARGET_SIGNAL_WAITING = 36, + TARGET_SIGNAL_LWP = 37, + TARGET_SIGNAL_DANGER = 38, + TARGET_SIGNAL_GRANT = 39, + TARGET_SIGNAL_RETRACT = 40, + TARGET_SIGNAL_MSG = 41, + TARGET_SIGNAL_SOUND = 42, + TARGET_SIGNAL_SAK = 43, + + /* Some signal we don't know about. */ + TARGET_SIGNAL_UNKNOWN, + + /* Use whatever signal we use when one is not specifically specified + (for passing to proceed and so on). */ + TARGET_SIGNAL_DEFAULT, + + /* Last and unused enum value, for sizing arrays, etc. */ + TARGET_SIGNAL_LAST +}; + +struct target_waitstatus { + enum target_waitkind kind; + + /* Exit status or signal number. */ + union { + int integer; + enum target_signal sig; + } value; +}; + +/* Return the string for a signal. */ +extern char *target_signal_to_string PARAMS ((enum target_signal)); + +/* Return the name (SIGHUP, etc.) for a signal. */ +extern char *target_signal_to_name PARAMS ((enum target_signal)); + +/* Given a name (SIGHUP, etc.), return its signal. */ +enum target_signal target_signal_from_name PARAMS ((char *)); + +/* If certain kinds of activity happen, target_wait should perform + callbacks. */ +/* Right now we just call (*TARGET_ACTIVITY_FUNCTION) if I/O is possible + on TARGET_ACTIVITY_FD. */ +extern int target_activity_fd; +/* Returns zero to leave the inferior alone, one to interrupt it. */ +extern int (*target_activity_function) PARAMS ((void)); + struct target_ops { char *to_shortname; /* Name this target type */ @@ -60,8 +197,8 @@ struct target_ops void (*to_close) PARAMS ((int)); void (*to_attach) PARAMS ((char *, int)); void (*to_detach) PARAMS ((char *, int)); - void (*to_resume) PARAMS ((int, int, int)); - int (*to_wait) PARAMS ((int, int *)); + void (*to_resume) PARAMS ((int, int, enum target_signal)); + int (*to_wait) PARAMS ((int, struct target_waitstatus *)); void (*to_fetch_registers) PARAMS ((int)); void (*to_store_registers) PARAMS ((int)); void (*to_prepare_to_store) PARAMS ((void)); @@ -88,6 +225,27 @@ struct target_ops int len, int write, struct target_ops * target)); +#if 0 + /* Enable this after 4.12. */ + + /* Search target memory. Start at STARTADDR and take LEN bytes of + target memory, and them with MASK, and compare to DATA. If they + match, set *ADDR_FOUND to the address we found it at, store the data + we found at LEN bytes starting at DATA_FOUND, and return. If + not, add INCREMENT to the search address and keep trying until + the search address is outside of the range [LORANGE,HIRANGE). + + If we don't find anything, set *ADDR_FOUND to (CORE_ADDR)0 and return. */ + void (*to_search) PARAMS ((int len, char *data, char *mask, + CORE_ADDR startaddr, int increment, + CORE_ADDR lorange, CORE_ADDR hirange, + CORE_ADDR *addr_found, char *data_found)); + +#define target_search(len, data, mask, startaddr, increment, lorange, hirange, addr_found, data_found) \ + (*current_target->to_search) (len, data, mask, startaddr, increment, \ + lorange, hirange, addr_found, data_found) +#endif /* 0 */ + void (*to_files_info) PARAMS ((struct target_ops *)); int (*to_insert_breakpoint) PARAMS ((CORE_ADDR, char *)); int (*to_remove_breakpoint) PARAMS ((CORE_ADDR, char *)); @@ -174,15 +332,20 @@ extern void target_detach PARAMS ((char *, int)); /* Resume execution of the target process PID. STEP says whether to - single-step or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be - given to the target, or zero for no signal. */ + single-step or to run free; SIGGNAL is the signal to be given to + the target, or TARGET_SIGNAL_0 for no signal. The caller may not + pass TARGET_SIGNAL_DEFAULT. */ #define target_resume(pid, step, siggnal) \ (*current_target->to_resume) (pid, step, siggnal) -/* Wait for process pid to do something. Pid = -1 to wait for any pid to do - something. Return pid of child, or -1 in case of error; store status - through argument pointer STATUS. */ +/* Wait for process pid to do something. Pid = -1 to wait for any pid + to do something. Return pid of child, or -1 in case of error; + store status through argument pointer STATUS. Note that it is + *not* OK to return_to_top_level out of target_wait without popping + the debugging target from the stack; GDB isn't prepared to get back + to the prompt with a debugging target but without the frame cache, + stop_pc, etc., set up. */ #define target_wait(pid, status) \ (*current_target->to_wait) (pid, status) @@ -208,8 +371,7 @@ target_detach PARAMS ((char *, int)); #define target_prepare_to_store() \ (*current_target->to_prepare_to_store) () -extern int -target_read_string PARAMS ((CORE_ADDR, char *, int)); +extern int target_read_string PARAMS ((CORE_ADDR, char **, int, int *)); extern int target_read_memory PARAMS ((CORE_ADDR, char *, int)); @@ -382,6 +544,8 @@ print_section_info PARAMS ((struct target_ops *, bfd *)); #define target_has_execution \ (current_target->to_has_execution) +extern void target_link PARAMS ((char *, CORE_ADDR *)); + /* Converts a process id to a string. Usually, the string just contains `process xyz', but on some systems it may contain `process xyz thread abc'. */ @@ -429,7 +593,9 @@ pop_target PARAMS ((void)); struct section_table { CORE_ADDR addr; /* Lowest address in section */ CORE_ADDR endaddr; /* 1+highest address in section */ - sec_ptr sec_ptr; /* BFD section pointer */ + + sec_ptr the_bfd_section; + bfd *bfd; /* BFD file pointer */ }; @@ -462,4 +628,22 @@ find_default_create_inferior PARAMS ((char *, char *, char **)); struct target_ops * find_core_target PARAMS ((void)); +/* Stuff that should be shared among the various remote targets. */ + +/* Debugging level. 0 is off, and non-zero values mean to print some debug + information (higher values, more information). */ +extern int remote_debug; + +/* Speed in bits per second, or -1 which means don't mess with the speed. */ +extern int baud_rate; + +/* Functions for helping to write a native target. */ + +/* This is for native targets which use a unix/POSIX-style waitstatus. */ +extern void store_waitstatus PARAMS ((struct target_waitstatus *, int)); + +/* Convert between host signal numbers and enum target_signal's. */ +extern enum target_signal target_signal_from_host PARAMS ((int)); +extern int target_signal_to_host PARAMS ((enum target_signal)); + #endif /* !defined (TARGET_H) */ diff --git a/gnu/usr.bin/gdb/gdb/terminal.h b/gnu/usr.bin/gdb/gdb/terminal.h index de52a16ba499..f76fa9031336 100644 --- a/gnu/usr.bin/gdb/gdb/terminal.h +++ b/gnu/usr.bin/gdb/gdb/terminal.h @@ -20,8 +20,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #if !defined (TERMINAL_H) #define TERMINAL_H 1 -#include - #if !defined(__GO32__) && !defined (HAVE_TERMIOS) /* Define a common set of macros -- BSD based -- and redefine whatever diff --git a/gnu/usr.bin/gdb/gdb/thread.c b/gnu/usr.bin/gdb/gdb/thread.c index f14b41fc041c..c3d52c33b4de 100644 --- a/gnu/usr.bin/gdb/gdb/thread.c +++ b/gnu/usr.bin/gdb/gdb/thread.c @@ -29,7 +29,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "target.h" #include "thread.h" #include "command.h" +#include "gdbcmd.h" +#include #include #include @@ -210,6 +212,112 @@ thread_switch (pid) select_frame (get_current_frame (), 0); } +static void +restore_current_thread (pid) + int pid; +{ + if (pid != inferior_pid) + thread_switch (pid); +} + +/* Apply a GDB command to a list of threads. List syntax is a whitespace + seperated list of numbers, or ranges, or the keyword `all'. Ranges consist + of two numbers seperated by a hyphen. Examples: + + thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4 + thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9 + thread apply all p x/i $pc Apply x/i $pc cmd to all threads +*/ + +static void +thread_apply_all_command (cmd, from_tty) + char *cmd; + int from_tty; +{ + struct thread_info *tp; + struct cleanup *old_chain; + + if (cmd == NULL || *cmd == '\000') + error ("Please specify a command following the thread ID list"); + + old_chain = make_cleanup (restore_current_thread, inferior_pid); + + for (tp = thread_list; tp; tp = tp->next) + { + thread_switch (tp->pid); + printf_filtered ("\nThread %d (%s):\n", tp->num, + target_pid_to_str (inferior_pid)); + execute_command (cmd, from_tty); + } +} + +static void +thread_apply_command (tidlist, from_tty) + char *tidlist; + int from_tty; +{ + char *cmd; + char *p; + struct cleanup *old_chain; + + if (tidlist == NULL || *tidlist == '\000') + error ("Please specify a thread ID list"); + + for (cmd = tidlist; *cmd != '\000' && !isalpha(*cmd); cmd++); + + if (*cmd == '\000') + error ("Please specify a command following the thread ID list"); + + old_chain = make_cleanup (restore_current_thread, inferior_pid); + + while (tidlist < cmd) + { + struct thread_info *tp; + int start, end; + + start = strtol (tidlist, &p, 10); + if (p == tidlist) + error ("Error parsing %s", tidlist); + tidlist = p; + + while (*tidlist == ' ' || *tidlist == '\t') + tidlist++; + + if (*tidlist == '-') /* Got a range of IDs? */ + { + tidlist++; /* Skip the - */ + end = strtol (tidlist, &p, 10); + if (p == tidlist) + error ("Error parsing %s", tidlist); + tidlist = p; + + while (*tidlist == ' ' || *tidlist == '\t') + tidlist++; + } + else + end = start; + + for (; start <= end; start++) + { + tp = find_thread_id (start); + + if (!tp) + { + warning ("Unknown thread %d.", start); + continue; + } + + thread_switch (tp->pid); + printf_filtered ("\nThread %d (%s):\n", tp->num, + target_pid_to_str (inferior_pid)); + execute_command (cmd, from_tty); + } + } +} + +/* Switch to the specified thread. Will dispatch off to thread_apply_command + if prefix of arg is `apply'. */ + static void thread_command (tidstr, from_tty) char *tidstr; @@ -222,7 +330,6 @@ thread_command (tidstr, from_tty) error ("Please specify a thread ID. Use the \"info threads\" command to\n\ see the IDs of currently known threads."); - num = atoi (tidstr); tp = find_thread_id (num); @@ -240,9 +347,25 @@ see the IDs of currently known threads.", num); void _initialize_thread () { + static struct cmd_list_element *thread_cmd_list = NULL; + static struct cmd_list_element *thread_apply_list = NULL; + extern struct cmd_list_element *cmdlist; + add_info ("threads", info_threads_command, "IDs of currently known threads."); - add_com ("thread", class_info, thread_command, - "Use this command to switch between threads.\n\ -The new thread ID must be currently known."); + + add_prefix_cmd ("thread", class_run, thread_command, + "Use this command to switch between threads.\n\ +The new thread ID must be currently known.", &thread_cmd_list, "thread ", 1, + &cmdlist); + + add_prefix_cmd ("apply", class_run, thread_apply_command, + "Apply a command to a list of threads.", + &thread_apply_list, "apply ", 1, &thread_cmd_list); + + add_cmd ("all", class_run, thread_apply_all_command, + "Apply a command to all threads.", + &thread_apply_list); + + add_com_alias ("t", "thread", class_run, 1); } diff --git a/gnu/usr.bin/gdb/gdb/tm-i386v.h b/gnu/usr.bin/gdb/gdb/tm-i386v.h index f80f51921488..49de3a07712f 100644 --- a/gnu/usr.bin/gdb/gdb/tm-i386v.h +++ b/gnu/usr.bin/gdb/gdb/tm-i386v.h @@ -84,9 +84,11 @@ i386_skip_prologue PARAMS ((int)); #define INVALID_FLOAT(p, len) (0) -/* Say how long (ordinary) registers are. */ +/* Say how long (ordinary) registers are. This is a piece of bogosity + used in push_word and a few other places; REGISTER_RAW_SIZE is the + real way to know how big a register is. */ -#define REGISTER_TYPE long +#define REGISTER_SIZE 4 /* Number of machine registers */ @@ -145,23 +147,6 @@ i386_skip_prologue PARAMS ((int)); #define MAX_REGISTER_VIRTUAL_SIZE 4 -/* Nonzero if register N requires conversion - from raw format to virtual format. */ - -#define REGISTER_CONVERTIBLE(N) (0) - -/* Convert data from raw format for register REGNUM - to virtual format for register REGNUM. */ - -#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \ - {memcpy ((TO), (FROM), 4);} - -/* Convert data from virtual format for register REGNUM - to raw format for register REGNUM. */ - -#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \ - {memcpy ((TO), (FROM), 4);} - /* Return the GDB type object for the "standard" data type of data in register N. */ /* Perhaps si and di should go here, but potentially they could be @@ -280,6 +265,8 @@ i386_pop_frame PARAMS ((void)); #define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */ +#define CALL_DUMMY_BREAKPOINT_OFFSET 5 + /* Insert the specified number of args and function address into a call sequence of the above form stored at DUMMYNAME. */ diff --git a/gnu/usr.bin/gdb/gdb/tm.h b/gnu/usr.bin/gdb/gdb/tm.h index 25b66c709dee..a33a6685c822 100644 --- a/gnu/usr.bin/gdb/gdb/tm.h +++ b/gnu/usr.bin/gdb/gdb/tm.h @@ -68,7 +68,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Offset to saved PC in sigcontext, from . */ #define SIGCONTEXT_PC_OFFSET 20 -#undef FRAME_SAVED_PC(FRAME) +#undef FRAME_SAVED_PC #define FRAME_SAVED_PC(FRAME) \ (((FRAME)->signal_handler_caller \ ? sigtramp_saved_pc (FRAME) \ diff --git a/gnu/usr.bin/gdb/gdb/typeprint.c b/gnu/usr.bin/gdb/gdb/typeprint.c index 5e13e07fb4d9..785ec619af6f 100644 --- a/gnu/usr.bin/gdb/gdb/typeprint.c +++ b/gnu/usr.bin/gdb/gdb/typeprint.c @@ -57,7 +57,7 @@ void type_print (type, varstring, stream, show) struct type *type; char *varstring; - FILE *stream; + GDB_FILE *stream; int show; { LA_PRINT_TYPE (type, varstring, stream, show, 0); @@ -72,7 +72,7 @@ whatis_exp (exp, show) int show; { struct expression *expr; - register value val; + register value_ptr val; register struct cleanup *old_chain = NULL; if (exp) @@ -85,7 +85,7 @@ whatis_exp (exp, show) val = access_value_history (0); printf_filtered ("type = "); - type_print (VALUE_TYPE (val), "", stdout, show); + type_print (VALUE_TYPE (val), "", gdb_stdout, show); printf_filtered ("\n"); if (exp) @@ -146,7 +146,7 @@ ptype_command (typename, from_tty) { /* User did "ptype " */ printf_filtered ("type = "); - type_print (type, "", stdout, 1); + type_print (type, "", gdb_stdout, 1); printf_filtered ("\n"); do_cleanups (old_chain); } @@ -175,7 +175,7 @@ void print_type_scalar (type, val, stream) struct type *type; LONGEST val; - FILE *stream; + GDB_FILE *stream; { unsigned int i; unsigned len; @@ -235,7 +235,7 @@ print_type_scalar (type, val, stream) default: error ("Invalid type code in symbol table."); } - fflush (stream); + gdb_flush (stream); } #if MAINTENANCE_CMDS @@ -249,7 +249,7 @@ maintenance_print_type (typename, from_tty) char *typename; int from_tty; { - register value val; + register value_ptr val; register struct type *type; register struct cleanup *old_chain; struct expression *expr; @@ -287,8 +287,8 @@ _initialize_typeprint () add_com ("ptype", class_vars, ptype_command, "Print definition of type TYPE.\n\ -Argument may be a type name defined by typedef, or \"struct STRUCTNAME\"\n\ -or \"union UNIONNAME\" or \"enum ENUMNAME\".\n\ +Argument may be a type name defined by typedef, or \"struct STRUCT-TAG\"\n\ +or \"class CLASS-NAME\" or \"union UNION-TAG\" or \"enum ENUM-TAG\".\n\ The selected stack frame's lexical context is used to look up the name."); add_com ("whatis", class_vars, whatis_command, diff --git a/gnu/usr.bin/gdb/gdb/typeprint.h b/gnu/usr.bin/gdb/gdb/typeprint.h index e6740db7c298..eead5f6f8b6e 100644 --- a/gnu/usr.bin/gdb/gdb/typeprint.h +++ b/gnu/usr.bin/gdb/gdb/typeprint.h @@ -18,4 +18,4 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ void -print_type_scalar PARAMS ((struct type *type, LONGEST, FILE *)); +print_type_scalar PARAMS ((struct type *type, LONGEST, GDB_FILE *)); diff --git a/gnu/usr.bin/gdb/gdb/utils.c b/gnu/usr.bin/gdb/gdb/utils.c index 38010e323e6f..863cef42d169 100644 --- a/gnu/usr.bin/gdb/gdb/utils.c +++ b/gnu/usr.bin/gdb/gdb/utils.c @@ -30,12 +30,17 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "signals.h" #include "gdbcmd.h" #include "serial.h" -#include "terminal.h" /* For job_control */ #include "bfd.h" #include "target.h" #include "demangle.h" #include "expression.h" #include "language.h" +#include "annotate.h" + +#include "readline.h" + +/* readline defines this. */ +#undef savestring /* Prototypes for local functions */ @@ -67,6 +72,10 @@ set_width_command PARAMS ((char *, int, struct cmd_list_element *)); static struct cleanup *cleanup_chain; +/* Nonzero if we have job control. */ + +int job_control; + /* Nonzero means a quit has been requested. */ int quit_flag; @@ -216,7 +225,7 @@ warning_setup () { target_terminal_ours (); wrap_here(""); /* Force out any buffered output */ - fflush (stdout); + gdb_flush (gdb_stdout); } /* Print a warning message. @@ -236,15 +245,33 @@ warning (va_alist) va_start (args); target_terminal_ours (); wrap_here(""); /* Force out any buffered output */ - fflush (stdout); + gdb_flush (gdb_stdout); if (warning_pre_print) - fprintf (stderr, warning_pre_print); + fprintf_unfiltered (gdb_stderr, warning_pre_print); string = va_arg (args, char *); - vfprintf (stderr, string, args); - fprintf (stderr, "\n"); + vfprintf_unfiltered (gdb_stderr, string, args); + fprintf_unfiltered (gdb_stderr, "\n"); va_end (args); } +/* Start the printing of an error message. Way to use this is to call + this, output the error message (use filtered output), and then call + return_to_top_level (RETURN_ERROR). error() provides a convenient way to + do this for the special case that the error message can be formatted with + a single printf call, but this is more general. */ +void +error_begin () +{ + target_terminal_ours (); + wrap_here (""); /* Force out any buffered output */ + gdb_flush (gdb_stdout); + + annotate_error_begin (); + + if (error_pre_print) + fprintf_filtered (gdb_stderr, error_pre_print); +} + /* Print an error message and return to command level. The first argument STRING is the error message, used as a fprintf string, and the remaining args are passed as arguments to it. */ @@ -257,15 +284,11 @@ error (va_alist) va_list args; char *string; + error_begin (); va_start (args); - target_terminal_ours (); - wrap_here(""); /* Force out any buffered output */ - fflush (stdout); - if (error_pre_print) - fprintf_filtered (stderr, error_pre_print); string = va_arg (args, char *); - vfprintf_filtered (stderr, string, args); - fprintf_filtered (stderr, "\n"); + vfprintf_filtered (gdb_stderr, string, args); + fprintf_filtered (gdb_stderr, "\n"); va_end (args); return_to_top_level (RETURN_ERROR); } @@ -287,9 +310,9 @@ fatal (va_alist) va_start (args); string = va_arg (args, char *); - fprintf (stderr, "\ngdb: "); - vfprintf (stderr, string, args); - fprintf (stderr, "\n"); + fprintf_unfiltered (gdb_stderr, "\ngdb: "); + vfprintf_unfiltered (gdb_stderr, string, args); + fprintf_unfiltered (gdb_stderr, "\n"); va_end (args); exit (1); } @@ -309,9 +332,9 @@ fatal_dump_core (va_alist) string = va_arg (args, char *); /* "internal error" is always correct, since GDB should never dump core, no matter what the input. */ - fprintf (stderr, "\ngdb internal error: "); - vfprintf (stderr, string, args); - fprintf (stderr, "\n"); + fprintf_unfiltered (gdb_stderr, "\ngdb internal error: "); + vfprintf_unfiltered (gdb_stderr, string, args); + fprintf_unfiltered (gdb_stderr, "\n"); va_end (args); signal (SIGQUIT, SIG_DFL); @@ -379,7 +402,7 @@ perror_with_name (string) /* I understand setting these is a matter of taste. Still, some people may clear errno but not know about bfd_error. Doing this here is not unreasonable. */ - bfd_error = no_error; + bfd_set_error (bfd_error_no_error); errno = 0; error ("%s.", combined); @@ -402,7 +425,10 @@ print_sys_errmsg (string, errcode) strcat (combined, ": "); strcat (combined, err); - fprintf (stderr, "%s.\n", combined); + /* We want anything which was printed on stdout to come out first, before + this message. */ + gdb_flush (gdb_stdout); + fprintf_unfiltered (gdb_stderr, "%s.\n", combined); } /* Control C eventually causes this to be called, at a convenient time. */ @@ -410,26 +436,39 @@ print_sys_errmsg (string, errcode) void quit () { - serial_t stdout_serial = serial_fdopen (1); + serial_t gdb_stdout_serial = serial_fdopen (1); target_terminal_ours (); - wrap_here ((char *)0); /* Force out any pending output */ - SERIAL_FLUSH_OUTPUT (stdout_serial); + /* We want all output to appear now, before we print "Quit". We + have 3 levels of buffering we have to flush (it's possible that + some of these should be changed to flush the lower-level ones + too): */ - SERIAL_UN_FDOPEN (stdout_serial); + /* 1. The _filtered buffer. */ + wrap_here ((char *)0); + + /* 2. The stdio buffer. */ + gdb_flush (gdb_stdout); + gdb_flush (gdb_stderr); + + /* 3. The system-level buffer. */ + SERIAL_FLUSH_OUTPUT (gdb_stdout_serial); + SERIAL_UN_FDOPEN (gdb_stdout_serial); + + annotate_error_begin (); /* Don't use *_filtered; we don't want to prompt the user to continue. */ if (error_pre_print) - fprintf (stderr, error_pre_print); + fprintf_unfiltered (gdb_stderr, error_pre_print); if (job_control /* If there is no terminal switching for this target, then we can't possibly get screwed by the lack of job control. */ || current_target->to_terminal_ours == NULL) - fprintf (stderr, "Quit\n"); + fprintf_unfiltered (gdb_stderr, "Quit\n"); else - fprintf (stderr, + fprintf_unfiltered (gdb_stderr, "Quit (expect signal SIGINT when the program is resumed)\n"); return_to_top_level (RETURN_QUIT); } @@ -446,16 +485,49 @@ pollquit() if (kbhit ()) { int k = getkey (); - if (k == 1) + if (k == 1) { quit_flag = 1; - else if (k == 2) + quit(); + } + else if (k == 2) { immediate_quit = 1; - quit (); + quit (); + } + else + { + /* We just ignore it */ + fprintf_unfiltered (gdb_stderr, "CTRL-A to quit, CTRL-B to quit harder\n"); + } } } -#endif +#endif +#ifdef __GO32__ +void notice_quit() +{ + if (kbhit ()) + { + int k = getkey (); + if (k == 1) { + quit_flag = 1; + } + else if (k == 2) + { + immediate_quit = 1; + } + else + { + fprintf_unfiltered (gdb_stderr, "CTRL-A to quit, CTRL-B to quit harder\n"); + } + } +} +#else +void notice_quit() +{ + /* Done by signals */ +} +#endif /* Control C comes here */ void @@ -464,13 +536,17 @@ request_quit (signo) { quit_flag = 1; -#ifdef USG - /* Restore the signal handler. */ + /* Restore the signal handler. Harmless with BSD-style signals, needed + for System V-style signals. So just always do it, rather than worrying + about USG defines and stuff like that. */ signal (signo, request_quit); -#endif +#ifdef REQUEST_QUIT + REQUEST_QUIT; +#else if (immediate_quit) quit (); +#endif } @@ -717,6 +793,21 @@ print_spaces (n, file) fputc (' ', file); } +/* Print a host address. */ + +void +gdb_print_address (addr, stream) + PTR addr; + GDB_FILE *stream; +{ + + /* We could use the %p conversion specifier to fprintf if we had any + way of knowing whether this host supports it. But the following + should work on the Alpha and on 32 bit machines. */ + + fprintf_filtered (stream, "0x%lx", (unsigned long)addr); +} + /* Ask user a y-or-n question and return 1 iff answer is yes. Takes three args which are given to printf to print the question. The first, a control string, should end in "? ". @@ -731,6 +822,7 @@ query (va_alist) char *ctlstr; register int answer; register int ans2; + int retval; /* Automatically answer "yes" if input is not from a terminal. */ if (!input_from_terminal_p ()) @@ -739,17 +831,28 @@ query (va_alist) while (1) { wrap_here (""); /* Flush any buffered output */ - fflush (stdout); + gdb_flush (gdb_stdout); + + if (annotation_level > 1) + printf_filtered ("\n\032\032pre-query\n"); + va_start (args); ctlstr = va_arg (args, char *); - vfprintf_filtered (stdout, ctlstr, args); + vfprintf_filtered (gdb_stdout, ctlstr, args); va_end (args); printf_filtered ("(y or n) "); - fflush (stdout); + + if (annotation_level > 1) + printf_filtered ("\n\032\032query\n"); + + gdb_flush (gdb_stdout); answer = fgetc (stdin); clearerr (stdin); /* in case of C-d */ if (answer == EOF) /* C-d */ - return 1; + { + retval = 1; + break; + } if (answer != '\n') /* Eat rest of input line, to EOF or newline */ do { @@ -760,11 +863,21 @@ query (va_alist) if (answer >= 'a') answer -= 040; if (answer == 'Y') - return 1; + { + retval = 1; + break; + } if (answer == 'N') - return 0; + { + retval = 0; + break; + } printf_filtered ("Please answer y or n.\n"); } + + if (annotation_level > 1) + printf_filtered ("\n\032\032post-query\n"); + return retval; } @@ -956,6 +1069,15 @@ static void prompt_for_continue () { char *ignore; + char cont_prompt[120]; + + if (annotation_level > 1) + printf_unfiltered ("\n\032\032pre-prompt-for-continue\n"); + + strcpy (cont_prompt, + "---Type to continue, or q to quit---"); + if (annotation_level > 1) + strcat (cont_prompt, "\n\032\032prompt-for-continue\n"); /* We must do this *before* we call gdb_readline, else it will eventually call us -- thinking that we're trying to print beyond the end of the @@ -970,8 +1092,14 @@ prompt_for_continue () from system to system, and because telling them what to do in the prompt is more user-friendly than expecting them to think of SIGINT. */ - ignore = - gdb_readline ("---Type to continue, or q to quit---"); + /* Call readline, not gdb_readline, because GO32 readline handles control-C + whereas control-C to gdb_readline will cause the user to get dumped + out to DOS. */ + ignore = readline (cont_prompt); + + if (annotation_level > 1) + printf_unfiltered ("\n\032\032post-prompt-for-continue\n"); + if (ignore) { char *p = ignore; @@ -1024,10 +1152,14 @@ void wrap_here(indent) char *indent; { + /* This should have been allocated, but be paranoid anyway. */ + if (!wrap_buffer) + abort (); + if (wrap_buffer[0]) { *wrap_pointer = '\0'; - fputs (wrap_buffer, stdout); + fputs_unfiltered (wrap_buffer, gdb_stdout); } wrap_pointer = wrap_buffer; wrap_buffer[0] = '\0'; @@ -1066,20 +1198,40 @@ begin_line () } } -/* Like fputs but pause after every screenful, and can wrap at points - other than the final character of a line. - Unlike fputs, fputs_filtered does not return a value. + +GDB_FILE * +gdb_fopen (name, mode) + char * name; + char * mode; +{ + return fopen (name, mode); +} + +void +gdb_flush (stream) + FILE *stream; +{ + fflush (stream); +} + +/* Like fputs but if FILTER is true, pause after every screenful. + + Regardless of FILTER can wrap at points other than the final + character of a line. + + Unlike fputs, fputs_maybe_filtered does not return a value. It is OK for LINEBUFFER to be NULL, in which case just don't print anything. - Note that a longjmp to top level may occur in this routine - (since prompt_for_continue may do so) so this routine should not be - called when cleanups are not in place. */ + Note that a longjmp to top level may occur in this routine (only if + FILTER is true) (since prompt_for_continue may do so) so this + routine should not be called when cleanups are not in place. */ -void -fputs_filtered (linebuffer, stream) +static void +fputs_maybe_filtered (linebuffer, stream, filter) const char *linebuffer; FILE *stream; + int filter; { const char *lineptr; @@ -1087,10 +1239,10 @@ fputs_filtered (linebuffer, stream) return; /* Don't do any filtering if it is disabled. */ - if (stream != stdout + if (stream != gdb_stdout || (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX)) { - fputs (linebuffer, stream); + fputs_unfiltered (linebuffer, stream); return; } @@ -1102,7 +1254,8 @@ fputs_filtered (linebuffer, stream) while (*lineptr) { /* Possible new page. */ - if (lines_printed >= lines_per_page - 1) + if (filter && + (lines_printed >= lines_per_page - 1)) prompt_for_continue (); while (*lineptr && *lineptr != '\n') @@ -1113,7 +1266,7 @@ fputs_filtered (linebuffer, stream) if (wrap_column) *wrap_pointer++ = '\t'; else - putc ('\t', stream); + fputc_unfiltered ('\t', stream); /* Shifting right by 3 produces the number of tab stops we have already passed, and then adding one and shifting left 3 advances to the next tab stop. */ @@ -1125,7 +1278,7 @@ fputs_filtered (linebuffer, stream) if (wrap_column) *wrap_pointer++ = *lineptr; else - putc (*lineptr, stream); + fputc_unfiltered (*lineptr, stream); chars_printed++; lineptr++; } @@ -1140,7 +1293,7 @@ fputs_filtered (linebuffer, stream) if chars_per_line is right, we probably just overflowed anyway; if it's wrong, let us keep going. */ if (wrap_column) - putc ('\n', stream); + fputc_unfiltered ('\n', stream); /* Possible new page. */ if (lines_printed >= lines_per_page - 1) @@ -1149,9 +1302,9 @@ fputs_filtered (linebuffer, stream) /* Now output indentation and wrapped string */ if (wrap_column) { - fputs (wrap_indent, stream); - *wrap_pointer = '\0'; /* Null-terminate saved stuff */ - fputs (wrap_buffer, stream); /* and eject it */ + fputs_unfiltered (wrap_indent, stream); + *wrap_pointer = '\0'; /* Null-terminate saved stuff */ + fputs_unfiltered (wrap_buffer, stream); /* and eject it */ /* FIXME, this strlen is what prevents wrap_indent from containing tabs. However, if we recurse to print it and count its chars, we risk trouble if wrap_indent is @@ -1172,36 +1325,77 @@ fputs_filtered (linebuffer, stream) chars_printed = 0; wrap_here ((char *)0); /* Spit out chars, cancel further wraps */ lines_printed++; - putc ('\n', stream); + fputc_unfiltered ('\n', stream); lineptr++; } } } +void +fputs_filtered (linebuffer, stream) + const char *linebuffer; + FILE *stream; +{ + fputs_maybe_filtered (linebuffer, stream, 1); +} + +void +putc_unfiltered (c) + int c; +{ + char buf[2]; + buf[0] = c; + buf[1] = 0; + fputs_unfiltered (buf, gdb_stdout); +} + +void +fputc_unfiltered (c, stream) + int c; + FILE * stream; +{ + char buf[2]; + buf[0] = c; + buf[1] = 0; + fputs_unfiltered (buf, stream); +} + + /* Print a variable number of ARGS using format FORMAT. If this information is going to put the amount written (since the last call to REINITIALIZE_MORE_FILTER or the last page break) over the page size, - print out a pause message and do a gdb_readline to get the users - permision to continue. + call prompt_for_continue to get the users permision to continue. Unlike fprintf, this function does not return a value. We implement three variants, vfprintf (takes a vararg list and stream), fprintf (takes a stream to write on), and printf (the usual). - Note that this routine has a restriction that the length of the - final output line must be less than 255 characters *or* it must be - less than twice the size of the format string. This is a very - arbitrary restriction, but it is an internal restriction, so I'll - put it in. This means that the %s format specifier is almost - useless; unless the caller can GUARANTEE that the string is short - enough, fputs_filtered should be used instead. - Note also that a longjmp to top level may occur in this routine (since prompt_for_continue may do so) so this routine should not be called when cleanups are not in place. */ -#define MIN_LINEBUF 255 +static void +vfprintf_maybe_filtered (stream, format, args, filter) + FILE *stream; + char *format; + va_list args; + int filter; +{ + char *linebuffer; + struct cleanup *old_cleanups; + + vasprintf (&linebuffer, format, args); + if (linebuffer == NULL) + { + fputs_unfiltered ("\ngdb: virtual memory exhausted.\n", gdb_stderr); + exit (1); + } + old_cleanups = make_cleanup (free, linebuffer); + fputs_maybe_filtered (linebuffer, stream, filter); + do_cleanups (old_cleanups); +} + void vfprintf_filtered (stream, format, args) @@ -1209,23 +1403,27 @@ vfprintf_filtered (stream, format, args) char *format; va_list args; { - char line_buf[MIN_LINEBUF+10]; - char *linebuffer = line_buf; - int format_length; + vfprintf_maybe_filtered (stream, format, args, 1); +} - format_length = strlen (format); +void +vfprintf_unfiltered (stream, format, args) + FILE *stream; + char *format; + va_list args; +{ + char *linebuffer; + struct cleanup *old_cleanups; - /* Reallocate buffer to a larger size if this is necessary. */ - if (format_length * 2 > MIN_LINEBUF) + vasprintf (&linebuffer, format, args); + if (linebuffer == NULL) { - linebuffer = alloca (10 + format_length * 2); + fputs_unfiltered ("\ngdb: virtual memory exhausted.\n", gdb_stderr); + exit (1); } - - /* This won't blow up if the restrictions described above are - followed. */ - vsprintf (linebuffer, format, args); - - fputs_filtered (linebuffer, stream); + old_cleanups = make_cleanup (free, linebuffer); + fputs_unfiltered (linebuffer, stream); + do_cleanups (old_cleanups); } void @@ -1233,7 +1431,15 @@ vprintf_filtered (format, args) char *format; va_list args; { - vfprintf_filtered (stdout, format, args); + vfprintf_maybe_filtered (gdb_stdout, format, args, 1); +} + +void +vprintf_unfiltered (format, args) + char *format; + va_list args; +{ + vfprintf_unfiltered (gdb_stdout, format, args); } /* VARARGS */ @@ -1249,13 +1455,28 @@ fprintf_filtered (va_alist) stream = va_arg (args, FILE *); format = va_arg (args, char *); - /* This won't blow up if the restrictions described above are - followed. */ vfprintf_filtered (stream, format, args); va_end (args); } -/* Like fprintf_filtered, but prints it's result indent. +/* VARARGS */ +void +fprintf_unfiltered (va_alist) + va_dcl +{ + va_list args; + FILE *stream; + char *format; + + va_start (args); + stream = va_arg (args, FILE *); + format = va_arg (args, char *); + + vfprintf_unfiltered (stream, format, args); + va_end (args); +} + +/* Like fprintf_filtered, but prints its result indented. Called as fprintfi_filtered (spaces, stream, format, ...); */ /* VARARGS */ @@ -1274,12 +1495,11 @@ fprintfi_filtered (va_alist) format = va_arg (args, char *); print_spaces_filtered (spaces, stream); - /* This won't blow up if the restrictions described above are - followed. */ vfprintf_filtered (stream, format, args); va_end (args); } + /* VARARGS */ void printf_filtered (va_alist) @@ -1291,7 +1511,23 @@ printf_filtered (va_alist) va_start (args); format = va_arg (args, char *); - vfprintf_filtered (stdout, format, args); + vfprintf_filtered (gdb_stdout, format, args); + va_end (args); +} + + +/* VARARGS */ +void +printf_unfiltered (va_alist) + va_dcl +{ + va_list args; + char *format; + + va_start (args); + format = va_arg (args, char *); + + vfprintf_unfiltered (gdb_stdout, format, args); va_end (args); } @@ -1310,8 +1546,8 @@ printfi_filtered (va_alist) va_start (args); spaces = va_arg (args, int); format = va_arg (args, char *); - print_spaces_filtered (spaces, stdout); - vfprintf_filtered (stdout, format, args); + print_spaces_filtered (spaces, gdb_stdout); + vfprintf_filtered (gdb_stdout, format, args); va_end (args); } @@ -1324,7 +1560,14 @@ void puts_filtered (string) char *string; { - fputs_filtered (string, stdout); + fputs_filtered (string, gdb_stdout); +} + +void +puts_unfiltered (string) + char *string; +{ + fputs_unfiltered (string, gdb_stdout); } /* Return a pointer to N spaces and a null. The pointer is good @@ -1512,7 +1755,7 @@ _initialize_utils () #endif #endif /* If the output is not a terminal, don't paginate it. */ - if (!ISATTY (stdout)) + if (!ISATTY (gdb_stdout)) lines_per_page = UINT_MAX; set_width_command ((char *)NULL, 0, c); diff --git a/gnu/usr.bin/gdb/gdb/valarith.c b/gnu/usr.bin/gdb/gdb/valarith.c index 3711a150d28c..acdf159002ac 100644 --- a/gnu/usr.bin/gdb/gdb/valarith.c +++ b/gnu/usr.bin/gdb/gdb/valarith.c @@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "expression.h" #include "target.h" #include "language.h" +#include "demangle.h" #include /* Define whether or not the C operator '/' truncates towards zero for @@ -33,15 +34,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define TRUNCATION_TOWARDS_ZERO ((-5 / 2) == -2) #endif -static value -value_subscripted_rvalue PARAMS ((value, value)); +static value_ptr value_subscripted_rvalue PARAMS ((value_ptr, value_ptr)); -value +value_ptr value_add (arg1, arg2) - value arg1, arg2; + value_ptr arg1, arg2; { - register value valint, valptr; + register value_ptr valint, valptr; register int len; COERCE_ARRAY (arg1); @@ -74,9 +74,9 @@ value_add (arg1, arg2) return value_binop (arg1, arg2, BINOP_ADD); } -value +value_ptr value_sub (arg1, arg2) - value arg1, arg2; + value_ptr arg1, arg2; { COERCE_ARRAY (arg1); @@ -118,17 +118,18 @@ an integer nor a pointer of the same type."); FIXME: Perhaps we should validate that the index is valid and if verbosity is set, warn about invalid indices (but still use them). */ -value +value_ptr value_subscript (array, idx) - value array, idx; + value_ptr array, idx; { int lowerbound; - value bound; + value_ptr bound; struct type *range_type; COERCE_REF (array); - if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_ARRAY) + if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_ARRAY + || TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_STRING) { range_type = TYPE_FIELD_TYPE (VALUE_TYPE (array), 0); lowerbound = TYPE_FIELD_BITPOS (range_type, 0); @@ -141,6 +142,7 @@ value_subscript (array, idx) { return value_subscripted_rvalue (array, idx); } + array = value_coerce_array (array); } return value_ind (value_add (array, idx)); } @@ -149,14 +151,14 @@ value_subscript (array, idx) (eg, a vector register). This routine used to promote floats to doubles, but no longer does. */ -static value +static value_ptr value_subscripted_rvalue (array, idx) - value array, idx; + value_ptr array, idx; { struct type *elt_type = TYPE_TARGET_TYPE (VALUE_TYPE (array)); int elt_size = TYPE_LENGTH (elt_type); int elt_offs = elt_size * longest_to_int (value_as_long (idx)); - value v; + value_ptr v; if (elt_offs >= TYPE_LENGTH (VALUE_TYPE (array))) error ("no such vector element"); @@ -183,7 +185,7 @@ value_subscripted_rvalue (array, idx) int binop_user_defined_p (op, arg1, arg2) enum exp_opcode op; - value arg1, arg2; + value_ptr arg1, arg2; { if (op == BINOP_ASSIGN) return 0; @@ -203,7 +205,7 @@ binop_user_defined_p (op, arg1, arg2) int unop_user_defined_p (op, arg1) enum exp_opcode op; - value arg1; + value_ptr arg1; { if (op == UNOP_ADDR) return 0; @@ -221,12 +223,12 @@ int unop_user_defined_p (op, arg1) is the opcode saying how to modify it. Otherwise, OTHEROP is unused. */ -value +value_ptr value_x_binop (arg1, arg2, op, otherop) - value arg1, arg2; + value_ptr arg1, arg2; enum exp_opcode op, otherop; { - value * argvec; + value_ptr * argvec; char *ptr; char tstr[13]; int static_memfuncp; @@ -242,7 +244,7 @@ value_x_binop (arg1, arg2, op, otherop) if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT) error ("Can't do that binary op on that type"); /* FIXME be explicit */ - argvec = (value *) alloca (sizeof (value) * 4); + argvec = (value_ptr *) alloca (sizeof (value_ptr) * 4); argvec[1] = value_addr (arg1); argvec[2] = arg2; argvec[3] = 0; @@ -294,7 +296,9 @@ value_x_binop (arg1, arg2, op, otherop) default: error ("Invalid binary operation specified."); } + argvec[0] = value_struct_elt (&arg1, argvec+1, tstr, &static_memfuncp, "structure"); + if (argvec[0]) { if (static_memfuncp) @@ -316,14 +320,14 @@ value_x_binop (arg1, arg2, op, otherop) and return that value (where '@' is (almost) any unary operator which is legal for GNU C++). */ -value +value_ptr value_x_unop (arg1, op) - value arg1; + value_ptr arg1; enum exp_opcode op; { - value * argvec; - char *ptr; - char tstr[13]; + value_ptr * argvec; + char *ptr, *mangle_ptr; + char tstr[13], mangle_tstr[13]; int static_memfuncp; COERCE_ENUM (arg1); @@ -334,13 +338,15 @@ value_x_unop (arg1, op) if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT) error ("Can't do that unary op on that type"); /* FIXME be explicit */ - argvec = (value *) alloca (sizeof (value) * 3); + argvec = (value_ptr *) alloca (sizeof (value_ptr) * 3); argvec[1] = value_addr (arg1); argvec[2] = 0; /* make the right function name up */ strcpy(tstr,"operator__"); ptr = tstr+8; + strcpy(mangle_tstr, "__"); + mangle_ptr = mangle_tstr+2; switch (op) { case UNOP_PREINCREMENT: strcpy(ptr,"++"); break; @@ -353,7 +359,9 @@ value_x_unop (arg1, op) default: error ("Invalid binary operation specified."); } + argvec[0] = value_struct_elt (&arg1, argvec+1, tstr, &static_memfuncp, "structure"); + if (argvec[0]) { if (static_memfuncp) @@ -389,11 +397,11 @@ value_x_unop (arg1, op) string values of length 1. */ -value +value_ptr value_concat (arg1, arg2) - value arg1, arg2; + value_ptr arg1, arg2; { - register value inval1, inval2, outval; + register value_ptr inval1, inval2, outval; int inval1len, inval2len; int count, idx; char *ptr; @@ -508,43 +516,43 @@ value_concat (arg1, arg2) } + /* Perform a binary operation on two operands which have reasonable representations as integers or floats. This includes booleans, characters, integers, or floats. Does not support addition and subtraction on pointers; use value_add or value_sub if you want to handle those possibilities. */ -value +value_ptr value_binop (arg1, arg2, op) - value arg1, arg2; + value_ptr arg1, arg2; enum exp_opcode op; { - register value val; + register value_ptr val; COERCE_ENUM (arg1); COERCE_ENUM (arg2); if ((TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_FLT - && - TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_CHAR - && - TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT - && - TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_BOOL) + && TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_CHAR + && TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT + && TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_BOOL + && TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_RANGE) || (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_FLT - && - TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_CHAR - && - TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT - && - TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_BOOL)) + && TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_CHAR + && TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT + && TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_BOOL + && TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_RANGE)) error ("Argument to arithmetic operation not a number or boolean."); if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_FLT || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_FLT) { + /* FIXME-if-picky-about-floating-accuracy: Should be doing this + in target format. real.c in GCC probably has the necessary + code. */ double v1, v2, v; v1 = value_as_double (arg1); v2 = value_as_double (arg2); @@ -571,8 +579,8 @@ value_binop (arg1, arg2, op) } val = allocate_value (builtin_type_double); - SWAP_TARGET_AND_HOST (&v, sizeof (v)); - *(double *) VALUE_CONTENTS_RAW (val) = v; + store_floating (VALUE_CONTENTS_RAW (val), TYPE_LENGTH (VALUE_TYPE (val)), + v); } else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_BOOL && @@ -702,7 +710,19 @@ value_binop (arg1, arg2, op) error ("Invalid binary operation on numbers."); } - val = allocate_value (BUILTIN_TYPE_UNSIGNED_LONGEST); + /* This is a kludge to get around the fact that we don't + know how to determine the result type from the types of + the operands. (I'm not really sure how much we feel the + need to duplicate the exact rules of the current + language. They can get really hairy. But not to do so + makes it hard to document just what we *do* do). */ + + /* Can't just call init_type because we wouldn't know what + name to give the type. */ + val = allocate_value + (sizeof (LONGEST) > TARGET_LONG_BIT / HOST_CHAR_BIT + ? builtin_type_unsigned_long_long + : builtin_type_unsigned_long); store_unsigned_integer (VALUE_CONTENTS_RAW (val), TYPE_LENGTH (VALUE_TYPE (val)), v); @@ -799,8 +819,20 @@ value_binop (arg1, arg2, op) default: error ("Invalid binary operation on numbers."); } - - val = allocate_value (BUILTIN_TYPE_LONGEST); + + /* This is a kludge to get around the fact that we don't + know how to determine the result type from the types of + the operands. (I'm not really sure how much we feel the + need to duplicate the exact rules of the current + language. They can get really hairy. But not to do so + makes it hard to document just what we *do* do). */ + + /* Can't just call init_type because we wouldn't know what + name to give the type. */ + val = allocate_value + (sizeof (LONGEST) > TARGET_LONG_BIT / HOST_CHAR_BIT + ? builtin_type_long_long + : builtin_type_long); store_signed_integer (VALUE_CONTENTS_RAW (val), TYPE_LENGTH (VALUE_TYPE (val)), v); @@ -814,7 +846,7 @@ value_binop (arg1, arg2, op) int value_logical_not (arg1) - value arg1; + value_ptr arg1; { register int len; register char *p; @@ -841,7 +873,7 @@ value_logical_not (arg1) int value_equal (arg1, arg2) - register value arg1, arg2; + register value_ptr arg1, arg2; { register int len; @@ -893,7 +925,7 @@ value_equal (arg1, arg2) int value_less (arg1, arg2) - register value arg1, arg2; + register value_ptr arg1, arg2; { register enum type_code code1; register enum type_code code2; @@ -935,9 +967,9 @@ value_less (arg1, arg2) /* The unary operators - and ~. Both free the argument ARG1. */ -value +value_ptr value_neg (arg1) - register value arg1; + register value_ptr arg1; { register struct type *type; @@ -955,9 +987,9 @@ value_neg (arg1) } } -value +value_ptr value_complement (arg1) - register value arg1; + register value_ptr arg1; { COERCE_ENUM (arg1); @@ -967,3 +999,70 @@ value_complement (arg1) return value_from_longest (VALUE_TYPE (arg1), ~ value_as_long (arg1)); } +/* The INDEX'th bit of SET value whose VALUE_TYPE is TYPE, + and whose VALUE_CONTENTS is valaddr. + Return -1 if out of range, -2 other error. */ + +int +value_bit_index (type, valaddr, index) + struct type *type; + char *valaddr; + int index; +{ + struct type *range; + int low_bound, high_bound, bit_length; + LONGEST word; + range = TYPE_FIELD_TYPE (type, 0); + if (TYPE_CODE (range) != TYPE_CODE_RANGE) + return -2; + low_bound = TYPE_LOW_BOUND (range); + high_bound = TYPE_HIGH_BOUND (range); + if (index < low_bound || index > high_bound) + return -1; + bit_length = high_bound - low_bound + 1; + index -= low_bound; + if (bit_length <= TARGET_CHAR_BIT) + word = unpack_long (builtin_type_unsigned_char, valaddr); + else if (bit_length <= TARGET_SHORT_BIT) + word = unpack_long (builtin_type_unsigned_short, valaddr); + else + { + int word_start_index = (index / TARGET_INT_BIT) * TARGET_INT_BIT; + index -= word_start_index; + word = unpack_long (builtin_type_unsigned_int, + valaddr + (word_start_index / HOST_CHAR_BIT)); + } +#if BITS_BIG_ENDIAN + if (bit_length <= TARGET_CHAR_BIT) + index = TARGET_CHAR_BIT - 1 - index; + else if (bit_length <= TARGET_SHORT_BIT) + index = TARGET_SHORT_BIT - 1 - index; + else + index = TARGET_INT_BIT - 1 - index; +#endif + return (word >> index) & 1; +} + +value_ptr +value_in (element, set) + value_ptr element, set; +{ + int member; + if (TYPE_CODE (VALUE_TYPE (set)) != TYPE_CODE_SET) + error ("Second argument of 'IN' has wrong type"); + if (TYPE_CODE (VALUE_TYPE (element)) != TYPE_CODE_INT + && TYPE_CODE (VALUE_TYPE (element)) != TYPE_CODE_CHAR + && TYPE_CODE (VALUE_TYPE (element)) != TYPE_CODE_ENUM + && TYPE_CODE (VALUE_TYPE (element)) != TYPE_CODE_BOOL) + error ("First argument of 'IN' has wrong type"); + member = value_bit_index (VALUE_TYPE (set), VALUE_CONTENTS (set), + value_as_long (element)); + if (member < 0) + error ("First argument of 'IN' not in range"); + return value_from_longest (builtin_type_int, member); +} + +void +_initialize_valarith () +{ +} diff --git a/gnu/usr.bin/gdb/gdb/valops.c b/gnu/usr.bin/gdb/gdb/valops.c index dc4d82a8651c..444ed1408e99 100644 --- a/gnu/usr.bin/gdb/gdb/valops.c +++ b/gnu/usr.bin/gdb/gdb/valops.c @@ -1,5 +1,6 @@ /* Perform non-arithmetic operations on values, for GDB. - Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc. + Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -32,24 +33,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Local functions. */ -static int -typecmp PARAMS ((int staticp, struct type *t1[], value t2[])); +static int typecmp PARAMS ((int staticp, struct type *t1[], value_ptr t2[])); -static CORE_ADDR -find_function_addr PARAMS ((value, struct type **)); +static CORE_ADDR find_function_addr PARAMS ((value_ptr, struct type **)); -static CORE_ADDR -value_push PARAMS ((CORE_ADDR, value)); +static CORE_ADDR value_push PARAMS ((CORE_ADDR, value_ptr)); -static CORE_ADDR -value_arg_push PARAMS ((CORE_ADDR, value)); +static CORE_ADDR value_arg_push PARAMS ((CORE_ADDR, value_ptr)); -static value -search_struct_field PARAMS ((char *, value, int, struct type *, int)); +static value_ptr search_struct_field PARAMS ((char *, value_ptr, int, + struct type *, int)); -static value -search_struct_method PARAMS ((char *, value *, value *, int, int *, - struct type *)); +static value_ptr search_struct_method PARAMS ((char *, value_ptr *, + value_ptr *, + int, int *, struct type *)); static int check_field_in PARAMS ((struct type *, const char *)); @@ -65,11 +62,11 @@ static CORE_ADDR allocate_space_in_inferior (len) int len; { - register value val; + register value_ptr val; register struct symbol *sym; struct minimal_symbol *msymbol; struct type *type; - value blocklen; + value_ptr blocklen; LONGEST maddr; /* Find the address of malloc in the inferior. */ @@ -114,10 +111,10 @@ allocate_space_in_inferior (len) and if ARG2 is an lvalue it can be cast into anything at all. */ /* In C++, casts may change pointer or object representations. */ -value +value_ptr value_cast (type, arg2) struct type *type; - register value arg2; + register value_ptr arg2; { register enum type_code code1; register enum type_code code2; @@ -140,8 +137,8 @@ value_cast (type, arg2) /* Look in the type of the source to see if it contains the type of the target as a superclass. If so, we'll need to offset the object in addition to changing its type. */ - value v = search_struct_field (type_name_no_tag (type), - arg2, 0, VALUE_TYPE (arg2), 1); + value_ptr v = search_struct_field (type_name_no_tag (type), + arg2, 0, VALUE_TYPE (arg2), 1); if (v) { VALUE_TYPE (v) = type; @@ -166,8 +163,8 @@ value_cast (type, arg2) && TYPE_CODE (t2) == TYPE_CODE_STRUCT && TYPE_NAME (t1) != 0) /* if name unknown, can't have supercl */ { - value v = search_struct_field (type_name_no_tag (t1), - value_ind (arg2), 0, t2, 1); + value_ptr v = search_struct_field (type_name_no_tag (t1), + value_ind (arg2), 0, t2, 1); if (v) { v = value_addr (v); @@ -197,12 +194,12 @@ value_cast (type, arg2) /* Create a value of type TYPE that is zero, and return it. */ -value +value_ptr value_zero (type, lv) struct type *type; enum lval_type lv; { - register value val = allocate_value (type); + register value_ptr val = allocate_value (type); memset (VALUE_CONTENTS (val), 0, TYPE_LENGTH (type)); VALUE_LVAL (val) = lv; @@ -219,12 +216,17 @@ value_zero (type, lv) is tested in the VALUE_CONTENTS macro, which is used if and when the contents are actually required. */ -value +value_ptr value_at (type, addr) struct type *type; CORE_ADDR addr; { - register value val = allocate_value (type); + register value_ptr val; + + if (TYPE_CODE (type) == TYPE_CODE_VOID) + error ("Attempt to dereference a generic pointer."); + + val = allocate_value (type); read_memory (addr, VALUE_CONTENTS_RAW (val), TYPE_LENGTH (type)); @@ -236,12 +238,17 @@ value_at (type, addr) /* Return a lazy value with type TYPE located at ADDR (cf. value_at). */ -value +value_ptr value_at_lazy (type, addr) struct type *type; CORE_ADDR addr; { - register value val = allocate_value (type); + register value_ptr val; + + if (TYPE_CODE (type) == TYPE_CODE_VOID) + error ("Attempt to dereference a generic pointer."); + + val = allocate_value (type); VALUE_LVAL (val) = lval_memory; VALUE_ADDRESS (val) = addr; @@ -264,7 +271,7 @@ value_at_lazy (type, addr) int value_fetch_lazy (val) - register value val; + register value_ptr val; { CORE_ADDR addr = VALUE_ADDRESS (val) + VALUE_OFFSET (val); @@ -279,19 +286,22 @@ value_fetch_lazy (val) /* Store the contents of FROMVAL into the location of TOVAL. Return a new value with the location of TOVAL and contents of FROMVAL. */ -value +value_ptr value_assign (toval, fromval) - register value toval, fromval; + register value_ptr toval, fromval; { - register struct type *type = VALUE_TYPE (toval); - register value val; + register struct type *type; + register value_ptr val; char raw_buffer[MAX_REGISTER_RAW_SIZE]; - char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; int use_buffer = 0; + if (!toval->modifiable) + error ("Left operand of assignment is not a modifiable lvalue."); + COERCE_ARRAY (fromval); COERCE_REF (toval); + type = VALUE_TYPE (toval); if (VALUE_LVAL (toval) != lval_internalvar) fromval = value_cast (type, fromval); @@ -300,17 +310,19 @@ value_assign (toval, fromval) convert FROMVAL's contents now, with result in `raw_buffer', and set USE_BUFFER to the number of bytes to write. */ +#ifdef REGISTER_CONVERTIBLE if (VALUE_REGNO (toval) >= 0 && REGISTER_CONVERTIBLE (VALUE_REGNO (toval))) { int regno = VALUE_REGNO (toval); - if (VALUE_TYPE (fromval) != REGISTER_VIRTUAL_TYPE (regno)) - fromval = value_cast (REGISTER_VIRTUAL_TYPE (regno), fromval); - memcpy (virtual_buffer, VALUE_CONTENTS (fromval), - REGISTER_VIRTUAL_SIZE (regno)); - REGISTER_CONVERT_TO_RAW (regno, virtual_buffer, raw_buffer); - use_buffer = REGISTER_RAW_SIZE (regno); + if (REGISTER_CONVERTIBLE (regno)) + { + REGISTER_CONVERT_TO_RAW (VALUE_TYPE (fromval), regno, + VALUE_CONTENTS (fromval), raw_buffer); + use_buffer = REGISTER_RAW_SIZE (regno); + } } +#endif switch (VALUE_LVAL (toval)) { @@ -329,13 +341,24 @@ value_assign (toval, fromval) case lval_memory: if (VALUE_BITSIZE (toval)) { - int v; /* FIXME, this won't work for large bitfields */ + char buffer[sizeof (LONGEST)]; + /* We assume that the argument to read_memory is in units of + host chars. FIXME: Is that correct? */ + int len = (VALUE_BITPOS (toval) + + VALUE_BITSIZE (toval) + + HOST_CHAR_BIT - 1) + / HOST_CHAR_BIT; + + if (len > sizeof (LONGEST)) + error ("Can't handle bitfields which don't fit in a %d bit word.", + sizeof (LONGEST) * HOST_CHAR_BIT); + read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), - (char *) &v, sizeof v); - modify_field ((char *) &v, value_as_long (fromval), + buffer, len); + modify_field (buffer, value_as_long (fromval), VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), - (char *)&v, sizeof v); + buffer, len); } else if (use_buffer) write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), @@ -348,14 +371,26 @@ value_assign (toval, fromval) case lval_register: if (VALUE_BITSIZE (toval)) { - int v; + char buffer[sizeof (LONGEST)]; + int len = REGISTER_RAW_SIZE (VALUE_REGNO (toval)); - read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), - (char *) &v, sizeof v); - modify_field ((char *) &v, value_as_long (fromval), - VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); - write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), - (char *) &v, sizeof v); + if (len > sizeof (LONGEST)) + error ("Can't handle bitfields in registers larger than %d bits.", + sizeof (LONGEST) * HOST_CHAR_BIT); + + if (VALUE_BITPOS (toval) + VALUE_BITSIZE (toval) + > len * HOST_CHAR_BIT) + /* Getting this right would involve being very careful about + byte order. */ + error ("\ +Can't handle bitfield which doesn't fit in a single register."); + + read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), + buffer, len); + modify_field (buffer, value_as_long (fromval), + VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); + write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), + buffer, len); } else if (use_buffer) write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), @@ -374,6 +409,12 @@ value_assign (toval, fromval) VALUE_CONTENTS (fromval), TYPE_LENGTH (type)); #endif } + /* Assigning to the stack pointer, frame pointer, and other + (architecture and calling convention specific) registers may + cause the frame cache to be out of date. We just do this + on all assignments to registers for simplicity; I doubt the slowdown + matters. */ + reinit_frame_cache (); break; case lval_reg_frame_relative: @@ -386,7 +427,12 @@ value_assign (toval, fromval) int byte_offset = VALUE_OFFSET (toval) % reg_size; int reg_offset = VALUE_OFFSET (toval) / reg_size; int amount_copied; - char *buffer = (char *) alloca (amount_to_copy); + + /* Make the buffer large enough in all cases. */ + char *buffer = (char *) alloca (amount_to_copy + + sizeof (LONGEST) + + MAX_REGISTER_RAW_SIZE); + int regno; FRAME frame; @@ -451,7 +497,7 @@ value_assign (toval, fromval) default: - error ("Left side of = operation is not an lvalue."); + error ("Left operand of assignment is not an lvalue."); } /* Return a value just like TOVAL except with the contents of FROMVAL @@ -463,9 +509,6 @@ value_assign (toval, fromval) type = VALUE_TYPE (fromval); } - /* FIXME: This loses if fromval is a different size than toval, for - example because fromval got cast in the REGISTER_CONVERTIBLE case - above. */ val = allocate_value (type); memcpy (val, toval, VALUE_CONTENTS_RAW (val) - (char *) val); memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS (fromval), @@ -477,12 +520,12 @@ value_assign (toval, fromval) /* Extend a value VAL to COUNT repetitions of its type. */ -value +value_ptr value_repeat (arg1, count) - value arg1; + value_ptr arg1; int count; { - register value val; + register value_ptr val; if (VALUE_LVAL (arg1) != lval_memory) error ("Only values in memory can be extended with '@'."); @@ -500,12 +543,12 @@ value_repeat (arg1, count) return val; } -value +value_ptr value_of_variable (var, b) struct symbol *var; struct block *b; { - value val; + value_ptr val; FRAME fr; if (b == NULL) @@ -553,9 +596,9 @@ value_of_variable (var, b) the coercion to pointer type. */ -value +value_ptr value_coerce_array (arg1) - value arg1; + value_ptr arg1; { register struct type *type; @@ -563,7 +606,8 @@ value_coerce_array (arg1) error ("Attempt to take address of value not located in memory."); /* Get type of elements. */ - if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY) + if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY + || TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRING) type = TYPE_TARGET_TYPE (VALUE_TYPE (arg1)); else /* A phony array made by value_repeat. @@ -577,9 +621,9 @@ value_coerce_array (arg1) /* Given a value which is a function, return a value which is a pointer to it. */ -value +value_ptr value_coerce_function (arg1) - value arg1; + value_ptr arg1; { if (VALUE_LVAL (arg1) != lval_memory) @@ -591,9 +635,9 @@ value_coerce_function (arg1) /* Return a pointer value for the object for which ARG1 is the contents. */ -value +value_ptr value_addr (arg1) - value arg1; + value_ptr arg1; { struct type *type = VALUE_TYPE (arg1); if (TYPE_CODE (type) == TYPE_CODE_REF) @@ -601,7 +645,7 @@ value_addr (arg1) /* Copy the value, but change the type from (T&) to (T*). We keep the same location information, which is efficient, and allows &(&X) to get the location containing the reference. */ - value arg2 = value_copy (arg1); + value_ptr arg2 = value_copy (arg1); VALUE_TYPE (arg2) = lookup_pointer_type (TYPE_TARGET_TYPE (type)); return arg2; } @@ -620,9 +664,9 @@ value_addr (arg1) /* Given a value of a pointer type, apply the C unary * operator to it. */ -value +value_ptr value_ind (arg1) - value arg1; + value_ptr arg1; { COERCE_ARRAY (arg1); @@ -650,9 +694,9 @@ value_ind (arg1) CORE_ADDR push_word (sp, word) CORE_ADDR sp; - REGISTER_TYPE word; + unsigned LONGEST word; { - register int len = sizeof (REGISTER_TYPE); + register int len = REGISTER_SIZE; char buffer[MAX_REGISTER_RAW_SIZE]; store_unsigned_integer (buffer, len, word); @@ -691,7 +735,7 @@ push_bytes (sp, buffer, len) static CORE_ADDR value_push (sp, arg) register CORE_ADDR sp; - value arg; + value_ptr arg; { register int len = TYPE_LENGTH (VALUE_TYPE (arg)); @@ -709,9 +753,9 @@ value_push (sp, arg) /* Perform the standard coercions that are specified for arguments to be passed to C functions. */ -value +value_ptr value_arg_coerce (arg) - value arg; + value_ptr arg; { register struct type *type; @@ -751,7 +795,7 @@ value_arg_coerce (arg) static CORE_ADDR value_arg_push (sp, arg) register CORE_ADDR sp; - value arg; + value_ptr arg; { return value_push (sp, value_arg_coerce (arg)); } @@ -761,7 +805,7 @@ value_arg_push (sp, arg) static CORE_ADDR find_function_addr (function, retval_type) - value function; + value_ptr function; struct type **retval_type; { register struct type *ftype = VALUE_TYPE (function); @@ -823,20 +867,21 @@ find_function_addr (function, retval_type) May fail to return, if a breakpoint or signal is hit during the execution of the function. */ -value +value_ptr call_function_by_hand (function, nargs, args) - value function; + value_ptr function; int nargs; - value *args; + value_ptr *args; { register CORE_ADDR sp; register int i; CORE_ADDR start_sp; - /* CALL_DUMMY is an array of words (REGISTER_TYPE), but each word - is in host byte order. It is switched to target byte order before calling - FIX_CALL_DUMMY. */ - static REGISTER_TYPE dummy[] = CALL_DUMMY; - REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)]; + /* CALL_DUMMY is an array of words (REGISTER_SIZE), but each word + is in host byte order. Before calling FIX_CALL_DUMMY, we byteswap it + and remove any extra bytes which might exist because unsigned LONGEST is + bigger than REGISTER_SIZE. */ + static unsigned LONGEST dummy[] = CALL_DUMMY; + char dummy1[REGISTER_SIZE * sizeof dummy / sizeof (unsigned LONGEST)]; CORE_ADDR old_sp; struct type *value_type; unsigned char struct_return; @@ -884,8 +929,9 @@ call_function_by_hand (function, nargs, args) /* Create a call sequence customized for this function and the number of arguments for it. */ - for (i = 0; i < sizeof dummy / sizeof (REGISTER_TYPE); i++) - store_unsigned_integer (&dummy1[i], sizeof (REGISTER_TYPE), + for (i = 0; i < sizeof dummy / sizeof (dummy[0]); i++) + store_unsigned_integer (&dummy1[i * REGISTER_SIZE], + REGISTER_SIZE, (unsigned LONGEST)dummy[i]); #ifdef GDB_TARGET_IS_HPPA @@ -978,30 +1024,30 @@ call_function_by_hand (function, nargs, args) #if defined (REG_STRUCT_HAS_ADDR) { - /* This is a machine like the sparc, where we need to pass a pointer + /* This is a machine like the sparc, where we may need to pass a pointer to the structure, not the structure itself. */ - if (REG_STRUCT_HAS_ADDR (using_gcc)) - for (i = nargs - 1; i >= 0; i--) - if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT) - { - CORE_ADDR addr; + for (i = nargs - 1; i >= 0; i--) + if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT + && REG_STRUCT_HAS_ADDR (using_gcc, VALUE_TYPE (args[i]))) + { + CORE_ADDR addr; #if !(1 INNER_THAN 2) - /* The stack grows up, so the address of the thing we push - is the stack pointer before we push it. */ - addr = sp; + /* The stack grows up, so the address of the thing we push + is the stack pointer before we push it. */ + addr = sp; #endif - /* Push the structure. */ - sp = value_push (sp, args[i]); + /* Push the structure. */ + sp = value_push (sp, args[i]); #if 1 INNER_THAN 2 - /* The stack grows down, so the address of the thing we push - is the stack pointer after we push it. */ - addr = sp; + /* The stack grows down, so the address of the thing we push + is the stack pointer after we push it. */ + addr = sp; #endif - /* The value we're going to pass is the address of the thing - we just pushed. */ - args[i] = value_from_longest (lookup_pointer_type (value_type), - (LONGEST) addr); - } + /* The value we're going to pass is the address of the thing + we just pushed. */ + args[i] = value_from_longest (lookup_pointer_type (value_type), + (LONGEST) addr); + } } #endif /* REG_STRUCT_HAS_ADDR. */ @@ -1064,6 +1110,7 @@ call_function_by_hand (function, nargs, args) char format[80]; sprintf (format, "at %s", local_hex_format ()); name = alloca (80); + /* FIXME-32x64: assumes funaddr fits in a long. */ sprintf (name, format, (unsigned long) funaddr); } @@ -1105,11 +1152,11 @@ the function call).", name); } } #else /* no CALL_DUMMY. */ -value +value_ptr call_function_by_hand (function, nargs, args) - value function; + value_ptr function; int nargs; - value *args; + value_ptr *args; { error ("Cannot invoke functions on this machine."); } @@ -1126,16 +1173,16 @@ call_function_by_hand (function, nargs, args) first element, and all elements must have the same size (though we don't currently enforce any restriction on their types). */ -value +value_ptr value_array (lowbound, highbound, elemvec) int lowbound; int highbound; - value *elemvec; + value_ptr *elemvec; { int nelem; int idx; int typelength; - value val; + value_ptr val; struct type *rangetype; struct type *arraytype; CORE_ADDR addr; @@ -1187,12 +1234,12 @@ value_array (lowbound, highbound, elemvec) zero and an upper bound of LEN - 1. Also note that the string may contain embedded null bytes. */ -value +value_ptr value_string (ptr, len) char *ptr; int len; { - value val; + value_ptr val; struct type *rangetype; struct type *stringtype; CORE_ADDR addr; @@ -1232,7 +1279,7 @@ static int typecmp (staticp, t1, t2) int staticp; struct type *t1[]; - value t2[]; + value_ptr t2[]; { int i; @@ -1246,21 +1293,27 @@ typecmp (staticp, t1, t2) if (t1[!staticp] == 0) return 0; for (i = !staticp; t1[i] && TYPE_CODE (t1[i]) != TYPE_CODE_VOID; i++) { + struct type *tt1, *tt2; if (! t2[i]) return i+1; - if (TYPE_CODE (t1[i]) == TYPE_CODE_REF + tt1 = t1[i]; + tt2 = VALUE_TYPE(t2[i]); + if (TYPE_CODE (tt1) == TYPE_CODE_REF /* We should be doing hairy argument matching, as below. */ - && (TYPE_CODE (TYPE_TARGET_TYPE (t1[i])) - == TYPE_CODE (VALUE_TYPE (t2[i])))) + && (TYPE_CODE (TYPE_TARGET_TYPE (tt1)) == TYPE_CODE (tt2))) { t2[i] = value_addr (t2[i]); continue; } - if (TYPE_CODE (t1[i]) == TYPE_CODE_PTR - && TYPE_CODE (VALUE_TYPE (t2[i])) == TYPE_CODE_ARRAY) - /* Array to pointer is a `trivial conversion' according to the ARM. */ - continue; + while (TYPE_CODE (tt1) == TYPE_CODE_PTR + && (TYPE_CODE(tt2)==TYPE_CODE_ARRAY || TYPE_CODE(tt2)==TYPE_CODE_PTR)) + { + tt1 = TYPE_TARGET_TYPE(tt1); + tt2 = TYPE_TARGET_TYPE(tt2); + } + if (TYPE_CODE(tt1) == TYPE_CODE(tt2)) continue; + /* Array to pointer is a `trivial conversion' according to the ARM. */ /* We should be doing much hairier argument matching (see section 13.2 of the ARM), but as a quick kludge, just check for the same type @@ -1280,10 +1333,10 @@ typecmp (staticp, t1, t2) If LOOKING_FOR_BASECLASS, then instead of looking for struct fields, look for a baseclass named NAME. */ -static value +static value_ptr search_struct_field (name, arg1, offset, type, looking_for_baseclass) char *name; - register value arg1; + register value_ptr arg1; int offset; register struct type *type; int looking_for_baseclass; @@ -1299,7 +1352,7 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass) if (t_field_name && STREQ (t_field_name, name)) { - value v; + value_ptr v; if (TYPE_FIELD_STATIC (type, i)) { char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, i); @@ -1321,7 +1374,7 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass) for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--) { - value v; + value_ptr v; /* If we are looking for baseclasses, this is what we get when we hit them. But it could happen that the base part's member name is not yet filled in. */ @@ -1331,7 +1384,7 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass) if (BASETYPE_VIA_VIRTUAL (type, i)) { - value v2; + value_ptr v2; /* Fix to use baseclass_offset instead. FIXME */ baseclass_addr (type, i, VALUE_CONTENTS (arg1) + offset, &v2, (int *)NULL); @@ -1360,20 +1413,31 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass) If found, return value, else if name matched and args not return (value)-1, else return NULL. */ -static value +static value_ptr search_struct_method (name, arg1p, args, offset, static_memfuncp, type) char *name; - register value *arg1p, *args; + register value_ptr *arg1p, *args; int offset, *static_memfuncp; register struct type *type; { int i; - static int name_matched = 0; + value_ptr v; + int name_matched = 0; + char dem_opname[64]; check_stub_type (type); for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--) { char *t_field_name = TYPE_FN_FIELDLIST_NAME (type, i); + if (strncmp(t_field_name, "__", 2)==0 || + strncmp(t_field_name, "op", 2)==0 || + strncmp(t_field_name, "type", 4)==0 ) + { + if (cplus_demangle_opname(t_field_name, dem_opname, DMGL_ANSI)) + t_field_name = dem_opname; + else if (cplus_demangle_opname(t_field_name, dem_opname, 0)) + t_field_name = dem_opname; + } if (t_field_name && STREQ (t_field_name, name)) { int j = TYPE_FN_FIELDLIST_LENGTH (type, i) - 1; @@ -1390,10 +1454,11 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type) TYPE_FN_FIELD_ARGS (f, j), args)) { if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) - return (value)value_virtual_fn_field (arg1p, f, j, type, offset); + return value_virtual_fn_field (arg1p, f, j, type, offset); if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp) *static_memfuncp = 1; - return (value)value_fn_field (arg1p, f, j, type, offset); + v = value_fn_field (arg1p, f, j, type, offset); + if (v != NULL) return v; } j--; } @@ -1402,7 +1467,6 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type) for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--) { - value v; int base_offset; if (BASETYPE_VIA_VIRTUAL (type, i)) @@ -1417,7 +1481,7 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type) } v = search_struct_method (name, arg1p, args, base_offset + offset, static_memfuncp, TYPE_BASECLASS (type, i)); - if (v == (value) -1) + if (v == (value_ptr) -1) { name_matched = 1; } @@ -1428,7 +1492,7 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type) return v; } } - if (name_matched) return (value) -1; + if (name_matched) return (value_ptr) -1; else return NULL; } @@ -1446,15 +1510,15 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type) ERR is an error message to be printed in case the field is not found. */ -value +value_ptr value_struct_elt (argp, args, name, static_memfuncp, err) - register value *argp, *args; + register value_ptr *argp, *args; char *name; int *static_memfuncp; char *err; { register struct type *t; - value v; + value_ptr v; COERCE_ARRAY (*argp); @@ -1500,7 +1564,9 @@ value_struct_elt (argp, args, name, static_memfuncp, err) v = search_struct_method (name, argp, args, 0, static_memfuncp, t); - if (v == 0) + if (v == (value_ptr) -1) + error ("Cannot take address of a method"); + else if (v == 0) { if (TYPE_NFN_FIELDS (t)) error ("There is no member or method named %s.", name); @@ -1515,9 +1581,10 @@ value_struct_elt (argp, args, name, static_memfuncp, err) if (!args[1]) { /* destructors are a special case. */ - return (value)value_fn_field (NULL, TYPE_FN_FIELDLIST1 (t, 0), - TYPE_FN_FIELDLIST_LENGTH (t, 0), - 0, 0); + v = value_fn_field (NULL, TYPE_FN_FIELDLIST1 (t, 0), + TYPE_FN_FIELDLIST_LENGTH (t, 0), 0, 0); + if (!v) error("could not find destructor function named %s.", name); + else return v; } else { @@ -1527,7 +1594,7 @@ value_struct_elt (argp, args, name, static_memfuncp, err) else v = search_struct_method (name, argp, args, 0, static_memfuncp, t); - if (v == (value) -1) + if (v == (value_ptr) -1) { error("Argument list of %s mismatch with component in the structure.", name); } @@ -1610,7 +1677,7 @@ check_field_in (type, name) int check_field (arg1, name) - register value arg1; + register value_ptr arg1; const char *name; { register struct type *t; @@ -1641,7 +1708,7 @@ check_field (arg1, name) "pointers to member functions". This function is used to resolve user expressions of the form "DOMAIN::NAME". */ -value +value_ptr value_struct_elt_for_reference (domain, offset, curtype, name, intype) struct type *domain, *curtype, *intype; int offset; @@ -1649,7 +1716,7 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype) { register struct type *t = curtype; register int i; - value v; + value_ptr v; if ( TYPE_CODE (t) != TYPE_CODE_STRUCT && TYPE_CODE (t) != TYPE_CODE_UNION) @@ -1697,7 +1764,19 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype) for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i) { - if (STREQ (TYPE_FN_FIELDLIST_NAME (t, i), name)) + char *t_field_name = TYPE_FN_FIELDLIST_NAME (t, i); + char dem_opname[64]; + + if (strncmp(t_field_name, "__", 2)==0 || + strncmp(t_field_name, "op", 2)==0 || + strncmp(t_field_name, "type", 4)==0 ) + { + if (cplus_demangle_opname(t_field_name, dem_opname, DMGL_ANSI)) + t_field_name = dem_opname; + else if (cplus_demangle_opname(t_field_name, dem_opname, 0)) + t_field_name = dem_opname; + } + if (t_field_name && STREQ (t_field_name, name)) { int j = TYPE_FN_FIELDLIST_LENGTH (t, i); struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i); @@ -1749,7 +1828,7 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype) } for (i = TYPE_N_BASECLASSES (t) - 1; i >= 0; i--) { - value v; + value_ptr v; int base_offset; if (BASETYPE_VIA_VIRTUAL (t, i)) @@ -1770,7 +1849,7 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype) /* C++: return the value of the class instance variable, if one exists. Flag COMPLAIN signals an error if the request is made in an inappropriate context. */ -value +value_ptr value_of_this (complain) int complain; { @@ -1779,7 +1858,7 @@ value_of_this (complain) struct block *b; int i; static const char funny_this[] = "this"; - value this; + value_ptr this; if (selected_frame == 0) if (complain) diff --git a/gnu/usr.bin/gdb/gdb/valprint.c b/gnu/usr.bin/gdb/gdb/valprint.c index b805645a4ce2..2214b16df487 100644 --- a/gnu/usr.bin/gdb/gdb/valprint.c +++ b/gnu/usr.bin/gdb/gdb/valprint.c @@ -1,5 +1,6 @@ /* Print values for GDB, the GNU debugger. - Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc. + Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -28,13 +29,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "obstack.h" #include "language.h" #include "demangle.h" +#include "annotate.h" #include /* Prototypes for local functions */ static void -print_hex_chars PARAMS ((FILE *, unsigned char *, unsigned int)); +print_hex_chars PARAMS ((GDB_FILE *, unsigned char *, unsigned int)); static void show_print PARAMS ((char *, int)); @@ -60,9 +62,6 @@ set_output_radix PARAMS ((char *, int, struct cmd_list_element *)); static void set_output_radix_1 PARAMS ((int, unsigned)); -static void -value_print_array_elements PARAMS ((value, FILE *, int, enum val_prettyprint)); - /* Maximum number of chars to print for a string pointer value or vector contents, or UINT_MAX for no limit. Note that "set print elements 0" stores UINT_MAX in print_max, which displays in a show command as @@ -83,8 +82,17 @@ int output_format = 0; unsigned int repeat_count_threshold = 10; -int prettyprint_structs; /* Controls pretty printing of structures */ -int prettyprint_arrays; /* Controls pretty printing of arrays. */ +/* If nonzero, stops printing of char arrays at first null. */ + +int stop_print_at_null; + +/* Controls pretty printing of structures. */ + +int prettyprint_structs; + +/* Controls pretty printing of arrays. */ + +int prettyprint_arrays; /* If nonzero, causes unions inside structures or other unions to be printed. */ @@ -121,7 +129,7 @@ val_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty) struct type *type; char *valaddr; CORE_ADDR address; - FILE *stream; + GDB_FILE *stream; int format; int deref_ref; int recurse; @@ -136,14 +144,13 @@ val_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty) /* Ensure that the type is complete and not just a stub. If the type is only a stub and we can't find and substitute its complete type, then - print appropriate string and return. Typical types that my be stubs - are structs, unions, and C++ methods. */ + print appropriate string and return. */ check_stub_type (type); if (TYPE_FLAGS (type) & TYPE_FLAG_STUB) { fprintf_filtered (stream, ""); - fflush (stream); + gdb_flush (stream); return (0); } @@ -158,13 +165,11 @@ val_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty) int value_print (val, stream, format, pretty) - value val; - FILE *stream; + value_ptr val; + GDB_FILE *stream; int format; enum val_prettyprint pretty; { - register unsigned int n, typelen; - if (val == 0) { printf_filtered ("
"); @@ -175,59 +180,7 @@ value_print (val, stream, format, pretty) printf_filtered (""); return 0; } - - /* A "repeated" value really contains several values in a row. - They are made by the @ operator. - Print such values as if they were arrays. */ - - if (VALUE_REPEATED (val)) - { - n = VALUE_REPETITIONS (val); - typelen = TYPE_LENGTH (VALUE_TYPE (val)); - fprintf_filtered (stream, "{"); - /* Print arrays of characters using string syntax. */ - if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT - && format == 0) - LA_PRINT_STRING (stream, VALUE_CONTENTS (val), n, 0); - else - { - value_print_array_elements (val, stream, format, pretty); - } - fprintf_filtered (stream, "}"); - return (n * typelen); - } - else - { - struct type *type = VALUE_TYPE (val); - - /* If it is a pointer, indicate what it points to. - - Print type also if it is a reference. - - C++: if it is a member pointer, we will take care - of that when we print it. */ - if (TYPE_CODE (type) == TYPE_CODE_PTR || - TYPE_CODE (type) == TYPE_CODE_REF) - { - /* Hack: remove (char *) for char strings. Their - type is indicated by the quoted string anyway. */ - if (TYPE_CODE (type) == TYPE_CODE_PTR && - TYPE_LENGTH (TYPE_TARGET_TYPE (type)) == sizeof(char) && - TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_INT && - !TYPE_UNSIGNED (TYPE_TARGET_TYPE (type))) - { - /* Print nothing */ - } - else - { - fprintf_filtered (stream, "("); - type_print (type, "", stream, -1); - fprintf_filtered (stream, ") "); - } - } - return (val_print (type, VALUE_CONTENTS (val), - VALUE_ADDRESS (val), stream, format, 1, 0, pretty)); - } + return LA_VALUE_PRINT (val, stream, format, pretty); } /* Called by various _val_print routines to print TYPE_CODE_INT's */ @@ -236,7 +189,7 @@ void val_print_type_code_int (type, valaddr, stream) struct type *type; char *valaddr; - FILE *stream; + GDB_FILE *stream; { char *p; /* Pointer to first (i.e. lowest address) nonzero character. */ @@ -277,9 +230,12 @@ val_print_type_code_int (type, valaddr, stream) #endif if (len <= sizeof (LONGEST)) { - /* We can print it in decimal. */ + /* The most significant bytes are zero, so we can just get + the least significant sizeof (LONGEST) bytes and print it + in decimal. */ print_longest (stream, 'u', 0, - unpack_long (BUILTIN_TYPE_LONGEST, first_addr)); + extract_unsigned_integer (first_addr, + sizeof (LONGEST))); } else { @@ -312,12 +268,14 @@ val_print_type_code_int (type, valaddr, stream) printf() that supports "ll" in the format string. We handle these by seeing if the number is actually a long, and if not we just bail out and print the number in hex. The format chars b,h,w,g are from - print_scalar_formatted(). USE_LOCAL says whether or not to call the - local formatting routine to get the format. */ + print_scalar_formatted(). If USE_LOCAL, format it according to the current + language (this should be used for most integers which GDB prints, the + exception is things like protocols where the format of the integer is + a protocol thing, not a user-visible thing). */ void print_longest (stream, format, use_local, val_long) - FILE *stream; + GDB_FILE *stream; int format; int use_local; LONGEST val_long; @@ -329,7 +287,7 @@ print_longest (stream, format, use_local, val_long) vbot = (long) val_long; if ((format == 'd' && (val_long < INT_MIN || val_long > INT_MAX)) - || ((format == 'u' || format == 'x') && val_long > UINT_MAX)) + || ((format == 'u' || format == 'x') && (unsigned long long)val_long > UINT_MAX)) { fprintf_filtered (stream, "0x%lx%08lx", vtop, vbot); return; @@ -424,6 +382,28 @@ print_longest (stream, format, use_local, val_long) #endif /* !PRINTF_HAS_LONG_LONG */ } +/* This used to be a macro, but I don't think it is called often enough + to merit such treatment. */ +/* Convert a LONGEST to an int. This is used in contexts (e.g. number of + arguments to a function, number in a value history, register number, etc.) + where the value must not be larger than can fit in an int. */ + +int +longest_to_int (arg) + LONGEST arg; +{ + + /* This check is in case a system header has botched the + definition of INT_MIN, like on BSDI. */ + if (sizeof (LONGEST) <= sizeof (int)) + return arg; + + if (arg > INT_MAX || arg < INT_MIN) + error ("Value out of range."); + + return arg; +} + /* Print a floating point value of type TYPE, pointed to in GDB by VALADDR, on STREAM. */ @@ -431,7 +411,7 @@ void print_floating (valaddr, type, stream) char *valaddr; struct type *type; - FILE *stream; + GDB_FILE *stream; { double doub; int inv; @@ -447,43 +427,48 @@ print_floating (valaddr, type, stream) representation, but is not IEEE conforming. */ { - long low, high; + unsigned long low, high; /* Is the sign bit 0? */ int nonnegative; /* Is it is a NaN (i.e. the exponent is all ones and the fraction is nonzero)? */ int is_nan; - if (len == sizeof (float)) + if (len == 4) { - /* It's single precision. */ - memcpy ((char *) &low, valaddr, sizeof (low)); - /* target -> host. */ - SWAP_TARGET_AND_HOST (&low, sizeof (float)); - nonnegative = low >= 0; + /* It's single precision. */ + /* Assume that floating point byte order is the same as + integer byte order. */ + low = extract_unsigned_integer (valaddr, 4); + nonnegative = ((low & 0x80000000) == 0); is_nan = ((((low >> 23) & 0xFF) == 0xFF) && 0 != (low & 0x7FFFFF)); low &= 0x7fffff; high = 0; } - else + else if (len == 8) { /* It's double precision. Get the high and low words. */ + /* Assume that floating point byte order is the same as + integer byte order. */ #if TARGET_BYTE_ORDER == BIG_ENDIAN - memcpy (&low, valaddr+4, sizeof (low)); - memcpy (&high, valaddr+0, sizeof (high)); + low = extract_unsigned_integer (valaddr + 4, 4); + high = extract_unsigned_integer (valaddr, 4); #else - memcpy (&low, valaddr+0, sizeof (low)); - memcpy (&high, valaddr+4, sizeof (high)); + low = extract_unsigned_integer (valaddr, 4); + high = extract_unsigned_integer (valaddr + 4, 4); #endif - SWAP_TARGET_AND_HOST (&low, sizeof (low)); - SWAP_TARGET_AND_HOST (&high, sizeof (high)); - nonnegative = high >= 0; + nonnegative = ((high & 0x80000000) == 0); is_nan = (((high >> 20) & 0x7ff) == 0x7ff && ! ((((high & 0xfffff) == 0)) && (low == 0))); high &= 0xfffff; } + else + /* Extended. We can't detect NaNs for extendeds yet. Also note + that currently extendeds get nuked to double in + REGISTER_CONVERTIBLE. */ + is_nan = 0; if (is_nan) { @@ -512,7 +497,7 @@ print_floating (valaddr, type, stream) static void print_hex_chars (stream, valaddr, len) - FILE *stream; + GDB_FILE *stream; unsigned char *valaddr; unsigned len; { @@ -551,7 +536,7 @@ val_print_array_elements (type, valaddr, address, stream, format, deref_ref, struct type *type; char *valaddr; CORE_ADDR address; - FILE *stream; + GDB_FILE *stream; int format; int deref_ref; int recurse; @@ -571,7 +556,9 @@ val_print_array_elements (type, valaddr, address, stream, format, deref_ref, elttype = TYPE_TARGET_TYPE (type); eltlen = TYPE_LENGTH (elttype); len = TYPE_LENGTH (type) / eltlen; - + + annotate_array_section_begin (i, elttype); + for (; i < len && things_printed < print_max; i++) { if (i != 0) @@ -587,7 +574,7 @@ val_print_array_elements (type, valaddr, address, stream, format, deref_ref, } } wrap_here (n_spaces (2 + 2 * recurse)); - + rep1 = i + 1; reps = 1; while ((rep1 < len) && @@ -596,12 +583,15 @@ val_print_array_elements (type, valaddr, address, stream, format, deref_ref, ++reps; ++rep1; } - + if (reps > repeat_count_threshold) { val_print (elttype, valaddr + i * eltlen, 0, stream, format, deref_ref, recurse + 1, pretty); + annotate_elt_rep (reps); fprintf_filtered (stream, " ", reps); + annotate_elt_rep_end (); + i = rep1 - 1; things_printed += repeat_count_threshold; } @@ -609,19 +599,21 @@ val_print_array_elements (type, valaddr, address, stream, format, deref_ref, { val_print (elttype, valaddr + i * eltlen, 0, stream, format, deref_ref, recurse + 1, pretty); + annotate_elt (); things_printed++; } } + annotate_array_section_end (); if (i < len) { fprintf_filtered (stream, "..."); } } -static void +void value_print_array_elements (val, stream, format, pretty) - value val; - FILE *stream; + value_ptr val; + GDB_FILE *stream; int format; enum val_prettyprint pretty; { @@ -657,7 +649,7 @@ value_print_array_elements (val, stream, format, pretty) val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i, VALUE_ADDRESS (val) + typelen * i, stream, format, 1, 0, pretty); - fprintf (stream, " ", reps); + fprintf_unfiltered (stream, " ", reps); i = rep1 - 1; things_printed += repeat_count_threshold; } @@ -680,11 +672,18 @@ value_print_array_elements (val, stream, format, pretty) byte, otherwise printing proceeds (including null bytes) until either print_max or LEN characters have been printed, whichever is smaller. */ +/* FIXME: All callers supply LEN of zero. Supplying a non-zero LEN is + pointless, this routine just then becomes a convoluted version of + target_read_memory_partial. Removing all the LEN stuff would simplify + this routine enormously. + + FIXME: Use target_read_string. */ + int val_print_string (addr, len, stream) CORE_ADDR addr; unsigned int len; - FILE *stream; + GDB_FILE *stream; { int force_ellipsis = 0; /* Force ellipsis to be printed if nonzero. */ int errcode; /* Errno returned from bad reads. */ @@ -714,9 +713,10 @@ val_print_string (addr, len, stream) are looking for a null terminator to end the fetching, so we might as well read in blocks that are large enough to be efficient, but not so large as to be slow if fetchlimit happens to be large. So we choose the - minimum of DEFAULT_PRINT_MAX and fetchlimit. */ + minimum of 8 and fetchlimit. We used to use 200 instead of 8 but + 200 is way too big for remote debugging over a serial line. */ - chunksize = (len == 0 ? min (PRINT_MAX_DEFAULT, fetchlimit) : fetchlimit); + chunksize = (len == 0 ? min (8, fetchlimit) : fetchlimit); /* Loop until we either have all the characters to print, or we encounter some error, such as bumping into the end of the address space. */ @@ -755,24 +755,35 @@ val_print_string (addr, len, stream) after the null byte, or at the next character after the end of the buffer. */ limit = bufptr + nfetch; - do { - addr++; - bufptr++; - } while (bufptr < limit && *(bufptr - 1) != '\0'); + while (bufptr < limit) + { + ++addr; + ++bufptr; + if (bufptr[-1] == '\0') + { + /* We don't care about any error which happened after + the NULL terminator. */ + errcode = 0; + break; + } + } } } while (errcode == 0 /* no error */ - && bufptr < buffer + fetchlimit /* no overrun */ + && bufsize < fetchlimit /* no overrun */ && !(len == 0 && *(bufptr - 1) == '\0')); /* no null term */ + /* bufptr and addr now point immediately beyond the last byte which we + consider part of the string (including a '\0' which ends the string). */ + /* We now have either successfully filled the buffer to fetchlimit, or terminated early due to an error or finding a null byte when LEN is - zero. */ + zero. */ - if (len == 0 && *(bufptr - 1) != '\0') + if (len == 0 && bufptr > buffer && *(bufptr - 1) != '\0') { /* We didn't find a null terminator we were looking for. Attempt to peek at the next character. If not successful, or it is not - a null byte, then force ellipsis to be printed. */ + a null byte, then force ellipsis to be printed. */ if (target_read_memory (addr, &peekchar, 1) != 0 || peekchar != '\0') { force_ellipsis = 1; @@ -787,29 +798,35 @@ val_print_string (addr, len, stream) } QUIT; - - if (addressprint) + + /* If we get an error before fetching anything, don't print a string. + But if we fetch something and then get an error, print the string + and then the error message. */ + if (errcode == 0 || bufptr > buffer) { - fputs_filtered (" ", stream); + if (addressprint) + { + fputs_filtered (" ", stream); + } + LA_PRINT_STRING (stream, buffer, bufptr - buffer, force_ellipsis); } - LA_PRINT_STRING (stream, buffer, bufptr - buffer, force_ellipsis); - - if (errcode != 0 && force_ellipsis) + + if (errcode != 0) { if (errcode == EIO) { - fprintf_filtered (stream, - "
", - (unsigned long) addr); + fprintf_filtered (stream, "
"); } else { - error ("Error reading memory address 0x%lx: %s.", - (unsigned long) addr, - safe_strerror (errcode)); + fprintf_filtered (stream, " ", safe_strerror (errcode)); } } - fflush (stream); + gdb_flush (stream); do_cleanups (old_chain); return (bufptr - buffer); } @@ -952,9 +969,9 @@ set_print (arg, from_tty) char *arg; int from_tty; { - printf ( + printf_unfiltered ( "\"set print\" must be followed by the name of a print subcommand.\n"); - help_list (setprintlist, "set print ", -1, stdout); + help_list (setprintlist, "set print ", -1, gdb_stdout); } /*ARGSUSED*/ @@ -991,6 +1008,13 @@ _initialize_valprint () &setprintlist), &showprintlist); + add_show_from_set + (add_set_cmd ("null-stop", no_class, var_boolean, + (char *)&stop_print_at_null, + "Set printing of char arrays to stop at first null char.", + &setprintlist), + &showprintlist); + add_show_from_set (add_set_cmd ("repeats", no_class, var_uinteger, (char *)&repeat_count_threshold, diff --git a/gnu/usr.bin/gdb/gdb/valprint.h b/gnu/usr.bin/gdb/gdb/valprint.h index 5918def07e68..e45f48de321a 100644 --- a/gnu/usr.bin/gdb/gdb/valprint.h +++ b/gnu/usr.bin/gdb/gdb/valprint.h @@ -1,5 +1,6 @@ /* Declarations for value printing routines for GDB, the GNU debugger. - Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc. + Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -29,12 +30,15 @@ extern int objectprint; /* Controls looking up an object's derived type using what we find in its vtables. */ extern unsigned int print_max; /* Max # of chars for strings/vectors */ + extern int output_format; +extern int stop_print_at_null; /* Stop printing at null char? */ + extern void -val_print_array_elements PARAMS ((struct type *, char *, CORE_ADDR, FILE *, +val_print_array_elements PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint, int)); extern void -val_print_type_code_int PARAMS ((struct type *, char *, FILE *)); +val_print_type_code_int PARAMS ((struct type *, char *, GDB_FILE *)); diff --git a/gnu/usr.bin/gdb/gdb/value.h b/gnu/usr.bin/gdb/gdb/value.h index b8e16761e5d6..403b66131b7e 100644 --- a/gnu/usr.bin/gdb/gdb/value.h +++ b/gnu/usr.bin/gdb/gdb/value.h @@ -1,5 +1,5 @@ /* Definitions for values of C expressions, for GDB. - Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc. + Copyright 1986, 1987, 1989, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GDB. @@ -47,6 +47,8 @@ struct value /* Type of value; either not an lval, or one of the various different possible kinds of lval. */ enum lval_type lval; + /* Is it modifiable? Only relevant if lval != not_lval. */ + int modifiable; /* Location of value (if lval). */ union { @@ -102,14 +104,12 @@ struct value union { long contents[1]; double force_double_align; -#ifdef CC_HAS_LONG_LONG - long long force_longlong_align; -#endif + LONGEST force_longlong_align; } aligner; }; -typedef struct value *value; +typedef struct value *value_ptr; #define VALUE_TYPE(val) (val)->type #define VALUE_LAZY(val) (val)->lazy @@ -123,8 +123,7 @@ typedef struct value *value; #define VALUE_CONTENTS_RAW(val) ((char *) (val)->aligner.contents) #define VALUE_CONTENTS(val) ((void)(VALUE_LAZY(val) && value_fetch_lazy(val)),\ VALUE_CONTENTS_RAW(val)) -extern int -value_fetch_lazy PARAMS ((value val)); +extern int value_fetch_lazy PARAMS ((value_ptr val)); #define VALUE_LVAL(val) (val)->lval #define VALUE_ADDRESS(val) (val)->location.address @@ -180,7 +179,7 @@ struct internalvar { struct internalvar *next; char *name; - value value; + value_ptr value; }; /* Pointer to member function. Depends on compiler implementation. */ @@ -200,220 +199,200 @@ struct fn_field; #endif extern void -print_address_demangle PARAMS ((CORE_ADDR, FILE *, int)); +print_address_demangle PARAMS ((CORE_ADDR, GDB_FILE *, int)); -extern LONGEST -value_as_long PARAMS ((value val)); +extern LONGEST value_as_long PARAMS ((value_ptr val)); -extern double -value_as_double PARAMS ((value val)); +extern double value_as_double PARAMS ((value_ptr val)); -extern CORE_ADDR -value_as_pointer PARAMS ((value val)); +extern CORE_ADDR value_as_pointer PARAMS ((value_ptr val)); -extern LONGEST -unpack_long PARAMS ((struct type *type, char *valaddr)); +extern LONGEST unpack_long PARAMS ((struct type *type, char *valaddr)); -extern double -unpack_double PARAMS ((struct type *type, char *valaddr, int *invp)); +extern double unpack_double PARAMS ((struct type *type, char *valaddr, + int *invp)); extern CORE_ADDR unpack_pointer PARAMS ((struct type *type, char *valaddr)); extern LONGEST unpack_field_as_long PARAMS ((struct type *type, char *valaddr, int fieldno)); -extern value value_from_longest PARAMS ((struct type *type, LONGEST num)); +extern value_ptr value_from_longest PARAMS ((struct type *type, LONGEST num)); -extern value value_from_double PARAMS ((struct type *type, double num)); +extern value_ptr value_from_double PARAMS ((struct type *type, double num)); -extern value value_at PARAMS ((struct type *type, CORE_ADDR addr)); +extern value_ptr value_at PARAMS ((struct type *type, CORE_ADDR addr)); -extern value value_at_lazy PARAMS ((struct type *type, CORE_ADDR addr)); +extern value_ptr value_at_lazy PARAMS ((struct type *type, CORE_ADDR addr)); /* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */ -extern value value_from_register PARAMS ((struct type *type, int regnum, +extern value_ptr value_from_register PARAMS ((struct type *type, int regnum, struct frame_info * frame)); -extern value value_of_variable PARAMS ((struct symbol *var, struct block *b)); +extern value_ptr value_of_variable PARAMS ((struct symbol *var, + struct block *b)); -extern value value_of_register PARAMS ((int regnum)); +extern value_ptr value_of_register PARAMS ((int regnum)); extern int symbol_read_needs_frame PARAMS ((struct symbol *)); /* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */ -extern value read_var_value PARAMS ((struct symbol *var, - struct frame_info *frame)); +extern value_ptr read_var_value PARAMS ((struct symbol *var, + struct frame_info *frame)); /* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */ -extern value locate_var_value PARAMS ((struct symbol *var, +extern value_ptr locate_var_value PARAMS ((struct symbol *var, struct frame_info *frame)); -extern value allocate_value PARAMS ((struct type *type)); +extern value_ptr allocate_value PARAMS ((struct type *type)); -extern value allocate_repeat_value PARAMS ((struct type *type, int count)); +extern value_ptr allocate_repeat_value PARAMS ((struct type *type, int count)); -extern value value_mark PARAMS ((void)); +extern value_ptr value_mark PARAMS ((void)); -extern void value_free_to_mark PARAMS ((value mark)); +extern void value_free_to_mark PARAMS ((value_ptr mark)); -extern value value_string PARAMS ((char *ptr, int len)); +extern value_ptr value_string PARAMS ((char *ptr, int len)); -extern value value_array PARAMS ((int lowbound, int highbound, - value *elemvec)); +extern value_ptr value_array PARAMS ((int lowbound, int highbound, + value_ptr *elemvec)); -extern value value_concat PARAMS ((value arg1, value arg2)); +extern value_ptr value_concat PARAMS ((value_ptr arg1, value_ptr arg2)); -extern value value_binop PARAMS ((value arg1, value arg2, enum exp_opcode op)); +extern value_ptr value_binop PARAMS ((value_ptr arg1, value_ptr arg2, + enum exp_opcode op)); -extern value value_add PARAMS ((value arg1, value arg2)); +extern value_ptr value_add PARAMS ((value_ptr arg1, value_ptr arg2)); -extern value value_sub PARAMS ((value arg1, value arg2)); +extern value_ptr value_sub PARAMS ((value_ptr arg1, value_ptr arg2)); -extern value value_coerce_array PARAMS ((value arg1)); +extern value_ptr value_coerce_array PARAMS ((value_ptr arg1)); -extern value value_coerce_function PARAMS ((value arg1)); +extern value_ptr value_coerce_function PARAMS ((value_ptr arg1)); -extern value value_ind PARAMS ((value arg1)); +extern value_ptr value_ind PARAMS ((value_ptr arg1)); -extern value value_addr PARAMS ((value arg1)); +extern value_ptr value_addr PARAMS ((value_ptr arg1)); -extern value value_assign PARAMS ((value toval, value fromval)); +extern value_ptr value_assign PARAMS ((value_ptr toval, value_ptr fromval)); -extern value value_neg PARAMS ((value arg1)); +extern value_ptr value_neg PARAMS ((value_ptr arg1)); -extern value value_complement PARAMS ((value arg1)); +extern value_ptr value_complement PARAMS ((value_ptr arg1)); -extern value value_struct_elt PARAMS ((value *argp, value *args, char *name, - int *static_memfuncp, char *err)); +extern value_ptr value_struct_elt PARAMS ((value_ptr *argp, value_ptr *args, + char *name, + int *static_memfuncp, char *err)); -extern value value_struct_elt_for_reference PARAMS ((struct type *domain, - int offset, - struct type *curtype, - char *name, - struct type *intype)); +extern value_ptr value_struct_elt_for_reference PARAMS ((struct type *domain, + int offset, + struct type *curtype, + char *name, + struct type *intype)); -extern value value_field PARAMS ((value arg1, int fieldno)); +extern value_ptr value_field PARAMS ((value_ptr arg1, int fieldno)); -extern value value_primitive_field PARAMS ((value arg1, int offset, - int fieldno, - struct type *arg_type)); +extern value_ptr value_primitive_field PARAMS ((value_ptr arg1, int offset, + int fieldno, + struct type *arg_type)); -extern value value_cast PARAMS ((struct type *type, value arg2)); +extern value_ptr value_cast PARAMS ((struct type *type, value_ptr arg2)); -extern value value_zero PARAMS ((struct type *type, enum lval_type lv)); +extern value_ptr value_zero PARAMS ((struct type *type, enum lval_type lv)); -extern value value_repeat PARAMS ((value arg1, int count)); +extern value_ptr value_repeat PARAMS ((value_ptr arg1, int count)); -extern value value_subscript PARAMS ((value array, value idx)); +extern value_ptr value_subscript PARAMS ((value_ptr array, value_ptr idx)); -extern value value_from_vtable_info PARAMS ((value arg, struct type *type)); +extern value_ptr value_from_vtable_info PARAMS ((value_ptr arg, + struct type *type)); -extern value value_being_returned PARAMS ((struct type *valtype, - char retbuf[REGISTER_BYTES], - int struct_return)); +extern value_ptr value_being_returned PARAMS ((struct type *valtype, + char retbuf[REGISTER_BYTES], + int struct_return)); -extern int -using_struct_return PARAMS ((value function, CORE_ADDR funcaddr, - struct type *value_type, int gcc_p)); +extern value_ptr value_in PARAMS ((value_ptr element, value_ptr set)); -extern void -set_return_value PARAMS ((value val)); +extern int value_bit_index PARAMS ((struct type *type, char *addr, int index)); -extern value -evaluate_expression PARAMS ((struct expression *exp)); +extern int using_struct_return PARAMS ((value_ptr function, CORE_ADDR funcaddr, + struct type *value_type, int gcc_p)); -extern value -evaluate_type PARAMS ((struct expression *exp)); +extern void set_return_value PARAMS ((value_ptr val)); -extern value -parse_and_eval PARAMS ((char *exp)); +extern value_ptr evaluate_expression PARAMS ((struct expression *exp)); -extern value -parse_to_comma_and_eval PARAMS ((char **expp)); +extern value_ptr evaluate_type PARAMS ((struct expression *exp)); -extern struct type * -parse_and_eval_type PARAMS ((char *p, int length)); +extern value_ptr parse_and_eval PARAMS ((char *exp)); -extern CORE_ADDR -parse_and_eval_address PARAMS ((char *exp)); +extern value_ptr parse_to_comma_and_eval PARAMS ((char **expp)); -extern CORE_ADDR -parse_and_eval_address_1 PARAMS ((char **expptr)); +extern struct type *parse_and_eval_type PARAMS ((char *p, int length)); -extern value -access_value_history PARAMS ((int num)); +extern CORE_ADDR parse_and_eval_address PARAMS ((char *exp)); -extern value -value_of_internalvar PARAMS ((struct internalvar *var)); +extern CORE_ADDR parse_and_eval_address_1 PARAMS ((char **expptr)); -extern void -set_internalvar PARAMS ((struct internalvar *var, value val)); +extern value_ptr access_value_history PARAMS ((int num)); -extern void -set_internalvar_component PARAMS ((struct internalvar *var, int offset, - int bitpos, int bitsize, - value newvalue)); +extern value_ptr value_of_internalvar PARAMS ((struct internalvar *var)); -extern struct internalvar * -lookup_internalvar PARAMS ((char *name)); +extern void set_internalvar PARAMS ((struct internalvar *var, value_ptr val)); -extern int -value_equal PARAMS ((value arg1, value arg2)); +extern void set_internalvar_component PARAMS ((struct internalvar *var, + int offset, + int bitpos, int bitsize, + value_ptr newvalue)); -extern int -value_less PARAMS ((value arg1, value arg2)); +extern struct internalvar *lookup_internalvar PARAMS ((char *name)); -extern int -value_logical_not PARAMS ((value arg1)); +extern int value_equal PARAMS ((value_ptr arg1, value_ptr arg2)); + +extern int value_less PARAMS ((value_ptr arg1, value_ptr arg2)); + +extern int value_logical_not PARAMS ((value_ptr arg1)); /* C++ */ -extern value -value_of_this PARAMS ((int complain)); +extern value_ptr value_of_this PARAMS ((int complain)); -extern value -value_x_binop PARAMS ((value arg1, value arg2, enum exp_opcode op, - enum exp_opcode otherop)); +extern value_ptr value_x_binop PARAMS ((value_ptr arg1, value_ptr arg2, + enum exp_opcode op, + enum exp_opcode otherop)); -extern value -value_x_unop PARAMS ((value arg1, enum exp_opcode op)); +extern value_ptr value_x_unop PARAMS ((value_ptr arg1, enum exp_opcode op)); -extern value -value_fn_field PARAMS ((value *arg1p, struct fn_field *f, int j, - struct type* type, int offset)); +extern value_ptr value_fn_field PARAMS ((value_ptr *arg1p, struct fn_field *f, + int j, + struct type* type, int offset)); -extern value -value_virtual_fn_field PARAMS ((value *arg1p, struct fn_field *f, int j, - struct type *type, int offset)); +extern value_ptr value_virtual_fn_field PARAMS ((value_ptr *arg1p, + struct fn_field *f, int j, + struct type *type, + int offset)); -extern int -binop_user_defined_p PARAMS ((enum exp_opcode op, value arg1, value arg2)); +extern int binop_user_defined_p PARAMS ((enum exp_opcode op, + value_ptr arg1, value_ptr arg2)); -extern int -unop_user_defined_p PARAMS ((enum exp_opcode op, value arg1)); +extern int unop_user_defined_p PARAMS ((enum exp_opcode op, value_ptr arg1)); -extern int -destructor_name_p PARAMS ((const char *name, const struct type *type)); +extern int destructor_name_p PARAMS ((const char *name, + const struct type *type)); #define value_free(val) free ((PTR)val) -extern void -free_all_values PARAMS ((void)); +extern void free_all_values PARAMS ((void)); -extern void -release_value PARAMS ((value val)); +extern void release_value PARAMS ((value_ptr val)); -extern int -record_latest_value PARAMS ((value val)); +extern int record_latest_value PARAMS ((value_ptr val)); -extern void -registers_changed PARAMS ((void)); +extern void registers_changed PARAMS ((void)); -extern void -read_register_bytes PARAMS ((int regbyte, char *myaddr, int len)); +extern void read_register_bytes PARAMS ((int regbyte, char *myaddr, int len)); -extern void -write_register_bytes PARAMS ((int regbyte, char *myaddr, int len)); +extern void write_register_bytes PARAMS ((int regbyte, char *myaddr, int len)); extern void read_register_gen PARAMS ((int regno, char *myaddr)); @@ -437,45 +416,49 @@ extern void modify_field PARAMS ((char *addr, LONGEST fieldval, int bitpos, int bitsize)); extern void -type_print PARAMS ((struct type *type, char *varstring, FILE *stream, +type_print PARAMS ((struct type *type, char *varstring, GDB_FILE *stream, int show)); -extern char * -baseclass_addr PARAMS ((struct type *type, int index, char *valaddr, - value *valuep, int *errp)); +extern char *baseclass_addr PARAMS ((struct type *type, int index, + char *valaddr, + value_ptr *valuep, int *errp)); extern void -print_longest PARAMS ((FILE *stream, int format, int use_local, - LONGEST value)); +print_longest PARAMS ((GDB_FILE *stream, int format, int use_local, + LONGEST val)); extern void -print_floating PARAMS ((char *valaddr, struct type *type, FILE *stream)); +print_floating PARAMS ((char *valaddr, struct type *type, GDB_FILE *stream)); -extern int -value_print PARAMS ((value val, FILE *stream, int format, - enum val_prettyprint pretty)); +extern int value_print PARAMS ((value_ptr val, GDB_FILE *stream, int format, + enum val_prettyprint pretty)); + +extern void +value_print_array_elements PARAMS ((value_ptr val, GDB_FILE* stream, + int format, enum val_prettyprint pretty)); + +extern value_ptr +value_release_to_mark PARAMS ((value_ptr mark)); extern int val_print PARAMS ((struct type *type, char *valaddr, CORE_ADDR address, - FILE *stream, int format, int deref_ref, + GDB_FILE *stream, int format, int deref_ref, int recurse, enum val_prettyprint pretty)); extern int -val_print_string PARAMS ((CORE_ADDR addr, unsigned int len, FILE *stream)); +val_print_string PARAMS ((CORE_ADDR addr, unsigned int len, GDB_FILE *stream)); /* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */ extern void print_variable_value PARAMS ((struct symbol *var, struct frame_info *frame, - FILE *stream)); + GDB_FILE *stream)); -extern value -value_arg_coerce PARAMS ((value)); +extern value_ptr value_arg_coerce PARAMS ((value_ptr)); -extern int -check_field PARAMS ((value, const char *)); +extern int check_field PARAMS ((value_ptr, const char *)); extern void -c_typedef_print PARAMS ((struct type *type, struct symbol *new, FILE *stream)); +c_typedef_print PARAMS ((struct type *type, struct symbol *new, GDB_FILE *stream)); extern char * internalvar_name PARAMS ((struct internalvar *var)); @@ -488,15 +471,12 @@ clear_internalvars PARAMS ((void)); /* From values.c */ -extern value -value_copy PARAMS ((value)); +extern value_ptr value_copy PARAMS ((value_ptr)); -extern int -baseclass_offset PARAMS ((struct type *, int, value, int)); +extern int baseclass_offset PARAMS ((struct type *, int, value_ptr, int)); /* From valops.c */ -extern value -call_function_by_hand PARAMS ((value, int, value *)); +extern value_ptr call_function_by_hand PARAMS ((value_ptr, int, value_ptr *)); #endif /* !defined (VALUE_H) */ diff --git a/gnu/usr.bin/gdb/gdb/values.c b/gnu/usr.bin/gdb/gdb/values.c index a592f9eeca98..1c833af52c8b 100644 --- a/gnu/usr.bin/gdb/gdb/values.c +++ b/gnu/usr.bin/gdb/gdb/values.c @@ -31,14 +31,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Local function prototypes. */ -static value -value_headof PARAMS ((value, struct type *, struct type *)); +static value_ptr value_headof PARAMS ((value_ptr, struct type *, + struct type *)); -static void -show_values PARAMS ((char *, int)); +static void show_values PARAMS ((char *, int)); -static void -show_convenience PARAMS ((char *, int)); +static void show_convenience PARAMS ((char *, int)); /* The value-history records all the values printed by print commands during this session. Each chunk @@ -51,7 +49,7 @@ show_convenience PARAMS ((char *, int)); struct value_history_chunk { struct value_history_chunk *next; - value values[VALUE_HISTORY_CHUNK]; + value_ptr values[VALUE_HISTORY_CHUNK]; }; /* Chain of chunks now in use. */ @@ -64,19 +62,19 @@ static int value_history_count; /* Abs number of last entry stored */ (except for those released by calls to release_value) This is so they can be freed after each command. */ -static value all_values; +static value_ptr all_values; /* Allocate a value that has the correct length for type TYPE. */ -value +value_ptr allocate_value (type) struct type *type; { - register value val; + register value_ptr val; check_stub_type (type); - val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type)); + val = (struct value *) xmalloc (sizeof (struct value) + TYPE_LENGTH (type)); VALUE_NEXT (val) = all_values; all_values = val; VALUE_TYPE (val) = type; @@ -91,20 +89,22 @@ allocate_value (type) VALUE_REGNO (val) = -1; VALUE_LAZY (val) = 0; VALUE_OPTIMIZED_OUT (val) = 0; + val->modifiable = 1; return val; } /* Allocate a value that has the correct length for COUNT repetitions type TYPE. */ -value +value_ptr allocate_repeat_value (type, count) struct type *type; int count; { - register value val; + register value_ptr val; - val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type) * count); + val = + (value_ptr) xmalloc (sizeof (struct value) + TYPE_LENGTH (type) * count); VALUE_NEXT (val) = all_values; all_values = val; VALUE_TYPE (val) = type; @@ -125,7 +125,7 @@ allocate_repeat_value (type, count) /* Return a mark in the value chain. All values allocated after the mark is obtained (except for those released) are subject to being freed if a subsequent value_free_to_mark is passed the mark. */ -value +value_ptr value_mark () { return all_values; @@ -135,9 +135,9 @@ value_mark () (except for those released). */ void value_free_to_mark (mark) - value mark; + value_ptr mark; { - value val, next; + value_ptr val, next; for (val = all_values; val && val != mark; val = next) { @@ -153,7 +153,7 @@ value_free_to_mark (mark) void free_all_values () { - register value val, next; + register value_ptr val, next; for (val = all_values; val; val = next) { @@ -169,9 +169,9 @@ free_all_values () void release_value (val) - register value val; + register value_ptr val; { - register value v; + register value_ptr v; if (all_values == val) { @@ -189,15 +189,33 @@ release_value (val) } } +/* Release all values up to mark */ +value_ptr +value_release_to_mark (mark) + value_ptr mark; +{ + value_ptr val, next; + + for (val = next = all_values; next; next = VALUE_NEXT (next)) + if (VALUE_NEXT (next) == mark) + { + all_values = VALUE_NEXT (next); + VALUE_NEXT (next) = 0; + return val; + } + all_values = 0; + return val; +} + /* Return a copy of the value ARG. It contains the same contents, for same memory address, but it's a different block of storage. */ -value +value_ptr value_copy (arg) - value arg; + value_ptr arg; { - register value val; + register value_ptr val; register struct type *type = VALUE_TYPE (arg); if (VALUE_REPEATED (arg)) val = allocate_repeat_value (type, VALUE_REPETITIONS (arg)); @@ -210,6 +228,7 @@ value_copy (arg) VALUE_BITSIZE (val) = VALUE_BITSIZE (arg); VALUE_REGNO (val) = VALUE_REGNO (arg); VALUE_LAZY (val) = VALUE_LAZY (arg); + val->modifiable = arg->modifiable; if (!VALUE_LAZY (val)) { memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS_RAW (arg), @@ -228,7 +247,7 @@ value_copy (arg) int record_latest_value (val) - value val; + value_ptr val; { int i; @@ -262,7 +281,10 @@ record_latest_value (val) a value on the value history never changes. */ if (VALUE_LAZY (val)) value_fetch_lazy (val); - VALUE_LVAL (val) = not_lval; + /* We preserve VALUE_LVAL so that the user can find out where it was fetched + from. This is a bit dubious, because then *&$1 does not just return $1 + but the current contents of that location. c'est la vie... */ + val->modifiable = 0; release_value (val); /* Now we regard value_history_count as origin-one @@ -273,7 +295,7 @@ record_latest_value (val) /* Return a copy of the value in the history with sequence number NUM. */ -value +value_ptr access_value_history (num) int num; { @@ -317,7 +339,7 @@ clear_value_history () { register struct value_history_chunk *next; register int i; - register value val; + register value_ptr val; while (value_history_chain) { @@ -337,7 +359,7 @@ show_values (num_exp, from_tty) int from_tty; { register int i; - register value val; + register value_ptr val; static int num = 1; if (num_exp) @@ -360,7 +382,7 @@ show_values (num_exp, from_tty) { val = access_value_history (i); printf_filtered ("$%d = ", i); - value_print (val, stdout, 0, Val_pretty_default); + value_print (val, gdb_stdout, 0, Val_pretty_default); printf_filtered ("\n"); } @@ -409,11 +431,11 @@ lookup_internalvar (name) return var; } -value +value_ptr value_of_internalvar (var) struct internalvar *var; { - register value val; + register value_ptr val; #ifdef IS_TRAPPED_INTERNALVAR if (IS_TRAPPED_INTERNALVAR (var->name)) @@ -432,7 +454,7 @@ void set_internalvar_component (var, offset, bitpos, bitsize, newval) struct internalvar *var; int offset, bitpos, bitsize; - value newval; + value_ptr newval; { register char *addr = VALUE_CONTENTS (var->value) + offset; @@ -451,21 +473,33 @@ set_internalvar_component (var, offset, bitpos, bitsize, newval) void set_internalvar (var, val) struct internalvar *var; - value val; + value_ptr val; { + value_ptr newval; + #ifdef IS_TRAPPED_INTERNALVAR if (IS_TRAPPED_INTERNALVAR (var->name)) SET_TRAPPED_INTERNALVAR (var, val, 0, 0, 0); #endif - free ((PTR)var->value); - var->value = value_copy (val); + newval = value_copy (val); + /* Force the value to be fetched from the target now, to avoid problems later when this internalvar is referenced and the target is gone or has changed. */ - if (VALUE_LAZY (var->value)) - value_fetch_lazy (var->value); - release_value (var->value); + if (VALUE_LAZY (newval)) + value_fetch_lazy (newval); + + /* Begin code which must not call error(). If var->value points to + something free'd, an error() obviously leaves a dangling pointer. + But we also get a danling pointer if var->value points to + something in the value chain (i.e., before release_value is + called), because after the error free_all_values will get called before + long. */ + free ((PTR)var->value); + var->value = newval; + release_value (newval); + /* End code which must not call error(). */ } char * @@ -512,11 +546,11 @@ show_convenience (ignore, from_tty) varseen = 1; } printf_filtered ("$%s = ", var->name); - value_print (var->value, stdout, 0, Val_pretty_default); + value_print (var->value, gdb_stdout, 0, Val_pretty_default); printf_filtered ("\n"); } if (!varseen) - printf ("No debugger convenience variables now defined.\n\ + printf_unfiltered ("No debugger convenience variables now defined.\n\ Convenience variables have names starting with \"$\";\n\ use \"set\" as in \"set $foo = 5\" to define them.\n"); } @@ -528,7 +562,7 @@ use \"set\" as in \"set $foo = 5\" to define them.\n"); LONGEST value_as_long (val) - register value val; + register value_ptr val; { /* This coerces arrays and functions, which is necessary (e.g. in disassemble_command). It also dereferences references, which @@ -540,7 +574,7 @@ value_as_long (val) double value_as_double (val) - register value val; + register value_ptr val; { double foo; int inv; @@ -554,7 +588,7 @@ value_as_double (val) Does not deallocate the value. */ CORE_ADDR value_as_pointer (val) - value val; + value_ptr val; { /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure whether we want this to be true eventually. */ @@ -582,9 +616,6 @@ value_as_pointer (val) to member which reaches here is considered to be equivalent to an INT (or some size). After all, it is only an offset. */ -/* FIXME: This should be rewritten as a switch statement for speed and - ease of comprehension. */ - LONGEST unpack_long (type, valaddr) struct type *type; @@ -594,49 +625,34 @@ unpack_long (type, valaddr) register int len = TYPE_LENGTH (type); register int nosign = TYPE_UNSIGNED (type); - if (code == TYPE_CODE_ENUM || code == TYPE_CODE_BOOL) - code = TYPE_CODE_INT; - if (code == TYPE_CODE_FLT) + switch (code) { - if (len == sizeof (float)) - { - float retval; - memcpy (&retval, valaddr, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } - - if (len == sizeof (double)) - { - double retval; - memcpy (&retval, valaddr, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } + case TYPE_CODE_ENUM: + case TYPE_CODE_BOOL: + case TYPE_CODE_INT: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + if (nosign) + return extract_unsigned_integer (valaddr, len); else - { - error ("Unexpected type of floating point number."); - } - } - else if ((code == TYPE_CODE_INT || code == TYPE_CODE_CHAR) && nosign) - { - return extract_unsigned_integer (valaddr, len); - } - else if (code == TYPE_CODE_INT || code == TYPE_CODE_CHAR) - { - return extract_signed_integer (valaddr, len); - } - /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure - whether we want this to be true eventually. */ - else if (code == TYPE_CODE_PTR || code == TYPE_CODE_REF) - { - return extract_address (valaddr, len); - } - else if (code == TYPE_CODE_MEMBER) - error ("not implemented: member types in unpack_long"); + return extract_signed_integer (valaddr, len); - error ("Value not integer or pointer."); - return 0; /* For lint -- never reached */ + case TYPE_CODE_FLT: + return extract_floating (valaddr, len); + + case TYPE_CODE_PTR: + case TYPE_CODE_REF: + /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure + whether we want this to be true eventually. */ + return extract_address (valaddr, len); + + case TYPE_CODE_MEMBER: + error ("not implemented: member types in unpack_long"); + + default: + error ("Value can't be converted to integer."); + } + return 0; /* Placate lint. */ } /* Return a double value from the specified type and address. @@ -663,35 +679,18 @@ unpack_double (type, valaddr, invp) *invp = 1; return 1.234567891011121314; } - - if (len == sizeof (float)) - { - float retval; - memcpy (&retval, valaddr, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } - - if (len == sizeof (double)) - { - double retval; - memcpy (&retval, valaddr, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } - else - { - error ("Unexpected type of floating point number."); - return 0; /* Placate lint. */ - } + return extract_floating (valaddr, len); + } + else if (nosign) + { + /* Unsigned -- be sure we compensate for signed LONGEST. */ + return (unsigned LONGEST) unpack_long (type, valaddr); + } + else + { + /* Signed -- we are OK with unpack_long. */ + return unpack_long (type, valaddr); } - else if (nosign) { - /* Unsigned -- be sure we compensate for signed LONGEST. */ - return (unsigned LONGEST) unpack_long (type, valaddr); - } else { - /* Signed -- we are OK with unpack_long. */ - return unpack_long (type, valaddr); - } } /* Unpack raw data (copied from debugee, target byte order) at VALADDR @@ -724,14 +723,14 @@ unpack_pointer (type, valaddr) For C++, must also be able to return values from static fields */ -value +value_ptr value_primitive_field (arg1, offset, fieldno, arg_type) - register value arg1; + register value_ptr arg1; int offset; register int fieldno; register struct type *arg_type; { - register value v; + register value_ptr v; register struct type *type; check_stub_type (arg_type); @@ -772,9 +771,9 @@ value_primitive_field (arg1, offset, fieldno, arg_type) For C++, must also be able to return values from static fields */ -value +value_ptr value_field (arg1, fieldno) - register value arg1; + register value_ptr arg1; register int fieldno; { return value_primitive_field (arg1, 0, fieldno, VALUE_TYPE (arg1)); @@ -784,22 +783,26 @@ value_field (arg1, fieldno) F is the list of member functions which contains the desired method. J is an index into F which provides the desired method. */ -value +value_ptr value_fn_field (arg1p, f, j, type, offset) - value *arg1p; + value_ptr *arg1p; struct fn_field *f; int j; struct type *type; int offset; { - register value v; + register value_ptr v; register struct type *ftype = TYPE_FN_FIELD_TYPE (f, j); struct symbol *sym; sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j), 0, VAR_NAMESPACE, 0, NULL); - if (! sym) error ("Internal error: could not find physical method named %s", + if (! sym) + return NULL; +/* + error ("Internal error: could not find physical method named %s", TYPE_FN_FIELD_PHYSNAME (f, j)); +*/ v = allocate_value (ftype); VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); @@ -827,22 +830,22 @@ value_fn_field (arg1p, f, j, type, offset) J is an index into F which provides the desired virtual function. TYPE is the type in which F is located. */ -value +value_ptr value_virtual_fn_field (arg1p, f, j, type, offset) - value *arg1p; + value_ptr *arg1p; struct fn_field *f; int j; struct type *type; int offset; { - value arg1 = *arg1p; + value_ptr arg1 = *arg1p; /* First, get the virtual function table pointer. That comes with a strange type, so cast it to type `pointer to long' (which should serve just fine as a function type). Then, index into the table, and convert final value to appropriate function type. */ - value entry, vfn, vtbl; - value vi = value_from_longest (builtin_type_int, - (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); + value_ptr entry, vfn, vtbl; + value_ptr vi = value_from_longest (builtin_type_int, + (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j); struct type *context; if (fcontext == NULL) @@ -877,16 +880,23 @@ value_virtual_fn_field (arg1p, f, j, type, offset) a virtual function. */ entry = value_subscript (vtbl, vi); - /* Move the `this' pointer according to the virtual function table. */ - VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0))/* + offset*/; - - if (! VALUE_LAZY (arg1)) + if (TYPE_CODE (VALUE_TYPE (entry)) == TYPE_CODE_STRUCT) { - VALUE_LAZY (arg1) = 1; - value_fetch_lazy (arg1); - } + /* Move the `this' pointer according to the virtual function table. */ + VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0)); + + if (! VALUE_LAZY (arg1)) + { + VALUE_LAZY (arg1) = 1; + value_fetch_lazy (arg1); + } - vfn = value_field (entry, 2); + vfn = value_field (entry, 2); + } + else if (TYPE_CODE (VALUE_TYPE (entry)) == TYPE_CODE_PTR) + vfn = entry; + else + error ("I'm confused: virtual function table has bad type"); /* Reinstantiate the function pointer with the correct type. */ VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j)); @@ -903,14 +913,14 @@ value_virtual_fn_field (arg1p, f, j, type, offset) FIXME-tiemann: should work with dossier entries as well. */ -static value +static value_ptr value_headof (in_arg, btype, dtype) - value in_arg; + value_ptr in_arg; struct type *btype, *dtype; { /* First collect the vtables we must look at for this object. */ /* FIXME-tiemann: right now, just look at top-most vtable. */ - value arg, vtbl, entry, best_entry = 0; + value_ptr arg, vtbl, entry, best_entry = 0; int i, nelems; int offset, best_offset = 0; struct symbol *sym; @@ -928,7 +938,8 @@ value_headof (in_arg, btype, dtype) /* Check that VTBL looks like it points to a virtual function table. */ msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl)); if (msymbol == NULL - || !VTBL_PREFIX_P (demangled_name = SYMBOL_NAME (msymbol))) + || (demangled_name = SYMBOL_NAME (msymbol)) == NULL + || !VTBL_PREFIX_P (demangled_name)) { /* If we expected to find a vtable, but did not, let the user know that we aren't happy, but don't throw an error. @@ -947,6 +958,9 @@ value_headof (in_arg, btype, dtype) { entry = value_subscript (vtbl, value_from_longest (builtin_type_int, (LONGEST) i)); + /* This won't work if we're using thunks. */ + if (TYPE_CODE (VALUE_TYPE (entry)) != TYPE_CODE_STRUCT) + break; offset = longest_to_int (value_as_long (value_field (entry, 0))); /* If we use '<=' we can handle single inheritance * where all offsets are zero - just use the first entry found. */ @@ -992,9 +1006,9 @@ value_headof (in_arg, btype, dtype) of its baseclasses) to figure out the most derived type that ARG could actually be a pointer to. */ -value +value_ptr value_from_vtable_info (arg, type) - value arg; + value_ptr arg; struct type *type; { /* Take care of preliminaries. */ @@ -1067,7 +1081,7 @@ int baseclass_offset (type, index, arg, offset) struct type *type; int index; - value arg; + value_ptr arg; int offset; { struct type *basetype = TYPE_BASECLASS (type, index); @@ -1129,7 +1143,7 @@ baseclass_addr (type, index, valaddr, valuep, errp) struct type *type; int index; char *valaddr; - value *valuep; + value_ptr *valuep; int *errp; { struct type *basetype = TYPE_BASECLASS (type, index); @@ -1149,7 +1163,7 @@ baseclass_addr (type, index, valaddr, valuep, errp) { if (vb_match (type, i, basetype)) { - value val = allocate_value (basetype); + value_ptr val = allocate_value (basetype); CORE_ADDR addr; int status; @@ -1299,12 +1313,12 @@ modify_field (addr, fieldval, bitpos, bitsize) /* Convert C numbers into newly allocated values */ -value +value_ptr value_from_longest (type, num) struct type *type; register LONGEST num; { - register value val = allocate_value (type); + register value_ptr val = allocate_value (type); register enum type_code code = TYPE_CODE (type); register int len = TYPE_LENGTH (type); @@ -1314,6 +1328,7 @@ value_from_longest (type, num) case TYPE_CODE_CHAR: case TYPE_CODE_ENUM: case TYPE_CODE_BOOL: + case TYPE_CODE_RANGE: store_signed_integer (VALUE_CONTENTS_RAW (val), len, num); break; @@ -1330,31 +1345,22 @@ value_from_longest (type, num) return val; } -value +value_ptr value_from_double (type, num) struct type *type; double num; { - register value val = allocate_value (type); + register value_ptr val = allocate_value (type); register enum type_code code = TYPE_CODE (type); register int len = TYPE_LENGTH (type); if (code == TYPE_CODE_FLT) { - if (len == sizeof (float)) - * (float *) VALUE_CONTENTS_RAW (val) = num; - else if (len == sizeof (double)) - * (double *) VALUE_CONTENTS_RAW (val) = num; - else - error ("Floating type encountered with unexpected data length."); + store_floating (VALUE_CONTENTS_RAW (val), len, num); } else error ("Unexpected type encountered for floating constant."); - /* num was in host byte order. So now put the value's contents - into target byte order. */ - SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (val), len); - return val; } @@ -1372,14 +1378,14 @@ value_from_double (type, num) 0 when it is using the value returning conventions (this often means returning pointer to where structure is vs. returning value). */ -value +value_ptr value_being_returned (valtype, retbuf, struct_return) register struct type *valtype; char retbuf[REGISTER_BYTES]; int struct_return; /*ARGSUSED*/ { - register value val; + register value_ptr val; CORE_ADDR addr; #if defined (EXTRACT_STRUCT_VALUE_ADDRESS) @@ -1431,7 +1437,7 @@ value_being_returned (valtype, retbuf, struct_return) int using_struct_return (function, funcaddr, value_type, gcc_p) - value function; + value_ptr function; CORE_ADDR funcaddr; struct type *value_type; int gcc_p; @@ -1456,7 +1462,7 @@ using_struct_return (function, funcaddr, value_type, gcc_p) void set_return_value (val) - value val; + value_ptr val; { register enum type_code code = TYPE_CODE (VALUE_TYPE (val)); double dbuf; diff --git a/gnu/usr.bin/gdb/gdb/version.c b/gnu/usr.bin/gdb/gdb/version.c index d32e958a2dd1..43f63d2c71ae 100644 --- a/gnu/usr.bin/gdb/gdb/version.c +++ b/gnu/usr.bin/gdb/gdb/version.c @@ -1,3 +1,3 @@ -char *version = "4.11"; -char *host_canonical = "i386-unknown-freebsd"; -char *target_canonical = "i386-unknown-freebsd"; +char *version = "4.13"; +char *host_name = "i386-unknown-freebsd"; +char *target_name = "i386-unknown-freebsd"; diff --git a/gnu/usr.bin/gdb/gdb/xm.h b/gnu/usr.bin/gdb/gdb/xm.h index fe5fe7601fda..6a71227aec77 100644 --- a/gnu/usr.bin/gdb/gdb/xm.h +++ b/gnu/usr.bin/gdb/gdb/xm.h @@ -26,8 +26,4 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define PSIGNAL_IN_SIGNAL_H -/* Get rid of any system-imposed stack limit if possible. */ - -#define SET_STACK_LIMIT_HUGE - #define HAVE_TERMIOS diff --git a/gnu/usr.bin/gdb/libiberty/Makefile b/gnu/usr.bin/gdb/libiberty/Makefile index 838781295e82..2bc6abfab4a7 100644 --- a/gnu/usr.bin/gdb/libiberty/Makefile +++ b/gnu/usr.bin/gdb/libiberty/Makefile @@ -1,7 +1,7 @@ LIB= iberty SRCS= argv.c basename.c concat.c cplus-dem.c fdmatch.c getopt.c \ getopt1.c ieee-float.c obstack.c spaces.c strerror.c strsignal.c \ - xmalloc.c + vasprintf.c xmalloc.c CFLAGS+= -I$(.CURDIR)/../gdb/. NOPROFILE=no diff --git a/gnu/usr.bin/gdb/libiberty/README.FreeBSD b/gnu/usr.bin/gdb/libiberty/README.FreeBSD index 573fa0a9a809..0964280eb08e 100644 --- a/gnu/usr.bin/gdb/libiberty/README.FreeBSD +++ b/gnu/usr.bin/gdb/libiberty/README.FreeBSD @@ -1,7 +1,4 @@ This is a greatly pared down libiberty directory. Only what's required to build -gdb-4.12 on FreeBSD was kept. +gdb-4.13 on FreeBSD 2.0 was kept. -This is temporary. In FreeBSD 2.0 a fully ported libiberty will likely appear -as a system library for use by all the build tools. - -paul@freefall.cdrom.com +gj@freebsd.org diff --git a/gnu/usr.bin/gdb/libiberty/argv.c b/gnu/usr.bin/gdb/libiberty/argv.c index fed46e7d797b..300ada2ce3fc 100644 --- a/gnu/usr.bin/gdb/libiberty/argv.c +++ b/gnu/usr.bin/gdb/libiberty/argv.c @@ -42,6 +42,9 @@ char *alloca (); #include "alloca-conf.h" +#include "ansidecl.h" +#include "libiberty.h" + /* Routines imported from standard C runtime libraries. */ #ifdef __STDC__ @@ -280,6 +283,11 @@ char *input; } argc++; argv[argc] = NULL; + + while (isspace (*input)) + { + input++; + } } while (*input != EOS); } @@ -299,6 +307,10 @@ static char *tests[] = "arg 'Jack said \\'hi\\'' has single quotes", "arg 'Jack said \\\"hi\\\"' has double quotes", "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9", + + /* This should be expanded into only one argument. */ + "trailing-whitespace ", + "", NULL }; diff --git a/gnu/usr.bin/gdb/libiberty/basename.c b/gnu/usr.bin/gdb/libiberty/basename.c index f61a308e9b53..db1bb6cbbdeb 100644 --- a/gnu/usr.bin/gdb/libiberty/basename.c +++ b/gnu/usr.bin/gdb/libiberty/basename.c @@ -39,6 +39,9 @@ BUGS */ +#include "ansidecl.h" +#include "libiberty.h" + char * basename (name) char *name; diff --git a/gnu/usr.bin/gdb/libiberty/concat.c b/gnu/usr.bin/gdb/libiberty/concat.c index 61f7d97481ce..fd720d1d2627 100644 --- a/gnu/usr.bin/gdb/libiberty/concat.c +++ b/gnu/usr.bin/gdb/libiberty/concat.c @@ -1,5 +1,5 @@ /* Concatenate variable number of strings. - Copyright (C) 1991 Free Software Foundation, Inc. + Copyright (C) 1991, 1994 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support This file is part of the libiberty library. @@ -53,29 +53,61 @@ NOTES */ +#include "ansidecl.h" +#include "libiberty.h" + +#ifdef ANSI_PROTOTYPES +#include +#else #include +#endif + +#ifdef __STDC__ +#include +extern size_t strlen (const char *s); +#else +extern int strlen (); +#endif #define NULLP (char *)0 -extern char *xmalloc (); - /* VARARGS */ +#ifdef ANSI_PROTOTYPES +char * +concat (const char *first, ...) +#else char * concat (va_alist) va_dcl +#endif { - register int length = 0; + register int length; register char *newstr; register char *end; - register char *arg; + register const char *arg; va_list args; +#ifndef ANSI_PROTOTYPES + const char *first; +#endif /* First compute the size of the result and get sufficient memory. */ +#ifdef ANSI_PROTOTYPES + va_start (args, first); +#else va_start (args); - while ((arg = va_arg (args, char *)) != NULLP) + first = va_arg (args, const char *); +#endif + + if (first == NULLP) + length = 0; + else { - length += strlen (arg); + length = strlen (first); + while ((arg = va_arg (args, const char *)) != NULLP) + { + length += strlen (arg); + } } newstr = (char *) xmalloc (length + 1); va_end (args); @@ -84,14 +116,27 @@ concat (va_alist) if (newstr != NULLP) { +#ifdef ANSI_PROTOTYPES + va_start (args, first); +#else va_start (args); + first = va_arg (args, const char *); +#endif end = newstr; - while ((arg = va_arg (args, char *)) != NULLP) + if (first != NULLP) { + arg = first; while (*arg) { *end++ = *arg++; } + while ((arg = va_arg (args, const char *)) != NULLP) + { + while (*arg) + { + *end++ = *arg++; + } + } } *end = '\000'; va_end (args); @@ -104,6 +149,9 @@ concat (va_alist) /* Simple little test driver. */ +#include + +int main () { printf ("\"\" = \"%s\"\n", concat (NULLP)); @@ -113,6 +161,7 @@ main () printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP)); printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP)); printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP)); + return 0; } #endif diff --git a/gnu/usr.bin/gdb/libiberty/cplus-dem.c b/gnu/usr.bin/gdb/libiberty/cplus-dem.c index 2ad0e971487b..5465fd809a07 100644 --- a/gnu/usr.bin/gdb/libiberty/cplus-dem.c +++ b/gnu/usr.bin/gdb/libiberty/cplus-dem.c @@ -32,10 +32,9 @@ Cambridge, MA 02139, USA. */ #include #include -extern char *xmalloc PARAMS((long)); -extern char *xrealloc PARAMS((PTR, long)); -extern char *strstr PARAMS ((const char *, const char *)); -extern void free PARAMS((PTR)); +#include "libiberty.h" + +extern char *strstr (); /* In order to allow a single demangler executable to demangle strings using various common values of CPLUS_MARKER, as well as any specific @@ -96,6 +95,8 @@ static CONST struct optable {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */ {"new", " new", 0}, /* old (1.91, and 1.x) */ {"delete", " delete", 0}, /* old (1.91, and 1.x) */ + {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */ + {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */ {"as", "=", DMGL_ANSI}, /* ansi */ {"ne", "!=", DMGL_ANSI}, /* old, ansi */ {"eq", "==", DMGL_ANSI}, /* old, ansi */ @@ -303,6 +304,129 @@ consume_count (type) return (count); } +int +cplus_demangle_opname (opname, result, options) + char *opname; + char *result; + int options; +{ + int len, i, len1, ret; + string type; + struct work_stuff work[1]; + CONST char *tem; + + len = strlen(opname); + result[0] = '\0'; + ret = 0; + work->options = options; + + if (opname[0] == '_' && opname[1] == '_' + && opname[2] == 'o' && opname[3] == 'p') + { + /* ANSI. */ + /* type conversion operator. */ + tem = opname + 4; + if (do_type (work, &tem, &type)) + { + strcat (result, "operator "); + strncat (result, type.b, type.p - type.b); + string_delete (&type); + ret = 1; + } + } + else if (opname[0] == '_' && opname[1] == '_' + && opname[2] >= 'a' && opname[2] <= 'z' + && opname[3] >= 'a' && opname[3] <= 'z') + { + if (opname[4] == '\0') + { + /* Operator. */ + for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + { + if (strlen (optable[i].in) == 2 + && memcmp (optable[i].in, opname + 2, 2) == 0) + { + strcat (result, "operator"); + strcat (result, optable[i].out); + ret = 1; + break; + } + } + } + else + { + if (opname[2] == 'a' && opname[5] == '\0') + { + /* Assignment. */ + for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + { + if (strlen (optable[i].in) == 3 + && memcmp (optable[i].in, opname + 2, 3) == 0) + { + strcat (result, "operator"); + strcat (result, optable[i].out); + ret = 1; + break; + } + } + } + } + } + else if (len >= 3 + && opname[0] == 'o' + && opname[1] == 'p' + && strchr (cplus_markers, opname[2]) != NULL) + { + /* see if it's an assignment expression */ + if (len >= 10 /* op$assign_ */ + && memcmp (opname + 3, "assign_", 7) == 0) + { + for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + { + len1 = len - 10; + if (strlen (optable[i].in) == len1 + && memcmp (optable[i].in, opname + 10, len1) == 0) + { + strcat (result, "operator"); + strcat (result, optable[i].out); + strcat (result, "="); + ret = 1; + break; + } + } + } + else + { + for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + { + len1 = len - 3; + if (strlen (optable[i].in) == len1 + && memcmp (optable[i].in, opname + 3, len1) == 0) + { + strcat (result, "operator"); + strcat (result, optable[i].out); + ret = 1; + break; + } + } + } + } + else if (len >= 5 && memcmp (opname, "type", 4) == 0 + && strchr (cplus_markers, opname[4]) != NULL) + { + /* type conversion operator */ + tem = opname + 5; + if (do_type (work, &tem, &type)) + { + strcat (result, "operator "); + strncat (result, type.b, type.p - type.b); + string_delete (&type); + ret = 1; + } + } + return ret; + +} /* Takes operator name as e.g. "++" and returns mangled operator name (e.g. "postincrement_expr"), or NULL if not found. @@ -343,9 +467,9 @@ int cplus_match (mangled, text, text_len) } } -/* char *cplus_demangle (const char *name, int options) +/* char *cplus_demangle (const char *mangled, int options) - If NAME is a mangled function name produced by GNU C++, then + If MANGLED is a mangled function name produced by GNU C++, then a pointer to a malloced string giving a C++ representation of the name will be returned; otherwise NULL will be returned. It is the caller's responsibility to free the string which @@ -369,7 +493,7 @@ int cplus_match (mangled, text, text_len) Note that any leading underscores, or other such characters prepended by the compilation system, are presumed to have already been stripped from - TYPE. */ + MANGLED. */ char * cplus_demangle (mangled, options) @@ -582,7 +706,15 @@ demangle_signature (work, mangled, declp) /* G++ Template */ string_init(&trawname); string_init(&tname); + if (oldmangled == NULL) + { + oldmangled = *mangled; + } success = demangle_template (work, mangled, &tname, &trawname); + if (success) + { + remember_type (work, oldmangled, *mangled - oldmangled); + } string_append(&tname, "::"); string_prepends(declp, &tname); if (work -> destructor & 1) @@ -598,6 +730,7 @@ demangle_signature (work, mangled, declp) } string_delete(&trawname); string_delete(&tname); + oldmangled = NULL; expect_func = 1; break; @@ -628,7 +761,9 @@ demangle_signature (work, mangled, declp) } break; } +/* if (AUTO_DEMANGLING || GNU_DEMANGLING) +*/ { if (success && expect_func) { @@ -709,7 +844,7 @@ demangle_template (work, mangled, tname, trawname) (*mangled)++; start = *mangled; /* get template name */ - if ((r = consume_count (mangled)) == 0) + if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r) { return (0); } @@ -770,6 +905,7 @@ demangle_template (work, mangled, tname, trawname) switch (*old_p) { case 'P': + case 'p': case 'R': done = is_pointer = 1; break; @@ -782,7 +918,9 @@ demangle_template (work, mangled, tname, trawname) case 'O': /* ??? */ old_p++; continue; - case 'Q': /* repetition of following */ + case 'Q': /* qualified name */ + done = is_integral = 1; + break; case 'T': /* remembered type */ abort (); break; @@ -803,7 +941,10 @@ demangle_template (work, mangled, tname, trawname) done = is_real = 1; break; default: - abort (); + /* it's probably user defined type, let's assume + it's integeral, it seems hard to figure out + what it really is */ + done = is_integral = 1; } } if (is_integral) @@ -865,6 +1006,8 @@ demangle_template (work, mangled, tname, trawname) } need_comma = 1; } + if (tname->p[-1] == '>') + string_append (tname, " "); string_append (tname, ">"); /* @@ -905,6 +1048,42 @@ arm_pt (work, mangled, n, anchor, args) return 0; } +static void +demangle_arm_pt (work, mangled, n, declp) + struct work_stuff *work; + CONST char **mangled; + int n; + string *declp; +{ + CONST char *p; + CONST char *args; + CONST char *e = *mangled + n; + + /* ARM template? */ + if (arm_pt (work, *mangled, n, &p, &args)) + { + string arg; + string_init (&arg); + string_appendn (declp, *mangled, p - *mangled); + string_append (declp, "<"); + /* should do error checking here */ + while (args < e) { + string_clear (&arg); + do_type (work, &args, &arg); + string_appends (declp, &arg); + string_append (declp, ","); + } + string_delete (&arg); + --declp->p; + string_append (declp, ">"); + } + else + { + string_appendn (declp, *mangled, n); + } + *mangled += n; +} + static int demangle_class_name (work, mangled, declp) struct work_stuff *work; @@ -916,35 +1095,11 @@ demangle_class_name (work, mangled, declp) n = consume_count (mangled); if (strlen (*mangled) >= n) - { - CONST char *p; - CONST char *args; - CONST char *e = *mangled + n; - /* ARM template? */ - if (arm_pt (work, *mangled, n, &p, &args)) - { - string arg; - string_init (&arg); - string_appendn (declp, *mangled, p - *mangled); - string_append (declp, "<"); - /* should do error checking here */ - while (args < e) { - string_clear (&arg); - do_type (work, &args, &arg); - string_appends (declp, &arg); - string_append (declp, ","); - } - string_delete (&arg); - --declp->p; - string_append (declp, ">"); - } - else - { - string_appendn (declp, *mangled, n); - } - *mangled += n; - success = 1; - } + { + demangle_arm_pt (work, mangled, n, declp); + success = 1; + } + return (success); } @@ -1057,17 +1212,24 @@ demangle_prefix (work, mangled, declp) CONST char *scan; int i; - if (strncmp(*mangled, "_GLOBAL_$D$", 11) == 0) + if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0) { - /* it's a GNU global destructor to be executed at program exit */ - (*mangled) += 11; - work->destructor = 2; - } - else if (strncmp(*mangled, "_GLOBAL_$I$", 11) == 0) - { - /* it's a GNU global constructor to be executed at program initial */ - (*mangled) += 11; - work->constructor = 2; + char *marker = strchr (cplus_markers, (*mangled)[8]); + if (marker != NULL && *marker == (*mangled)[10]) + { + if ((*mangled)[9] == 'D') + { + /* it's a GNU global destructor to be executed at program exit */ + (*mangled) += 11; + work->destructor = 2; + } + else if ((*mangled)[9] == 'I') + { + /* it's a GNU global constructor to be executed at program init */ + (*mangled) += 11; + work->constructor = 2; + } + } } else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0) { @@ -1134,9 +1296,12 @@ demangle_prefix (work, mangled, declp) } else { - /* A GNU style constructor starts with "__[0-9Qt]. */ - work -> constructor += 1; - *mangled = scan + 2; + /* A GNU style constructor starts with __[0-9Qt]. But cfront uses + names like __Q2_3foo3bar for nested type names. So don't accept + this style of constructor for cfront demangling. */ + if (!(LUCID_DEMANGLING || ARM_DEMANGLING)) + work -> constructor += 1; + *mangled = scan + 2; } } else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't')) @@ -1163,6 +1328,14 @@ demangle_prefix (work, mangled, declp) } } } + else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't') + { + /* Cfront-style parameterized type. Handled later as a signature. */ + success = 1; + + /* ARM template? */ + demangle_arm_pt (work, mangled, strlen (*mangled), declp); + } else if (*(scan + 2) != '\0') { /* Mangled name does not start with "__" but does have one somewhere @@ -1206,9 +1379,11 @@ DESCRIPTION _$_3foo (destructor for class foo) _vt$foo (foo virtual table) _vt$foo$bar (foo::bar virtual table) + __vt_foo (foo virtual table, new style with thunks) _3foo$varname (static data member) _Q22rs2tu$vw (static data member) __t6vector1Zii (constructor with template) + __thunk_4__$_7ostream (virtual function thunk) */ static int @@ -1230,35 +1405,62 @@ gnu_special (work, mangled, declp) work -> destructor += 1; } else if ((*mangled)[0] == '_' - && (*mangled)[1] == 'v' - && (*mangled)[2] == 't' - && strchr (cplus_markers, (*mangled)[3]) != NULL) + && (((*mangled)[1] == '_' + && (*mangled)[2] == 'v' + && (*mangled)[3] == 't' + && (*mangled)[4] == '_') + || ((*mangled)[1] == 'v' + && (*mangled)[2] == 't' + && strchr (cplus_markers, (*mangled)[3]) != NULL))) { /* Found a GNU style virtual table, get past "_vt" and create the decl. Note that we consume the entire mangled input string, which means that demangle_signature has no work to do. */ - (*mangled) += 4; + if ((*mangled)[2] == 'v') + (*mangled) += 5; /* New style, with thunks: "__vt_" */ + else + (*mangled) += 4; /* Old style, no thunks: "_vt" */ while (**mangled != '\0') { - if (isdigit(*mangled[0])) + p = strpbrk (*mangled, cplus_markers); + switch (**mangled) { - n = consume_count(mangled); + case 'Q': + success = demangle_qualified (work, mangled, declp, 0, 1); + break; + case 't': + success = demangle_template (work, mangled, declp, 0); + break; + default: + if (isdigit(*mangled[0])) + { + n = consume_count(mangled); + } + else + { + n = strcspn (*mangled, cplus_markers); + } + string_appendn (declp, *mangled, n); + (*mangled) += n; + } + + if (success && ((p == NULL) || (p == *mangled))) + { + if (p != NULL) + { + string_append (declp, "::"); + (*mangled)++; + } } else { - n = strcspn (*mangled, cplus_markers); - } - string_appendn (declp, *mangled, n); - (*mangled) += n; - - if (**mangled != '\0') - { - string_append (declp, "::"); - (*mangled)++; + success = 0; + break; } } - string_append (declp, " virtual table"); + if (success) + string_append (declp, " virtual table"); } else if ((*mangled)[0] == '_' && (strchr("0123456789Qt", (*mangled)[1]) != NULL) @@ -1294,6 +1496,25 @@ gnu_special (work, mangled, declp) success = 0; } } + else if (strncmp (*mangled, "__thunk_", 8) == 0) + { + int delta = ((*mangled) += 8, consume_count (mangled)); + char *method = cplus_demangle (++*mangled, work->options); + if (method) + { + char buf[50]; + sprintf (buf, "virtual function thunk (delta:%d) for ", -delta); + string_append (declp, buf); + string_append (declp, method); + free (method); + n = strlen (*mangled); + (*mangled) += n; + } + else + { + success = 0; + } + } else { success = 0; @@ -1621,6 +1842,7 @@ do_type (work, mangled, result) /* A pointer type */ case 'P': + case 'p': (*mangled)++; string_prepend (&decl, "*"); break; @@ -1904,6 +2126,11 @@ demangle_fund_type (work, mangled, result) APPEND_BLANK (result); string_append (result, "short"); break; + case 'b': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "bool"); + break; case 'c': (*mangled)++; APPEND_BLANK (result); @@ -2271,7 +2498,8 @@ demangle_function_name (work, mangled, declp, scan) } } } - else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type$", 5) == 0) + else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0 + && strchr (cplus_markers, declp->b[4]) != NULL) { /* type conversion operator */ tem = declp->b + 5; @@ -2486,9 +2714,10 @@ string_prependn (p, s, n) } } -/* To generate a standalone demangler program for testing purposes, just - compile and link this file with -DMAIN. When run, it demangles each - command line arg, or each stdin string, and prints the result on stdout. */ +/* To generate a standalone demangler program for testing purposes, + just compile and link this file with -DMAIN and libiberty.a. When + run, it demangles each command line arg, or each stdin string, and + prints the result on stdout. */ #ifdef MAIN @@ -2510,35 +2739,6 @@ demangle_it (mangled_name) } } -char * -xmalloc (size) - long size; -{ - char * newmem; - - if ((newmem = (char *) malloc ((int) size)) == NULL) - { - fprintf (stderr, "\nCan't allocate %u bytes\n", size); - exit (1); - } - return (newmem); -} - -char * -xrealloc (oldmem, size) - PTR oldmem; - long size; -{ - char * newmem; - - if ((newmem = (char *) realloc ((char *) oldmem, (int) size)) == NULL) - { - fprintf (stderr, "\nCan't reallocate %u bytes\n", size); - exit (1); - } - return (newmem); -} - #include "getopt.h" static char *program_name; @@ -2550,8 +2750,9 @@ usage (stream, status) int status; { fprintf (stream, "\ -Usage: %s [-_] [-s {gnu,lucid,arm}] [--strip-underscores]\n\ - [--format={gnu,lucid,arm}] [--help] [--version] [arg...]\n", +Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\ + [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\ + [--help] [--version] [arg...]\n", program_name); exit (status); } @@ -2568,6 +2769,7 @@ static struct option long_options[] = { {"strip-underscores", no_argument, 0, '_'}, {"format", required_argument, 0, 's'}, {"help", no_argument, 0, 'h'}, + {"no-strip-underscores", no_argument, 0, 'n'}, {"version", no_argument, 0, 'v'}, {0, no_argument, 0, 0} }; @@ -2581,9 +2783,11 @@ main (argc, argv) int c; program_name = argv[0]; + xmalloc_set_program_name (program_name); + strip_underscore = prepends_underscore; - while ((c = getopt_long (argc, argv, "_s:", long_options, (int *) 0)) != EOF) + while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF) { switch (c) { @@ -2592,6 +2796,9 @@ main (argc, argv) break; case 'h': usage (stdout, 0); + case 'n': + strip_underscore = 0; + break; case 'v': printf ("GNU %s version %s\n", program_name, program_version); exit (0); diff --git a/gnu/usr.bin/gdb/libiberty/fdmatch.c b/gnu/usr.bin/gdb/libiberty/fdmatch.c index 0a6de2af0fd0..10033d4b69ea 100644 --- a/gnu/usr.bin/gdb/libiberty/fdmatch.c +++ b/gnu/usr.bin/gdb/libiberty/fdmatch.c @@ -47,6 +47,8 @@ BUGS */ +#include "ansidecl.h" +#include "libiberty.h" #include #include diff --git a/gnu/usr.bin/gdb/libiberty/getopt.c b/gnu/usr.bin/gdb/libiberty/getopt.c index c7a8b0326418..671553dd24ae 100644 --- a/gnu/usr.bin/gdb/libiberty/getopt.c +++ b/gnu/usr.bin/gdb/libiberty/getopt.c @@ -3,7 +3,7 @@ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! - Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or @@ -20,9 +20,22 @@ along with this program; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + #ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include +#else #include "config.h" #endif +#endif #ifndef __STDC__ /* This is a separate conditional since some stdc systems @@ -32,11 +45,6 @@ #endif #endif -/* This tells Alpha OSF/1 not to define a getopt prototype in . */ -#ifndef _NO_PROTO -#define _NO_PROTO -#endif - #include /* Comment out all this code if we are using the GNU C Library, and are not @@ -58,11 +66,6 @@ #include #endif /* GNU C library. */ -/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a - long-named option. Because this is not POSIX.2 compliant, it is - being phased out. */ -/* #define GETOPT_COMPAT */ - /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. @@ -85,7 +88,7 @@ Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ -char *optarg = 0; +char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller @@ -185,19 +188,18 @@ my_index (str, chr) } /* If using GCC, we can safely declare strlen this way. - If not using GCC, it is ok not to declare it. - (Supposedly there are some machines where it might get a warning, - but changing this conditional to __STDC__ is too risky.) */ + If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ -#ifdef IN_GCC -#include "gstddef.h" -#else -#include -#endif -extern size_t strlen (const char *); -#endif +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#ifndef __STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ -#endif /* GNU C library. */ +#endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ @@ -272,6 +274,40 @@ exchange (argv) first_nonopt += (optind - last_nonopt); last_nonopt = optind; } + +/* Initialize the internal data when the first call is made. */ + +static const char * +_getopt_initialize (optstring) + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + + return optstring; +} /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. @@ -338,41 +374,15 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int *longind; int long_only; { - int option_index; - - optarg = 0; - - /* Initialize the internal data when the first call is made. - Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ + optarg = NULL; if (optind == 0) - { - first_nonopt = last_nonopt = optind = 1; - - nextchar = NULL; - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (getenv ("POSIXLY_CORRECT") != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - } + optstring = _getopt_initialize (optstring); if (nextchar == NULL || *nextchar == '\0') { + /* Advance to the next ARGV-element. */ + if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, @@ -383,21 +393,16 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) else if (last_nonopt != optind) first_nonopt = optind; - /* Now skip any additional non-options + /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc - && (argv[optind][0] != '-' || argv[optind][1] == '\0') -#ifdef GETOPT_COMPAT - && (longopts == NULL - || argv[optind][0] != '+' || argv[optind][1] == '\0') -#endif /* GETOPT_COMPAT */ - ) + && (argv[optind][0] != '-' || argv[optind][1] == '\0')) optind++; last_nonopt = optind; } - /* Special ARGV-element `--' means premature end of options. + /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ @@ -430,12 +435,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ - if ((argv[optind][0] != '-' || argv[optind][1] == '\0') -#ifdef GETOPT_COMPAT - && (longopts == NULL - || argv[optind][0] != '+' || argv[optind][1] == '\0') -#endif /* GETOPT_COMPAT */ - ) + if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) { if (ordering == REQUIRE_ORDER) return EOF; @@ -444,36 +444,48 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) } /* We have found another option-ARGV-element. - Start decoding its characters. */ + Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + if (longopts != NULL - && ((argv[optind][0] == '-' - && (argv[optind][1] == '-' || long_only)) -#ifdef GETOPT_COMPAT - || argv[optind][0] == '+' -#endif /* GETOPT_COMPAT */ - )) + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { + char *nameend; const struct option *p; - char *s = nextchar; + const struct option *pfound = NULL; int exact = 0; int ambig = 0; - const struct option *pfound = NULL; int indfound; + int option_index; - while (*s && *s != '=') - s++; + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; - /* Test all options for either exact match or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; - p++, option_index++) - if (!strncmp (p->name, nextchar, s - nextchar)) + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) { - if (s - nextchar == strlen (p->name)) + if (nameend - nextchar == strlen (p->name)) { /* Exact match found. */ pfound = p; @@ -488,7 +500,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) indfound = option_index; } else - /* Second nonexact match found. */ + /* Second or later nonexact match found. */ ambig = 1; } @@ -506,12 +518,12 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) { option_index = indfound; optind++; - if (*s) + if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) - optarg = s + 1; + optarg = nameend + 1; else { if (opterr) @@ -554,14 +566,12 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) } return pfound->val; } + /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' -#ifdef GETOPT_COMPAT - || argv[optind][0] == '+' -#endif /* GETOPT_COMPAT */ || my_index (optstring, *nextchar) == NULL) { if (opterr) @@ -581,7 +591,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) } } - /* Look at and handle the next option-character. */ + /* Look at and handle the next short option-character. */ { char c = *nextchar++; @@ -595,16 +605,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) { if (opterr) { -#if 0 - if (c < 040 || c >= 0177) - fprintf (stderr, "%s: unrecognized option, character code 0%o\n", - argv[0], c); - else - fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); -#else /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); -#endif } optopt = c; return '?'; @@ -620,7 +622,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) optind++; } else - optarg = 0; + optarg = NULL; nextchar = NULL; } else @@ -637,14 +639,9 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) { if (opterr) { -#if 0 - fprintf (stderr, "%s: option `-%c' requires an argument\n", - argv[0], c); -#else /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: option requires an argument -- %c\n", argv[0], c); -#endif } optopt = c; if (optstring[0] == ':') diff --git a/gnu/usr.bin/gdb/libiberty/getopt1.c b/gnu/usr.bin/gdb/libiberty/getopt1.c index 6806da5f983f..90dc12a04b94 100644 --- a/gnu/usr.bin/gdb/libiberty/getopt1.c +++ b/gnu/usr.bin/gdb/libiberty/getopt1.c @@ -17,8 +17,15 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include +#else #include "config.h" #endif +#endif #include "getopt.h" diff --git a/gnu/usr.bin/gdb/libiberty/obstack.c b/gnu/usr.bin/gdb/libiberty/obstack.c index 4297bbbd51f1..f3f39fc2f423 100644 --- a/gnu/usr.bin/gdb/libiberty/obstack.c +++ b/gnu/usr.bin/gdb/libiberty/obstack.c @@ -1,5 +1,5 @@ /* obstack.c - subroutines used implicitly by object stack macros - Copyright (C) 1988, 1993 Free Software Foundation, Inc. + Copyright (C) 1988, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the @@ -28,7 +28,15 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ +/* CYGNUS LOCAL. No, don't comment the code out. We will be using + ../include/obstack.h, which was changed relatively recently in a + way that is not binary compatible. Until we feel confident that + nobody is using the old obstack.c code, force the use of this code. + This issue will arise anytime a change is made which is not binary + compatible. #if defined (_LIBC) || !defined (__GNU_LIBRARY__) +*/ +#if 1 #ifdef __STDC__ @@ -83,9 +91,13 @@ struct obstack *_obstack; /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). Objects start on multiples of ALIGNMENT (0 means use default). CHUNKFUN is the function to use to allocate chunks, - and FREEFUN the function to free them. */ + and FREEFUN the function to free them. -void + Return nonzero if successful, zero if out of memory. + To recover from an out of memory error, + free up some memory, then call this again. */ + +int _obstack_begin (h, size, alignment, chunkfun, freefun) struct obstack *h; int size; @@ -121,15 +133,22 @@ _obstack_begin (h, size, alignment, chunkfun, freefun) h->use_extra_arg = 0; chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) + { + h->alloc_failed = 1; + return 0; + } + h->alloc_failed = 0; h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size; chunk->prev = 0; /* The initial chunk now contains no empty object. */ h->maybe_empty_object = 0; + return 1; } -void +int _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) struct obstack *h; int size; @@ -167,12 +186,19 @@ _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) h->use_extra_arg = 1; chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) + { + h->alloc_failed = 1; + return 0; + } + h->alloc_failed = 0; h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size; chunk->prev = 0; /* The initial chunk now contains no empty object. */ h->maybe_empty_object = 0; + return 1; } /* Allocate a new current chunk for the obstack *H @@ -199,7 +225,14 @@ _obstack_newchunk (h, length) new_size = h->chunk_size; /* Allocate and initialize the new chunk. */ - new_chunk = h->chunk = CALL_CHUNKFUN (h, new_size); + new_chunk = CALL_CHUNKFUN (h, new_size); + if (!new_chunk) + { + h->alloc_failed = 1; + return; + } + h->alloc_failed = 0; + h->chunk = new_chunk; new_chunk->prev = old_chunk; new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; diff --git a/gnu/usr.bin/gdb/libiberty/spaces.c b/gnu/usr.bin/gdb/libiberty/spaces.c index 28f07462d372..6b1c9d1815ea 100644 --- a/gnu/usr.bin/gdb/libiberty/spaces.c +++ b/gnu/usr.bin/gdb/libiberty/spaces.c @@ -37,8 +37,10 @@ BUGS */ +#include "ansidecl.h" +#include "libiberty.h" -char * +const char * spaces (count) int count; { @@ -55,6 +57,8 @@ spaces (count) free (buf); } buf = malloc (count + 1); + if (buf == (char *) 0) + return 0; for (t = buf + count ; t != buf ; ) { *--t = ' '; @@ -62,6 +66,6 @@ spaces (count) maxsize = count; buf[count] = '\0'; } - return (buf + maxsize - count); + return (const char *) (buf + maxsize - count); } diff --git a/gnu/usr.bin/gdb/libiberty/strerror.c b/gnu/usr.bin/gdb/libiberty/strerror.c index f377311a4f56..5c0a58d97a46 100644 --- a/gnu/usr.bin/gdb/libiberty/strerror.c +++ b/gnu/usr.bin/gdb/libiberty/strerror.c @@ -18,6 +18,9 @@ License along with libiberty; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "ansidecl.h" +#include "libiberty.h" + #include "config.h" #ifndef NEED_sys_errlist @@ -43,9 +46,6 @@ Cambridge, MA 02139, USA. */ extern void *malloc (size_t size); /* 4.10.3.3 */ extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */ #else /* !__STDC__ */ -#ifndef const -#define const -#endif extern char *malloc (); /* Standard memory allocater */ extern char *memset (); #endif /* __STDC__ */ @@ -68,382 +68,390 @@ extern char *memset (); struct error_info { int value; /* The numeric value from */ - char *name; /* The equivalent symbolic value */ - char *msg; /* Short message about this value */ + const char *name; /* The equivalent symbolic value */ +#ifdef NEED_sys_errlist + const char *msg; /* Short message about this value */ +#endif }; +#ifdef NEED_sys_errlist +# define ENTRY(value, name, msg) {value, name, msg} +#else +# define ENTRY(value, name, msg) {value, name} +#endif + static const struct error_info error_table[] = { #if defined (EPERM) - {EPERM, "EPERM", "Not owner"}, + ENTRY(EPERM, "EPERM", "Not owner"), #endif #if defined (ENOENT) - {ENOENT, "ENOENT", "No such file or directory"}, + ENTRY(ENOENT, "ENOENT", "No such file or directory"), #endif #if defined (ESRCH) - {ESRCH, "ESRCH", "No such process"}, + ENTRY(ESRCH, "ESRCH", "No such process"), #endif #if defined (EINTR) - {EINTR, "EINTR", "Interrupted system call"}, + ENTRY(EINTR, "EINTR", "Interrupted system call"), #endif #if defined (EIO) - {EIO, "EIO", "I/O error"}, + ENTRY(EIO, "EIO", "I/O error"), #endif #if defined (ENXIO) - {ENXIO, "ENXIO", "No such device or address"}, + ENTRY(ENXIO, "ENXIO", "No such device or address"), #endif #if defined (E2BIG) - {E2BIG, "E2BIG", "Arg list too long"}, + ENTRY(E2BIG, "E2BIG", "Arg list too long"), #endif #if defined (ENOEXEC) - {ENOEXEC, "ENOEXEC", "Exec format error"}, + ENTRY(ENOEXEC, "ENOEXEC", "Exec format error"), #endif #if defined (EBADF) - {EBADF, "EBADF", "Bad file number"}, + ENTRY(EBADF, "EBADF", "Bad file number"), #endif #if defined (ECHILD) - {ECHILD, "ECHILD", "No child processes"}, + ENTRY(ECHILD, "ECHILD", "No child processes"), #endif #if defined (EWOULDBLOCK) /* Put before EAGAIN, sometimes aliased */ - {EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"}, + ENTRY(EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"), #endif #if defined (EAGAIN) - {EAGAIN, "EAGAIN", "No more processes"}, + ENTRY(EAGAIN, "EAGAIN", "No more processes"), #endif #if defined (ENOMEM) - {ENOMEM, "ENOMEM", "Not enough space"}, + ENTRY(ENOMEM, "ENOMEM", "Not enough space"), #endif #if defined (EACCES) - {EACCES, "EACCES", "Permission denied"}, + ENTRY(EACCES, "EACCES", "Permission denied"), #endif #if defined (EFAULT) - {EFAULT, "EFAULT", "Bad address"}, + ENTRY(EFAULT, "EFAULT", "Bad address"), #endif #if defined (ENOTBLK) - {ENOTBLK, "ENOTBLK", "Block device required"}, + ENTRY(ENOTBLK, "ENOTBLK", "Block device required"), #endif #if defined (EBUSY) - {EBUSY, "EBUSY", "Device busy"}, + ENTRY(EBUSY, "EBUSY", "Device busy"), #endif #if defined (EEXIST) - {EEXIST, "EEXIST", "File exists"}, + ENTRY(EEXIST, "EEXIST", "File exists"), #endif #if defined (EXDEV) - {EXDEV, "EXDEV", "Cross-device link"}, + ENTRY(EXDEV, "EXDEV", "Cross-device link"), #endif #if defined (ENODEV) - {ENODEV, "ENODEV", "No such device"}, + ENTRY(ENODEV, "ENODEV", "No such device"), #endif #if defined (ENOTDIR) - {ENOTDIR, "ENOTDIR", "Not a directory"}, + ENTRY(ENOTDIR, "ENOTDIR", "Not a directory"), #endif #if defined (EISDIR) - {EISDIR, "EISDIR", "Is a directory"}, + ENTRY(EISDIR, "EISDIR", "Is a directory"), #endif #if defined (EINVAL) - {EINVAL, "EINVAL", "Invalid argument"}, + ENTRY(EINVAL, "EINVAL", "Invalid argument"), #endif #if defined (ENFILE) - {ENFILE, "ENFILE", "File table overflow"}, + ENTRY(ENFILE, "ENFILE", "File table overflow"), #endif #if defined (EMFILE) - {EMFILE, "EMFILE", "Too many open files"}, + ENTRY(EMFILE, "EMFILE", "Too many open files"), #endif #if defined (ENOTTY) - {ENOTTY, "ENOTTY", "Not a typewriter"}, + ENTRY(ENOTTY, "ENOTTY", "Not a typewriter"), #endif #if defined (ETXTBSY) - {ETXTBSY, "ETXTBSY", "Text file busy"}, + ENTRY(ETXTBSY, "ETXTBSY", "Text file busy"), #endif #if defined (EFBIG) - {EFBIG, "EFBIG", "File too large"}, + ENTRY(EFBIG, "EFBIG", "File too large"), #endif #if defined (ENOSPC) - {ENOSPC, "ENOSPC", "No space left on device"}, + ENTRY(ENOSPC, "ENOSPC", "No space left on device"), #endif #if defined (ESPIPE) - {ESPIPE, "ESPIPE", "Illegal seek"}, + ENTRY(ESPIPE, "ESPIPE", "Illegal seek"), #endif #if defined (EROFS) - {EROFS, "EROFS", "Read-only file system"}, + ENTRY(EROFS, "EROFS", "Read-only file system"), #endif #if defined (EMLINK) - {EMLINK, "EMLINK", "Too many links"}, + ENTRY(EMLINK, "EMLINK", "Too many links"), #endif #if defined (EPIPE) - {EPIPE, "EPIPE", "Broken pipe"}, + ENTRY(EPIPE, "EPIPE", "Broken pipe"), #endif #if defined (EDOM) - {EDOM, "EDOM", "Math argument out of domain of func"}, + ENTRY(EDOM, "EDOM", "Math argument out of domain of func"), #endif #if defined (ERANGE) - {ERANGE, "ERANGE", "Math result not representable"}, + ENTRY(ERANGE, "ERANGE", "Math result not representable"), #endif #if defined (ENOMSG) - {ENOMSG, "ENOMSG", "No message of desired type"}, + ENTRY(ENOMSG, "ENOMSG", "No message of desired type"), #endif #if defined (EIDRM) - {EIDRM, "EIDRM", "Identifier removed"}, + ENTRY(EIDRM, "EIDRM", "Identifier removed"), #endif #if defined (ECHRNG) - {ECHRNG, "ECHRNG", "Channel number out of range"}, + ENTRY(ECHRNG, "ECHRNG", "Channel number out of range"), #endif #if defined (EL2NSYNC) - {EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"}, + ENTRY(EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"), #endif #if defined (EL3HLT) - {EL3HLT, "EL3HLT", "Level 3 halted"}, + ENTRY(EL3HLT, "EL3HLT", "Level 3 halted"), #endif #if defined (EL3RST) - {EL3RST, "EL3RST", "Level 3 reset"}, + ENTRY(EL3RST, "EL3RST", "Level 3 reset"), #endif #if defined (ELNRNG) - {ELNRNG, "ELNRNG", "Link number out of range"}, + ENTRY(ELNRNG, "ELNRNG", "Link number out of range"), #endif #if defined (EUNATCH) - {EUNATCH, "EUNATCH", "Protocol driver not attached"}, + ENTRY(EUNATCH, "EUNATCH", "Protocol driver not attached"), #endif #if defined (ENOCSI) - {ENOCSI, "ENOCSI", "No CSI structure available"}, + ENTRY(ENOCSI, "ENOCSI", "No CSI structure available"), #endif #if defined (EL2HLT) - {EL2HLT, "EL2HLT", "Level 2 halted"}, + ENTRY(EL2HLT, "EL2HLT", "Level 2 halted"), #endif #if defined (EDEADLK) - {EDEADLK, "EDEADLK", "Deadlock condition"}, + ENTRY(EDEADLK, "EDEADLK", "Deadlock condition"), #endif #if defined (ENOLCK) - {ENOLCK, "ENOLCK", "No record locks available"}, + ENTRY(ENOLCK, "ENOLCK", "No record locks available"), #endif #if defined (EBADE) - {EBADE, "EBADE", "Invalid exchange"}, + ENTRY(EBADE, "EBADE", "Invalid exchange"), #endif #if defined (EBADR) - {EBADR, "EBADR", "Invalid request descriptor"}, + ENTRY(EBADR, "EBADR", "Invalid request descriptor"), #endif #if defined (EXFULL) - {EXFULL, "EXFULL", "Exchange full"}, + ENTRY(EXFULL, "EXFULL", "Exchange full"), #endif #if defined (ENOANO) - {ENOANO, "ENOANO", "No anode"}, + ENTRY(ENOANO, "ENOANO", "No anode"), #endif #if defined (EBADRQC) - {EBADRQC, "EBADRQC", "Invalid request code"}, + ENTRY(EBADRQC, "EBADRQC", "Invalid request code"), #endif #if defined (EBADSLT) - {EBADSLT, "EBADSLT", "Invalid slot"}, + ENTRY(EBADSLT, "EBADSLT", "Invalid slot"), #endif #if defined (EDEADLOCK) - {EDEADLOCK, "EDEADLOCK", "File locking deadlock error"}, + ENTRY(EDEADLOCK, "EDEADLOCK", "File locking deadlock error"), #endif #if defined (EBFONT) - {EBFONT, "EBFONT", "Bad font file format"}, + ENTRY(EBFONT, "EBFONT", "Bad font file format"), #endif #if defined (ENOSTR) - {ENOSTR, "ENOSTR", "Device not a stream"}, + ENTRY(ENOSTR, "ENOSTR", "Device not a stream"), #endif #if defined (ENODATA) - {ENODATA, "ENODATA", "No data available"}, + ENTRY(ENODATA, "ENODATA", "No data available"), #endif #if defined (ETIME) - {ETIME, "ETIME", "Timer expired"}, + ENTRY(ETIME, "ETIME", "Timer expired"), #endif #if defined (ENOSR) - {ENOSR, "ENOSR", "Out of streams resources"}, + ENTRY(ENOSR, "ENOSR", "Out of streams resources"), #endif #if defined (ENONET) - {ENONET, "ENONET", "Machine is not on the network"}, + ENTRY(ENONET, "ENONET", "Machine is not on the network"), #endif #if defined (ENOPKG) - {ENOPKG, "ENOPKG", "Package not installed"}, + ENTRY(ENOPKG, "ENOPKG", "Package not installed"), #endif #if defined (EREMOTE) - {EREMOTE, "EREMOTE", "Object is remote"}, + ENTRY(EREMOTE, "EREMOTE", "Object is remote"), #endif #if defined (ENOLINK) - {ENOLINK, "ENOLINK", "Link has been severed"}, + ENTRY(ENOLINK, "ENOLINK", "Link has been severed"), #endif #if defined (EADV) - {EADV, "EADV", "Advertise error"}, + ENTRY(EADV, "EADV", "Advertise error"), #endif #if defined (ESRMNT) - {ESRMNT, "ESRMNT", "Srmount error"}, + ENTRY(ESRMNT, "ESRMNT", "Srmount error"), #endif #if defined (ECOMM) - {ECOMM, "ECOMM", "Communication error on send"}, + ENTRY(ECOMM, "ECOMM", "Communication error on send"), #endif #if defined (EPROTO) - {EPROTO, "EPROTO", "Protocol error"}, + ENTRY(EPROTO, "EPROTO", "Protocol error"), #endif #if defined (EMULTIHOP) - {EMULTIHOP, "EMULTIHOP", "Multihop attempted"}, + ENTRY(EMULTIHOP, "EMULTIHOP", "Multihop attempted"), #endif #if defined (EDOTDOT) - {EDOTDOT, "EDOTDOT", "RFS specific error"}, + ENTRY(EDOTDOT, "EDOTDOT", "RFS specific error"), #endif #if defined (EBADMSG) - {EBADMSG, "EBADMSG", "Not a data message"}, + ENTRY(EBADMSG, "EBADMSG", "Not a data message"), #endif #if defined (ENAMETOOLONG) - {ENAMETOOLONG, "ENAMETOOLONG", "File name too long"}, + ENTRY(ENAMETOOLONG, "ENAMETOOLONG", "File name too long"), #endif #if defined (EOVERFLOW) - {EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"}, + ENTRY(EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"), #endif #if defined (ENOTUNIQ) - {ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"}, + ENTRY(ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"), #endif #if defined (EBADFD) - {EBADFD, "EBADFD", "File descriptor in bad state"}, + ENTRY(EBADFD, "EBADFD", "File descriptor in bad state"), #endif #if defined (EREMCHG) - {EREMCHG, "EREMCHG", "Remote address changed"}, + ENTRY(EREMCHG, "EREMCHG", "Remote address changed"), #endif #if defined (ELIBACC) - {ELIBACC, "ELIBACC", "Can not access a needed shared library"}, + ENTRY(ELIBACC, "ELIBACC", "Can not access a needed shared library"), #endif #if defined (ELIBBAD) - {ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"}, + ENTRY(ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"), #endif #if defined (ELIBSCN) - {ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"}, + ENTRY(ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"), #endif #if defined (ELIBMAX) - {ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"}, + ENTRY(ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"), #endif #if defined (ELIBEXEC) - {ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"}, + ENTRY(ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"), #endif #if defined (EILSEQ) - {EILSEQ, "EILSEQ", "Illegal byte sequence"}, + ENTRY(EILSEQ, "EILSEQ", "Illegal byte sequence"), #endif #if defined (ENOSYS) - {ENOSYS, "ENOSYS", "Operation not applicable"}, + ENTRY(ENOSYS, "ENOSYS", "Operation not applicable"), #endif #if defined (ELOOP) - {ELOOP, "ELOOP", "Too many symbolic links encountered"}, + ENTRY(ELOOP, "ELOOP", "Too many symbolic links encountered"), #endif #if defined (ERESTART) - {ERESTART, "ERESTART", "Interrupted system call should be restarted"}, + ENTRY(ERESTART, "ERESTART", "Interrupted system call should be restarted"), #endif #if defined (ESTRPIPE) - {ESTRPIPE, "ESTRPIPE", "Streams pipe error"}, + ENTRY(ESTRPIPE, "ESTRPIPE", "Streams pipe error"), #endif #if defined (ENOTEMPTY) - {ENOTEMPTY, "ENOTEMPTY", "Directory not empty"}, + ENTRY(ENOTEMPTY, "ENOTEMPTY", "Directory not empty"), #endif #if defined (EUSERS) - {EUSERS, "EUSERS", "Too many users"}, + ENTRY(EUSERS, "EUSERS", "Too many users"), #endif #if defined (ENOTSOCK) - {ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"}, + ENTRY(ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"), #endif #if defined (EDESTADDRREQ) - {EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"}, + ENTRY(EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"), #endif #if defined (EMSGSIZE) - {EMSGSIZE, "EMSGSIZE", "Message too long"}, + ENTRY(EMSGSIZE, "EMSGSIZE", "Message too long"), #endif #if defined (EPROTOTYPE) - {EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"}, + ENTRY(EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"), #endif #if defined (ENOPROTOOPT) - {ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"}, + ENTRY(ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"), #endif #if defined (EPROTONOSUPPORT) - {EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"}, + ENTRY(EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"), #endif #if defined (ESOCKTNOSUPPORT) - {ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"}, + ENTRY(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"), #endif #if defined (EOPNOTSUPP) - {EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"}, + ENTRY(EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"), #endif #if defined (EPFNOSUPPORT) - {EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"}, + ENTRY(EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"), #endif #if defined (EAFNOSUPPORT) - {EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"}, + ENTRY(EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"), #endif #if defined (EADDRINUSE) - {EADDRINUSE, "EADDRINUSE", "Address already in use"}, + ENTRY(EADDRINUSE, "EADDRINUSE", "Address already in use"), #endif #if defined (EADDRNOTAVAIL) - {EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"}, + ENTRY(EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"), #endif #if defined (ENETDOWN) - {ENETDOWN, "ENETDOWN", "Network is down"}, + ENTRY(ENETDOWN, "ENETDOWN", "Network is down"), #endif #if defined (ENETUNREACH) - {ENETUNREACH, "ENETUNREACH", "Network is unreachable"}, + ENTRY(ENETUNREACH, "ENETUNREACH", "Network is unreachable"), #endif #if defined (ENETRESET) - {ENETRESET, "ENETRESET", "Network dropped connection because of reset"}, + ENTRY(ENETRESET, "ENETRESET", "Network dropped connection because of reset"), #endif #if defined (ECONNABORTED) - {ECONNABORTED, "ECONNABORTED", "Software caused connection abort"}, + ENTRY(ECONNABORTED, "ECONNABORTED", "Software caused connection abort"), #endif #if defined (ECONNRESET) - {ECONNRESET, "ECONNRESET", "Connection reset by peer"}, + ENTRY(ECONNRESET, "ECONNRESET", "Connection reset by peer"), #endif #if defined (ENOBUFS) - {ENOBUFS, "ENOBUFS", "No buffer space available"}, + ENTRY(ENOBUFS, "ENOBUFS", "No buffer space available"), #endif #if defined (EISCONN) - {EISCONN, "EISCONN", "Transport endpoint is already connected"}, + ENTRY(EISCONN, "EISCONN", "Transport endpoint is already connected"), #endif #if defined (ENOTCONN) - {ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"}, + ENTRY(ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"), #endif #if defined (ESHUTDOWN) - {ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"}, + ENTRY(ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"), #endif #if defined (ETOOMANYREFS) - {ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"}, + ENTRY(ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"), #endif #if defined (ETIMEDOUT) - {ETIMEDOUT, "ETIMEDOUT", "Connection timed out"}, + ENTRY(ETIMEDOUT, "ETIMEDOUT", "Connection timed out"), #endif #if defined (ECONNREFUSED) - {ECONNREFUSED, "ECONNREFUSED", "Connection refused"}, + ENTRY(ECONNREFUSED, "ECONNREFUSED", "Connection refused"), #endif #if defined (EHOSTDOWN) - {EHOSTDOWN, "EHOSTDOWN", "Host is down"}, + ENTRY(EHOSTDOWN, "EHOSTDOWN", "Host is down"), #endif #if defined (EHOSTUNREACH) - {EHOSTUNREACH, "EHOSTUNREACH", "No route to host"}, + ENTRY(EHOSTUNREACH, "EHOSTUNREACH", "No route to host"), #endif #if defined (EALREADY) - {EALREADY, "EALREADY", "Operation already in progress"}, + ENTRY(EALREADY, "EALREADY", "Operation already in progress"), #endif #if defined (EINPROGRESS) - {EINPROGRESS, "EINPROGRESS", "Operation now in progress"}, + ENTRY(EINPROGRESS, "EINPROGRESS", "Operation now in progress"), #endif #if defined (ESTALE) - {ESTALE, "ESTALE", "Stale NFS file handle"}, + ENTRY(ESTALE, "ESTALE", "Stale NFS file handle"), #endif #if defined (EUCLEAN) - {EUCLEAN, "EUCLEAN", "Structure needs cleaning"}, + ENTRY(EUCLEAN, "EUCLEAN", "Structure needs cleaning"), #endif #if defined (ENOTNAM) - {ENOTNAM, "ENOTNAM", "Not a XENIX named type file"}, + ENTRY(ENOTNAM, "ENOTNAM", "Not a XENIX named type file"), #endif #if defined (ENAVAIL) - {ENAVAIL, "ENAVAIL", "No XENIX semaphores available"}, + ENTRY(ENAVAIL, "ENAVAIL", "No XENIX semaphores available"), #endif #if defined (EISNAM) - {EISNAM, "EISNAM", "Is a named type file"}, + ENTRY(EISNAM, "EISNAM", "Is a named type file"), #endif #if defined (EREMOTEIO) - {EREMOTEIO, "EREMOTEIO", "Remote I/O error"}, + ENTRY(EREMOTEIO, "EREMOTEIO", "Remote I/O error"), #endif - {0, NULL, NULL} + ENTRY(0, NULL, NULL) }; /* Translation table allocated and initialized at runtime. Indexed by the errno value to find the equivalent symbolic value. */ -static char **error_names; +static const char **error_names; static int num_error_names = 0; /* Translation table allocated and initialized at runtime, if it does not @@ -457,7 +465,7 @@ static int num_error_names = 0; #ifdef NEED_sys_errlist static int sys_nerr; -static char **sys_errlist; +static const char **sys_errlist; #else @@ -521,7 +529,7 @@ init_error_tables () if (error_names == NULL) { nbytes = num_error_names * sizeof (char *); - if ((error_names = (char **) malloc (nbytes)) != NULL) + if ((error_names = (const char **) malloc (nbytes)) != NULL) { memset (error_names, 0, nbytes); for (eip = error_table; eip -> name != NULL; eip++) @@ -539,7 +547,7 @@ init_error_tables () if (sys_errlist == NULL) { nbytes = num_error_names * sizeof (char *); - if ((sys_errlist = (char **) malloc (nbytes)) != NULL) + if ((sys_errlist = (const char **) malloc (nbytes)) != NULL) { memset (sys_errlist, 0, nbytes); sys_nerr = num_error_names; @@ -656,7 +664,7 @@ strerror (errnoval) else { /* In range, and a valid message. Just return the message. */ - msg = sys_errlist[errnoval]; + msg = (char *) sys_errlist[errnoval]; } return (msg); @@ -673,7 +681,7 @@ NAME SYNOPSIS - char *strerrno (int errnoval) + const char *strerrno (int errnoval) DESCRIPTION @@ -696,11 +704,11 @@ BUGS */ -char * +const char * strerrno (errnoval) int errnoval; { - char *name; + const char *name; static char buf[32]; if (error_names == NULL) @@ -717,7 +725,7 @@ strerrno (errnoval) { /* In range, but no error_names or no entry at this index. */ sprintf (buf, "Error %d", errnoval); - name = buf; + name = (const char *) buf; } else { @@ -747,7 +755,7 @@ DESCRIPTION int strtoerrno (name) - char *name; + const char *name; { int errnoval = 0; @@ -779,13 +787,15 @@ strtoerrno (name) #ifdef MAIN +#include + +int main () { int errn; int errnmax; - char *name; + const char *name; char *msg; - char *strerrno (); char *strerror (); errnmax = errno_max (); @@ -806,6 +816,8 @@ main () msg = (msg == NULL) ? "" : msg; printf ("%-4d%-18s%s\n", errn, name, msg); } + + return 0; } #endif diff --git a/gnu/usr.bin/gdb/libiberty/strsignal.c b/gnu/usr.bin/gdb/libiberty/strsignal.c index 15411ff496c6..7acb733bd56f 100644 --- a/gnu/usr.bin/gdb/libiberty/strsignal.c +++ b/gnu/usr.bin/gdb/libiberty/strsignal.c @@ -18,7 +18,8 @@ License along with libiberty; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include +#include "ansidecl.h" +#include "libiberty.h" #include "config.h" @@ -36,9 +37,6 @@ Cambridge, MA 02139, USA. */ extern void *malloc (size_t size); /* 4.10.3.3 */ extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */ #else /* !__STDC__ */ -#ifndef const -#define const -#endif extern char *malloc (); /* Standard memory allocater */ extern char *memset (); #endif /* __STDC__ */ @@ -73,161 +71,169 @@ extern char *memset (); struct signal_info { int value; /* The numeric value from */ - char *name; /* The equivalent symbolic value */ - char *msg; /* Short message about this value */ + const char *name; /* The equivalent symbolic value */ +#ifdef NEED_sys_siglist + const char *msg; /* Short message about this value */ +#endif }; +#ifdef NEED_sys_siglist +# define ENTRY(value, name, msg) {value, name, msg} +#else +# define ENTRY(value, name, msg) {value, name} +#endif + static const struct signal_info signal_table[] = { #if defined (SIGHUP) - {SIGHUP, "SIGHUP", "Hangup"}, + ENTRY(SIGHUP, "SIGHUP", "Hangup"), #endif #if defined (SIGINT) - {SIGINT, "SIGINT", "Interrupt"}, + ENTRY(SIGINT, "SIGINT", "Interrupt"), #endif #if defined (SIGQUIT) - {SIGQUIT, "SIGQUIT", "Quit"}, + ENTRY(SIGQUIT, "SIGQUIT", "Quit"), #endif #if defined (SIGILL) - {SIGILL, "SIGILL", "Illegal instruction"}, + ENTRY(SIGILL, "SIGILL", "Illegal instruction"), #endif #if defined (SIGTRAP) - {SIGTRAP, "SIGTRAP", "Trace/breakpoint trap"}, + ENTRY(SIGTRAP, "SIGTRAP", "Trace/breakpoint trap"), #endif /* Put SIGIOT before SIGABRT, so that if SIGIOT==SIGABRT then SIGABRT overrides SIGIOT. SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. */ #if defined (SIGIOT) - {SIGIOT, "SIGIOT", "IOT trap"}, + ENTRY(SIGIOT, "SIGIOT", "IOT trap"), #endif #if defined (SIGABRT) - {SIGABRT, "SIGABRT", "Aborted"}, + ENTRY(SIGABRT, "SIGABRT", "Aborted"), #endif #if defined (SIGEMT) - {SIGEMT, "SIGEMT", "Emulation trap"}, + ENTRY(SIGEMT, "SIGEMT", "Emulation trap"), #endif #if defined (SIGFPE) - {SIGFPE, "SIGFPE", "Arithmetic exception"}, + ENTRY(SIGFPE, "SIGFPE", "Arithmetic exception"), #endif #if defined (SIGKILL) - {SIGKILL, "SIGKILL", "Killed"}, + ENTRY(SIGKILL, "SIGKILL", "Killed"), #endif #if defined (SIGBUS) - {SIGBUS, "SIGBUS", "Bus error"}, + ENTRY(SIGBUS, "SIGBUS", "Bus error"), #endif #if defined (SIGSEGV) - {SIGSEGV, "SIGSEGV", "Segmentation fault"}, + ENTRY(SIGSEGV, "SIGSEGV", "Segmentation fault"), #endif #if defined (SIGSYS) - {SIGSYS, "SIGSYS", "Bad system call"}, + ENTRY(SIGSYS, "SIGSYS", "Bad system call"), #endif #if defined (SIGPIPE) - {SIGPIPE, "SIGPIPE", "Broken pipe"}, + ENTRY(SIGPIPE, "SIGPIPE", "Broken pipe"), #endif #if defined (SIGALRM) - {SIGALRM, "SIGALRM", "Alarm clock"}, + ENTRY(SIGALRM, "SIGALRM", "Alarm clock"), #endif #if defined (SIGTERM) - {SIGTERM, "SIGTERM", "Terminated"}, + ENTRY(SIGTERM, "SIGTERM", "Terminated"), #endif #if defined (SIGUSR1) - {SIGUSR1, "SIGUSR1", "User defined signal 1"}, + ENTRY(SIGUSR1, "SIGUSR1", "User defined signal 1"), #endif #if defined (SIGUSR2) - {SIGUSR2, "SIGUSR2", "User defined signal 2"}, + ENTRY(SIGUSR2, "SIGUSR2", "User defined signal 2"), #endif /* Put SIGCLD before SIGCHLD, so that if SIGCLD==SIGCHLD then SIGCHLD overrides SIGCLD. SIGCHLD is in POXIX.1 */ #if defined (SIGCLD) - {SIGCLD, "SIGCLD", "Child status changed"}, + ENTRY(SIGCLD, "SIGCLD", "Child status changed"), #endif #if defined (SIGCHLD) - {SIGCHLD, "SIGCHLD", "Child status changed"}, + ENTRY(SIGCHLD, "SIGCHLD", "Child status changed"), #endif #if defined (SIGPWR) - {SIGPWR, "SIGPWR", "Power fail/restart"}, + ENTRY(SIGPWR, "SIGPWR", "Power fail/restart"), #endif #if defined (SIGWINCH) - {SIGWINCH, "SIGWINCH", "Window size changed"}, + ENTRY(SIGWINCH, "SIGWINCH", "Window size changed"), #endif #if defined (SIGURG) - {SIGURG, "SIGURG", "Urgent I/O condition"}, + ENTRY(SIGURG, "SIGURG", "Urgent I/O condition"), #endif #if defined (SIGIO) /* "I/O pending" has also been suggested, but is misleading since the signal only happens when the process has asked for it, not everytime I/O is pending. */ - {SIGIO, "SIGIO", "I/O possible"}, + ENTRY(SIGIO, "SIGIO", "I/O possible"), #endif #if defined (SIGPOLL) - {SIGPOLL, "SIGPOLL", "Pollable event occurred"}, + ENTRY(SIGPOLL, "SIGPOLL", "Pollable event occurred"), #endif #if defined (SIGSTOP) - {SIGSTOP, "SIGSTOP", "Stopped (signal)"}, + ENTRY(SIGSTOP, "SIGSTOP", "Stopped (signal)"), #endif #if defined (SIGTSTP) - {SIGTSTP, "SIGTSTP", "Stopped (user)"}, + ENTRY(SIGTSTP, "SIGTSTP", "Stopped (user)"), #endif #if defined (SIGCONT) - {SIGCONT, "SIGCONT", "Continued"}, + ENTRY(SIGCONT, "SIGCONT", "Continued"), #endif #if defined (SIGTTIN) - {SIGTTIN, "SIGTTIN", "Stopped (tty input)"}, + ENTRY(SIGTTIN, "SIGTTIN", "Stopped (tty input)"), #endif #if defined (SIGTTOU) - {SIGTTOU, "SIGTTOU", "Stopped (tty output)"}, + ENTRY(SIGTTOU, "SIGTTOU", "Stopped (tty output)"), #endif #if defined (SIGVTALRM) - {SIGVTALRM, "SIGVTALRM", "Virtual timer expired"}, + ENTRY(SIGVTALRM, "SIGVTALRM", "Virtual timer expired"), #endif #if defined (SIGPROF) - {SIGPROF, "SIGPROF", "Profiling timer expired"}, + ENTRY(SIGPROF, "SIGPROF", "Profiling timer expired"), #endif #if defined (SIGXCPU) - {SIGXCPU, "SIGXCPU", "CPU time limit exceeded"}, + ENTRY(SIGXCPU, "SIGXCPU", "CPU time limit exceeded"), #endif #if defined (SIGXFSZ) - {SIGXFSZ, "SIGXFSZ", "File size limit exceeded"}, + ENTRY(SIGXFSZ, "SIGXFSZ", "File size limit exceeded"), #endif #if defined (SIGWIND) - {SIGWIND, "SIGWIND", "SIGWIND"}, + ENTRY(SIGWIND, "SIGWIND", "SIGWIND"), #endif #if defined (SIGPHONE) - {SIGPHONE, "SIGPHONE", "SIGPHONE"}, + ENTRY(SIGPHONE, "SIGPHONE", "SIGPHONE"), #endif #if defined (SIGLOST) - {SIGLOST, "SIGLOST", "Resource lost"}, + ENTRY(SIGLOST, "SIGLOST", "Resource lost"), #endif #if defined (SIGWAITING) - {SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"}, + ENTRY(SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"), #endif #if defined (SIGLWP) - {SIGLWP, "SIGLWP", "Signal LWP"}, + ENTRY(SIGLWP, "SIGLWP", "Signal LWP"), #endif #if defined (SIGDANGER) - {SIGDANGER, "SIGDANGER", "Swap space dangerously low"}, + ENTRY(SIGDANGER, "SIGDANGER", "Swap space dangerously low"), #endif #if defined (SIGGRANT) - {SIGGRANT, "SIGGRANT", "Monitor mode granted"}, + ENTRY(SIGGRANT, "SIGGRANT", "Monitor mode granted"), #endif #if defined (SIGRETRACT) - {SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"}, + ENTRY(SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"), #endif #if defined (SIGMSG) - {SIGMSG, "SIGMSG", "Monitor mode data available"}, + ENTRY(SIGMSG, "SIGMSG", "Monitor mode data available"), #endif #if defined (SIGSOUND) - {SIGSOUND, "SIGSOUND", "Sound completed"}, + ENTRY(SIGSOUND, "SIGSOUND", "Sound completed"), #endif #if defined (SIGSAK) - {SIGSAK, "SIGSAK", "Secure attention"}, + ENTRY(SIGSAK, "SIGSAK", "Secure attention"), #endif - {0, NULL, NULL} + ENTRY(0, NULL, NULL) }; /* Translation table allocated and initialized at runtime. Indexed by the signal value to find the equivalent symbolic value. */ -static char **signal_names; +static const char **signal_names; static int num_signal_names = 0; /* Translation table allocated and initialized at runtime, if it does not @@ -241,7 +247,7 @@ static int num_signal_names = 0; #ifdef NEED_sys_siglist static int sys_nsig; -static char **sys_siglist; +static const char **sys_siglist; #else @@ -305,7 +311,7 @@ init_signal_tables () if (signal_names == NULL) { nbytes = num_signal_names * sizeof (char *); - if ((signal_names = (char **) malloc (nbytes)) != NULL) + if ((signal_names = (const char **) malloc (nbytes)) != NULL) { memset (signal_names, 0, nbytes); for (eip = signal_table; eip -> name != NULL; eip++) @@ -323,7 +329,7 @@ init_signal_tables () if (sys_siglist == NULL) { nbytes = num_signal_names * sizeof (char *); - if ((sys_siglist = (char **) malloc (nbytes)) != NULL) + if ((sys_siglist = (const char **) malloc (nbytes)) != NULL) { memset (sys_siglist, 0, nbytes); sys_nsig = num_signal_names; @@ -388,7 +394,7 @@ NAME SYNOPSIS - char *strsignal (int signo) + const char *strsignal (int signo) DESCRIPTION @@ -410,11 +416,11 @@ DESCRIPTION */ -char * +const char * strsignal (signo) int signo; { - char *msg; + const char *msg; static char buf[32]; #ifdef NEED_sys_siglist @@ -435,12 +441,12 @@ strsignal (signo) { /* In range, but no sys_siglist or no entry at this index. */ sprintf (buf, "Signal %d", signo); - msg = buf; + msg = (const char *) buf; } else { /* In range, and a valid message. Just return the message. */ - msg = (char*)sys_siglist[signo]; + msg = (const char *) sys_siglist[signo]; } return (msg); @@ -455,7 +461,7 @@ NAME SYNOPSIS - char *strsigno (int signo) + const char *strsigno (int signo) DESCRIPTION @@ -477,11 +483,11 @@ BUGS */ -char * +const char * strsigno (signo) int signo; { - char *name; + const char *name; static char buf[32]; if (signal_names == NULL) @@ -498,7 +504,7 @@ strsigno (signo) { /* In range, but no signal_names or no entry at this index. */ sprintf (buf, "Signal %d", signo); - name = buf; + name = (const char *) buf; } else { @@ -529,7 +535,7 @@ DESCRIPTION int strtosigno (name) - char *name; + const char *name; { int signo = 0; @@ -602,14 +608,15 @@ psignal (signo, message) #ifdef MAIN +#include + +int main () { int signo; int maxsigno; - char *name; - char *msg; - char *strsigno (); - char *strsignal (); + const char *name; + const char *msg; maxsigno = signo_max (); printf ("%d entries in names table.\n", num_signal_names); @@ -629,6 +636,8 @@ main () msg = (msg == NULL) ? "" : msg; printf ("%-4d%-18s%s\n", signo, name, msg); } + + return 0; } #endif diff --git a/gnu/usr.bin/gdb/libiberty/xmalloc.c b/gnu/usr.bin/gdb/libiberty/xmalloc.c index be0c7aa9319c..b15b27c6c36f 100644 --- a/gnu/usr.bin/gdb/libiberty/xmalloc.c +++ b/gnu/usr.bin/gdb/libiberty/xmalloc.c @@ -1,5 +1,5 @@ /* memory allocation routines with error checking. - Copyright 1989, 1991, 1993 Free Software Foundation, Inc. + Copyright 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc. This file is part of the libiberty library. Libiberty is free software; you can redistribute it and/or @@ -17,7 +17,8 @@ License along with libiberty; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include +#include "ansidecl.h" +#include "libiberty.h" #include @@ -27,17 +28,35 @@ Cambridge, MA 02139, USA. */ #define size_t unsigned long #endif +/* For systems with larger pointers than ints, these must be declared. */ +PTR malloc PARAMS ((size_t)); +PTR realloc PARAMS ((PTR, size_t)); + +/* The program name if set. */ +static const char *name = ""; + +void +xmalloc_set_program_name (s) + const char *s; +{ + name = s; +} PTR xmalloc (size) size_t size; { - char * newmem; + PTR newmem; - if ((newmem = (char *) malloc ((int) size)) == NULL) + if (size == 0) + size = 1; + newmem = malloc (size); + if (!newmem) { - fprintf (stderr, "\nCan't allocate %u bytes\n", size); - exit (1); + fprintf (stderr, "\n%s%sCan not allocate %lu bytes\n", + name, *name ? ": " : "", + (unsigned long) size); + xexit (1); } return (newmem); } @@ -47,12 +66,20 @@ xrealloc (oldmem, size) PTR oldmem; size_t size; { - char * newmem; + PTR newmem; - if ((newmem = (char *) realloc ((char *) oldmem, (int) size)) == NULL) + if (size == 0) + size = 1; + if (!oldmem) + newmem = malloc (size); + else + newmem = realloc (oldmem, size); + if (!newmem) { - fprintf (stderr, "\nCan't reallocate %u bytes\n", size); - exit (1); + fprintf (stderr, "\n%s%sCan not reallocate %lu bytes\n", + name, *name ? ": " : "", + (unsigned long) size); + xexit (1); } return (newmem); } diff --git a/gnu/usr.bin/gdb/mmalloc/README.FreeBSD b/gnu/usr.bin/gdb/mmalloc/README.FreeBSD index 338400ffa885..544755a16027 100644 --- a/gnu/usr.bin/gdb/mmalloc/README.FreeBSD +++ b/gnu/usr.bin/gdb/mmalloc/README.FreeBSD @@ -1,7 +1,4 @@ This is a greatly pared down libmmalloc directory. Only what's required to build -gdb-4.12 on FreeBSD was kept. +gdb-4.13 on FreeBSD 2.0 was kept. -This is temporary. In FreeBSD 2.0 a fully ported libmmalloc will likely appear -as a system library for use by all the build tools. - -paul@freefall.cdrom.com +gj@freebsd.org diff --git a/gnu/usr.bin/gdb/mmalloc/mmtrace.c b/gnu/usr.bin/gdb/mmalloc/mmtrace.c index 73368a1b57aa..aca3508c026e 100644 --- a/gnu/usr.bin/gdb/mmalloc/mmtrace.c +++ b/gnu/usr.bin/gdb/mmalloc/mmtrace.c @@ -1,5 +1,5 @@ /* More debugging hooks for `mmalloc'. - Copyright 1991, 1992 Free Software Foundation + Copyright 1991, 1992, 1994 Free Software Foundation Written April 2, 1991 by John Gilmore of Cygnus Support Based on mcheck.c by Mike Haertel. @@ -64,7 +64,7 @@ tr_freehook (md, ptr) mdp = MD_TO_MDP (md); /* Be sure to print it first. */ - fprintf (mallstream, "- %08x\n", (unsigned int) ptr); + fprintf (mallstream, "- %08lx\n", (unsigned long) ptr); if (ptr == mallwatch) tr_break (); mdp -> mfree_hook = old_mfree_hook; @@ -86,7 +86,7 @@ tr_mallochook (md, size) mdp -> mmalloc_hook = tr_mallochook; /* We could be printing a NULL here; that's OK. */ - fprintf (mallstream, "+ %08x %x\n", (unsigned int) hdr, size); + fprintf (mallstream, "+ %08lx %x\n", (unsigned long) hdr, size); if (hdr == mallwatch) tr_break (); @@ -117,10 +117,10 @@ tr_reallochook (md, ptr, size) mdp -> mrealloc_hook = tr_reallochook; if (hdr == NULL) /* Failed realloc. */ - fprintf (mallstream, "! %08x %x\n", (unsigned int) ptr, size); + fprintf (mallstream, "! %08lx %x\n", (unsigned long) ptr, size); else - fprintf (mallstream, "< %08x\n> %08x %x\n", (unsigned int) ptr, - (unsigned int) hdr, size); + fprintf (mallstream, "< %08lx\n> %08lx %x\n", (unsigned long) ptr, + (unsigned long) hdr, size); if (hdr == mallwatch) tr_break ();